You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by gp...@apache.org on 2012/07/07 22:15:44 UTC

git commit: DELTASPIKE-222 prototype of a type-safe message-source

Updated Branches:
  refs/heads/master 0bf3cd8ee -> d4db08916


DELTASPIKE-222 prototype of a type-safe message-source

 allows the type-safe usage with @MessageContextConfig and the fluent MessageContext api
 (and to implement fine-grained message-interfaces which use the same message-source)


Project: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/commit/d4db0891
Tree: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/tree/d4db0891
Diff: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/diff/d4db0891

Branch: refs/heads/master
Commit: d4db089160f1699c785ffa87d452dd9daee1b33a
Parents: 0bf3cd8
Author: gpetracek <gp...@apache.org>
Authored: Sat Jul 7 22:08:01 2012 +0200
Committer: gpetracek <gp...@apache.org>
Committed: Sat Jul 7 22:14:59 2012 +0200

----------------------------------------------------------------------
 .../api/literal/MessageContextConfigLiteral.java   |   14 +++-
 .../core/api/message/MessageContext.java           |   20 ++++--
 .../core/api/message/MessageResolver.java          |    1 -
 .../deltaspike/core/api/message/MessageSource.java |   54 +++++++++++++++
 .../message/annotation/MessageContextConfig.java   |    7 ++
 .../core/impl/message/DefaultMessageContext.java   |   42 +++++++++---
 .../core/impl/message/DefaultMessageResolver.java  |   38 +++++++---
 .../message/MessageBundleInvocationHandler.java    |   35 ++++++++--
 .../core/api/message/CustomMinimalMessages.java    |   32 +++++++++
 .../test/core/api/message/MessageContextTest.java  |    8 ++-
 .../test/core/api/message/MinimalMessagesTest.java |    9 +++
 .../api/message/source/InvalidMessageSource.java   |   35 +++++++++
 .../api/message/source/MinimalMessageSource.java   |   36 ++++++++++
 13 files changed, 291 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageContextConfigLiteral.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageContextConfigLiteral.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageContextConfigLiteral.java
index 9eba8f0..8d0165b 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageContextConfigLiteral.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageContextConfigLiteral.java
@@ -19,6 +19,7 @@
 package org.apache.deltaspike.core.api.literal;
 
 import org.apache.deltaspike.core.api.message.LocaleResolver;
+import org.apache.deltaspike.core.api.message.MessageSource;
 import org.apache.deltaspike.core.api.message.annotation.MessageContextConfig;
 import org.apache.deltaspike.core.api.message.MessageInterpolator;
 import org.apache.deltaspike.core.api.message.MessageResolver;
@@ -35,19 +36,28 @@ public class MessageContextConfigLiteral extends AnnotationLiteral<MessageContex
     private final Class<? extends MessageResolver> messageResolver;
     private final Class<? extends MessageInterpolator> messageInterpolator;
     private final Class<? extends LocaleResolver> localeResolver;
+    private final Class<? extends MessageSource>[] messageSource;
 
     public MessageContextConfigLiteral()
     {
-        this(MessageResolver.class, MessageInterpolator.class, LocaleResolver.class);
+        this(MessageResolver.class, MessageInterpolator.class, LocaleResolver.class, MessageSource.class);
     }
 
     public MessageContextConfigLiteral(Class<? extends MessageResolver> messageResolver,
                                        Class<? extends MessageInterpolator> messageInterpolator,
-                                       Class<? extends LocaleResolver> localeResolver)
+                                       Class<? extends LocaleResolver> localeResolver,
+                                       Class<? extends MessageSource>... messageSource)
     {
         this.messageResolver = messageResolver;
         this.messageInterpolator = messageInterpolator;
         this.localeResolver = localeResolver;
+        this.messageSource = messageSource;
+    }
+
+    @Override
+    public Class<? extends MessageSource>[] messageSource()
+    {
+        return this.messageSource;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageContext.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageContext.java
index 8225fea..00712ff 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageContext.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageContext.java
@@ -19,6 +19,7 @@
 package org.apache.deltaspike.core.api.message;
 
 import java.io.Serializable;
+import java.util.List;
 
 /**
  * Central context for handling dynamic messages.
@@ -38,16 +39,19 @@ public interface MessageContext extends LocaleResolver, Serializable, Cloneable
     Message message();
 
     /**
-     * @param messageBundleName a name of the message bundle which should be used
+     * Allows to add a message-source instance which can be used by a {@link MessageResolver}
+     * @param messageSource message-source to add
      * @return the instance of the current message context builder
      */
-    MessageContext bundle(String messageBundleName);
+    MessageContext messageSource(MessageSource messageSource);
 
     /**
-     * @return the configured message bundle name
+     * Allows to add a message-source class which needs to provide a default constructor.
+     * The message-source can be used by a {@link MessageResolver}
+     * @param messageSourceClass class of a message-source to add
+     * @return the instance of the current message context builder
      */
-    String getBundle();
-
+    MessageContext messageSource(Class<? extends MessageSource> messageSourceClass);
 
     /**
      * @param messageInterpolator a new message interpolator to be set
@@ -82,6 +86,8 @@ public interface MessageContext extends LocaleResolver, Serializable, Cloneable
      */
     LocaleResolver getLocaleResolver();
 
-
-
+    /**
+     * @return list of registered message-sources
+     */
+    List<MessageSource> getMessageSources();
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageResolver.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageResolver.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageResolver.java
index 1a05695..3470839 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageResolver.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageResolver.java
@@ -35,5 +35,4 @@ public interface MessageResolver extends Serializable
      *         or <code>null</code> if an error happened or the resource could not be resolved.
      */
     String getMessage(MessageContext messageContext, String messageTemplate);
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageSource.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageSource.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageSource.java
new file mode 100644
index 0000000..37263cd
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageSource.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.core.api.message;
+
+/**
+ * Allows to provide an identifier for a message-source which gets processed by the {@link MessageResolver}.
+ * In combination with the default implementation of {@link MessageResolver} it allows to specify a custom
+ * resource-bundle location.
+ *
+ * It also allows to use more fine-grained bundle classes which use e.g. only one message-bundle
+ * and the message-source class can be used also for the fluent {@link MessageContext} API.
+ *
+ * example:
+ * <pre>
+ * &#064;MessageBundle
+ * &#064;MessageContextConfig(messageSource = CustomMessageSource.class)
+ * public interface Messages
+ * {
+ *     String msgX(String name);
+ * }
+ *
+ * &#064;MessageBundle
+ * &#064;MessageContextConfig(messageSource = CustomMessageSource.class)
+ * public interface Labels
+ * {
+ *     String labelX();
+ * }
+ * </pre>
+ * In this case both message-interfaces use the same bundle.
+ */
+public interface MessageSource
+{
+    /**
+     * Allows to point to a custom message-source
+     * @return key to identify the location of the message-source
+     */
+    String getKey();
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/MessageContextConfig.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/MessageContextConfig.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/MessageContextConfig.java
index 84a7763..a0e6d5e 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/MessageContextConfig.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/MessageContextConfig.java
@@ -21,6 +21,7 @@ package org.apache.deltaspike.core.api.message.annotation;
 import org.apache.deltaspike.core.api.message.LocaleResolver;
 import org.apache.deltaspike.core.api.message.MessageInterpolator;
 import org.apache.deltaspike.core.api.message.MessageResolver;
+import org.apache.deltaspike.core.api.message.MessageSource;
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
@@ -39,6 +40,12 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 public @interface MessageContextConfig
 {
     /**
+     * Optional custom message-source.
+     * @return classes of the message-sources
+     */
+    Class<? extends MessageSource>[] messageSource() default MessageSource.class;
+
+    /**
      * {@link MessageResolver} which should be used for resolving the message-template (= basic text)
      * @return class of the {@link MessageResolver}-bean or the default marker
      */

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageContext.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageContext.java
index d2fc890..7e18cc4 100644
--- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageContext.java
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageContext.java
@@ -23,8 +23,13 @@ import org.apache.deltaspike.core.api.message.Message;
 import org.apache.deltaspike.core.api.message.MessageContext;
 import org.apache.deltaspike.core.api.message.MessageInterpolator;
 import org.apache.deltaspike.core.api.message.MessageResolver;
+import org.apache.deltaspike.core.api.message.MessageSource;
+import org.apache.deltaspike.core.util.ClassUtils;
 
 import javax.enterprise.inject.Typed;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Locale;
 
 @Typed()
@@ -35,7 +40,7 @@ class DefaultMessageContext implements MessageContext
     private MessageInterpolator messageInterpolator = null;
     private MessageResolver messageResolver = null;
     private LocaleResolver localeResolver = null;
-    private String messageBundleName = null;
+    private List<MessageSource> messageSources = new ArrayList<MessageSource>();
 
     DefaultMessageContext()
     {
@@ -45,8 +50,9 @@ class DefaultMessageContext implements MessageContext
     {
         messageInterpolator(otherMessageContext.getMessageInterpolator());
         localeResolver(otherMessageContext.getLocaleResolver());
-        messageResolver(otherMessageContext.getMessageResolver()) ;
+        messageResolver(otherMessageContext.getMessageResolver());
 
+        this.messageSources.addAll(otherMessageContext.getMessageSources());
     }
 
     @Override
@@ -56,22 +62,27 @@ class DefaultMessageContext implements MessageContext
     }
 
     @Override
-    public MessageContext bundle(String messageBundleName)
+    public Message message()
     {
-        this.messageBundleName = messageBundleName;
-        return this;
+        return new DefaultMessage(this);
     }
 
     @Override
-    public String getBundle()
+    public MessageContext messageSource(MessageSource messageSource)
     {
-        return messageBundleName;
+        this.messageSources.add(messageSource);
+        return this;
     }
 
     @Override
-    public Message message()
+    public MessageContext messageSource(Class<? extends MessageSource> messageSourceClass)
     {
-        return new DefaultMessage(this);
+        //prevent adding the interface itself - TODO discuss it
+        if (MessageSource.class.equals(messageSourceClass))
+        {
+            return this;
+        }
+        return messageSource(ClassUtils.tryToInstantiateClass(messageSourceClass));
     }
 
     @Override
@@ -85,37 +96,48 @@ class DefaultMessageContext implements MessageContext
         return getLocaleResolver().getLocale();
     }
 
+    @Override
     public LocaleResolver getLocaleResolver()
     {
         return localeResolver;
     }
 
+    @Override
+    public List<MessageSource> getMessageSources()
+    {
+        return Collections.unmodifiableList(this.messageSources);
+    }
+
+    @Override
     public MessageContext localeResolver(LocaleResolver localeResolver)
     {
         this.localeResolver = localeResolver;
         return this;
     }
 
+    @Override
     public MessageInterpolator getMessageInterpolator()
     {
         return messageInterpolator;
     }
 
+    @Override
     public MessageContext messageInterpolator(MessageInterpolator messageInterpolator)
     {
         this.messageInterpolator = messageInterpolator;
         return this;
     }
 
+    @Override
     public MessageResolver getMessageResolver()
     {
         return messageResolver;
     }
 
+    @Override
     public MessageContext messageResolver(MessageResolver messageResolver)
     {
         this.messageResolver = messageResolver;
         return this;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageResolver.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageResolver.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageResolver.java
index bf80829..65d2ea7 100644
--- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageResolver.java
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageResolver.java
@@ -20,19 +20,22 @@ package org.apache.deltaspike.core.impl.message;
 
 import org.apache.deltaspike.core.api.message.MessageContext;
 import org.apache.deltaspike.core.api.message.MessageResolver;
+import org.apache.deltaspike.core.api.message.MessageSource;
 import org.apache.deltaspike.core.util.PropertyFileUtils;
 
 import javax.enterprise.context.Dependent;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 
 @Dependent
+@SuppressWarnings("UnusedDeclaration")
 class DefaultMessageResolver implements MessageResolver
 {
     private static final long serialVersionUID = 5834411208472341006L;
 
-
     @Override
     public String getMessage(MessageContext messageContext, String messageTemplate)
     {
@@ -47,28 +50,39 @@ class DefaultMessageResolver implements MessageResolver
         {
             String resourceKey = messageTemplate.substring(1, messageTemplate.length() - 1);
 
-            String bundleName = messageContext.getBundle();
+            List<MessageSource> messageSources = messageContext.getMessageSources();
 
-            if (bundleName == null)
+            if (messageSources == null || messageSources.isEmpty())
             {
                 // using {} without a bundle is always an error
                 return null;
             }
 
-            try
-            {
-                Locale locale = messageContext.getLocale();
-                ResourceBundle messageBundle = PropertyFileUtils.getResourceBundle(bundleName, locale);
+            Iterator<MessageSource> messageSourceIterator = messageSources.iterator();
 
-                return messageBundle.getString(resourceKey);
-            }
-            catch (MissingResourceException e)
+            MessageSource currentMessageSource;
+            while (messageSourceIterator.hasNext())
             {
-                return null;
+                currentMessageSource = messageSourceIterator.next();
+
+                try
+                {
+                    Locale locale = messageContext.getLocale();
+                    ResourceBundle messageBundle = PropertyFileUtils
+                        .getResourceBundle(currentMessageSource.getKey(), locale);
+
+                    return messageBundle.getString(resourceKey);
+                }
+                catch (MissingResourceException e)
+                {
+                    if (!messageSourceIterator.hasNext())
+                    {
+                        return null;
+                    }
+                }
             }
         }
 
         return messageTemplate;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleInvocationHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleInvocationHandler.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleInvocationHandler.java
index 6d7e73e..04eb5ab 100644
--- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleInvocationHandler.java
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleInvocationHandler.java
@@ -28,6 +28,7 @@ import org.apache.deltaspike.core.api.message.LocaleResolver;
 import org.apache.deltaspike.core.api.message.MessageContext;
 import org.apache.deltaspike.core.api.message.MessageInterpolator;
 import org.apache.deltaspike.core.api.message.MessageResolver;
+import org.apache.deltaspike.core.api.message.MessageSource;
 import org.apache.deltaspike.core.api.message.annotation.MessageContextConfig;
 import org.apache.deltaspike.core.api.message.annotation.MessageTemplate;
 import org.apache.deltaspike.core.api.provider.BeanProvider;
@@ -72,17 +73,14 @@ class MessageBundleInvocationHandler implements InvocationHandler
             }
         }
 
-        String messageBundleName = method.getDeclaringClass().getName();
+        messageContext.messageSource(createDefaultMessageSource(method.getDeclaringClass()));
 
         if (String.class.isAssignableFrom(method.getReturnType()))
         {
-            return messageContext.bundle(messageBundleName).message().template(messageTemplateValue)
-                    .argument(arguments.toArray()).toString();
+            return messageContext.message().template(messageTemplateValue).argument(arguments.toArray()).toString();
         }
 
-        return messageContext.bundle(messageBundleName).message().template(messageTemplateValue)
-                .argument(arguments.toArray());
-
+        return messageContext.message().template(messageTemplateValue).argument(arguments.toArray());
     }
 
     private void applyMessageContextConfig(MessageContext messageContext, MessageContextConfig messageContextConfig)
@@ -113,6 +111,13 @@ class MessageBundleInvocationHandler implements InvocationHandler
             messageContext.localeResolver(
                     BeanProvider.getContextualReference(localeResolverClass, new AnyLiteral()));
         }
+        
+        Class<? extends MessageSource>[] messageSources = messageContextConfig.messageSource();
+
+        for (Class<? extends MessageSource> currentMessageSource : messageSources)
+        {
+            messageContext.messageSource(currentMessageSource);
+        }
     }
 
     private List<Object> resolveMessageArguments(Object[] args)
@@ -149,4 +154,22 @@ class MessageBundleInvocationHandler implements InvocationHandler
     {
         return BeanProvider.getContextualReference(MessageContext.class);
     }
+
+    /**
+     * the fully qualified class name is the name of the bundle
+     * @param messageBundleClass message-bundle class
+     * @return message source for the given message-bundle class
+     */
+    private MessageSource createDefaultMessageSource(final Class<?> messageBundleClass)
+    {
+        final String className = messageBundleClass.getName();
+        return new MessageSource()
+        {
+            @Override
+            public String getKey()
+            {
+                return className;
+            }
+        };
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/CustomMinimalMessages.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/CustomMinimalMessages.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/CustomMinimalMessages.java
new file mode 100644
index 0000000..19bbf2a
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/CustomMinimalMessages.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.core.api.message;
+
+import org.apache.deltaspike.core.api.message.annotation.MessageBundle;
+import org.apache.deltaspike.core.api.message.annotation.MessageContextConfig;
+import org.apache.deltaspike.test.core.api.message.source.MinimalMessageSource;
+
+@MessageBundle
+@MessageContextConfig(
+    localeResolver = FixedEnglishLocalResolver.class,
+    messageSource = MinimalMessageSource.class)
+public interface CustomMinimalMessages
+{
+    String sayHello(String name);
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageContextTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageContextTest.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageContextTest.java
index 938b76e..c64073c 100644
--- a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageContextTest.java
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageContextTest.java
@@ -22,6 +22,7 @@ import org.apache.deltaspike.core.api.message.LocaleResolver;
 import org.apache.deltaspike.core.api.message.MessageContext;
 import org.apache.deltaspike.core.impl.message.MessageBundleExtension;
 import org.apache.deltaspike.test.category.SeCategory;
+import org.apache.deltaspike.test.core.api.message.source.InvalidMessageSource;
 import org.apache.deltaspike.test.util.ArchiveUtils;
 import org.jboss.arquillian.container.test.api.Deployment;
 import org.jboss.arquillian.junit.Arquillian;
@@ -110,7 +111,11 @@ public class MessageContextTest
         String messageText = messageContext.message().template("{xyz123}").toString();
         Assert.assertEquals("???xyz123???", messageText);
 
-        messageText = messageContext.bundle("nonexistingbundle.properties").message().template("{xyz123}").toString();
+        messageText = messageContext
+                .messageSource(InvalidMessageSource.class)
+                .message()
+                .template("{xyz123}")
+                .toString();
         Assert.assertEquals("???xyz123???", messageText);
     }
 
@@ -122,5 +127,4 @@ public class MessageContextTest
 
         Assert.assertEquals("???xyz123??? [123, 456, 789]", messageText);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MinimalMessagesTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MinimalMessagesTest.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MinimalMessagesTest.java
index 30a860a..c3383ac 100644
--- a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MinimalMessagesTest.java
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MinimalMessagesTest.java
@@ -46,6 +46,9 @@ public class MinimalMessagesTest
     @Inject
     private MinimalMessages minimalMessages;
 
+    @Inject
+    private CustomMinimalMessages customMinimalMessages;
+
     /**
      * X TODO creating a WebArchive is only a workaround because JavaArchive
      * cannot contain other archives.
@@ -72,4 +75,10 @@ public class MinimalMessagesTest
     {
         assertEquals("Hello DeltaSpike", minimalMessages.sayHello("DeltaSpike"));
     }
+
+    @Test
+    public void testCustomMinimalMessage()
+    {
+        assertEquals("Hello DeltaSpike", customMinimalMessages.sayHello("DeltaSpike"));
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/source/InvalidMessageSource.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/source/InvalidMessageSource.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/source/InvalidMessageSource.java
new file mode 100644
index 0000000..2ef81e2
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/source/InvalidMessageSource.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.core.api.message.source;
+
+import org.apache.deltaspike.core.api.exclude.annotation.Exclude;
+import org.apache.deltaspike.core.api.message.MessageSource;
+
+/**
+ * Message-source which doesn't point to a valid location
+ */
+@Exclude
+public class InvalidMessageSource implements MessageSource
+{
+    @Override
+    public String getKey()
+    {
+        return "/dev/null";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/d4db0891/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/source/MinimalMessageSource.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/source/MinimalMessageSource.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/source/MinimalMessageSource.java
new file mode 100644
index 0000000..b8253ee
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/source/MinimalMessageSource.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.core.api.message.source;
+
+import org.apache.deltaspike.core.api.exclude.annotation.Exclude;
+import org.apache.deltaspike.core.api.message.MessageSource;
+import org.apache.deltaspike.test.core.api.message.MinimalMessages;
+
+/**
+ * Custom message-source
+ */
+@Exclude
+public class MinimalMessageSource implements MessageSource
+{
+    @Override
+    public String getKey()
+    {
+        return MinimalMessages.class.getName();
+    }
+}