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/04/09 22:08:21 UTC

git commit: DELTASPIKE-153 Message and MessageContext

Updated Branches:
  refs/heads/master dd355a2ba -> 2975d3373


DELTASPIKE-153 Message and MessageContext

 including DELTASPIKE-154


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

Branch: refs/heads/master
Commit: 2975d3373c7c96ca6fa11d978932c52c4ccc943b
Parents: dd355a2
Author: gpetracek <gp...@apache.org>
Authored: Sun Apr 8 20:11:02 2012 +0200
Committer: gpetracek <gp...@apache.org>
Committed: Mon Apr 9 22:03:28 2012 +0200

----------------------------------------------------------------------
 .../deltaspike/core/api/message/Message.java       |   41 +++
 .../core/api/message/MessageContext.java           |  131 ++++++++
 .../core/api/message/MessageResolver.java          |    4 +-
 .../core/api/message/annotation/Message.java       |   39 ---
 .../api/message/annotation/MessageTemplate.java    |   39 +++
 .../core/impl/message/DefaultLocaleResolver.java   |   41 +++
 .../core/impl/message/DefaultMessage.java          |  180 ++++++++++
 .../core/impl/message/DefaultMessageBuilder.java   |  236 ++++++++++++++
 .../core/impl/message/DefaultMessageContext.java   |   92 ++++++
 .../impl/message/DefaultMessageContextConfig.java  |  252 +++++++++++++++
 .../impl/message/DefaultMessageInterpolator.java   |   39 +++
 .../core/impl/message/DefaultMessageResolver.java  |   12 +-
 .../core/impl/message/MessageBundleExtension.java  |   50 +++
 .../message/MessageBundleInvocationHandler.java    |  110 +++++---
 .../core/impl/message/MessageContextProducer.java  |   62 ++++
 .../impl/message/UnmodifiableMessageContext.java   |   61 ++++
 .../message/UnmodifiableMessageContextConfig.java  |   77 +++++
 .../test/core/api/message/MessageContextTest.java  |  131 ++++++++
 .../test/core/api/message/MessageTest.java         |    2 +-
 .../test/core/api/message/SimpleMessage.java       |   11 +-
 .../test/core/api/message/SimpleMessageTest.java   |    6 +-
 .../core/api/message/TestGermanLocaleResolver.java |   36 ++
 .../test/core/api/message/TestLocalResolver.java   |   36 ++
 .../core/api/message/TestMessageInterpolator.java  |    2 +
 .../test/core/api/message/TestMessageResolver.java |   78 +++++
 .../test/core/api/message/TestMessages.java        |   16 +-
 .../test/core/api/message/TestMessages.properties  |   19 --
 .../core/api/message/TestMessages_de.properties    |   18 +
 .../core/api/message/TestMessages_en.properties    |   21 ++
 29 files changed, 1723 insertions(+), 119 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Message.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Message.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Message.java
new file mode 100644
index 0000000..ce926b6
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Message.java
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+/**
+ * Basic interface for all message-types
+ */
+public interface Message
+{
+    /**
+     * @return the message key (or inline-text) of the current message
+     */
+    String getMessageTemplate();
+
+    /**
+     * @return all named and numbered arguments
+     */
+    Object[] getArguments();
+
+    /**
+     * @param arguments 1-n new arguments for the current message
+     * @return the current instance
+     */
+    Message addArgument(Object... arguments);
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/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
new file mode 100644
index 0000000..7b17a9b
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageContext.java
@@ -0,0 +1,131 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+
+/**
+ * Central context for handling dynamic messages
+ */
+public interface MessageContext extends LocaleResolver, Serializable
+{
+    /**
+     * @return message builder to add and/or create a new message based on the current context via a fluent api
+     */
+    MessageBuilder message();
+
+    /**
+     * @return the current config to change it or create a new one base on the current config
+     */
+    Config config();
+
+    /*
+     * @param messageTemplate a message which should be added to the current context (message handlers)
+     */
+    //void addMessage(Message messageTemplate);
+
+    /**
+     * Helper for building instances of {@link Message}
+     */
+    interface MessageBuilder
+    {
+        /**
+         * @param messageTemplate message key (or inline-text) for the current message
+         * @return the current instance of the message builder to allow a fluent api
+         */
+        MessageBuilder text(String messageTemplate);
+
+        /**
+         * @param arguments numbered and/or named argument(s) for the current message
+         * @return the current instance of the message builder to allow a fluent api
+         */
+        MessageBuilder argument(Object... arguments);
+
+        /**
+         * @return the message which was built via the fluent api
+         */
+        Message create();
+
+        /**
+         * @return the text of the message which was built via the fluent api
+         */
+        String toText();
+    }
+
+    /**
+     * Config for customizing a {@link MessageContext}
+     */
+    interface Config extends Serializable
+    {
+        /**
+         * create a new context based on the default context - the default context won't get modified
+         *
+         * @return a message context builder based on the current config
+         */
+        MessageContextBuilder use();
+
+        /**
+         * change the default context
+         *
+         * @return a message context builder to change the current config
+         */
+        MessageContextBuilder change();
+
+        /**
+         * @return the current message interpolator
+         */
+        MessageInterpolator getMessageInterpolator();
+
+        /**
+         * @return the current message resolver
+         */
+        MessageResolver getMessageResolver();
+
+        /**
+         * @return the current locale resolver
+         */
+        LocaleResolver getLocaleResolver();
+
+        interface MessageContextBuilder
+        {
+            /**
+             * @param messageInterpolator a new message interpolator
+             * @return the instance of the current message context builder
+             */
+            MessageContextBuilder messageInterpolator(MessageInterpolator messageInterpolator);
+
+            /**
+             * @param messageResolver a new message resolver
+             * @return the instance of the current message context builder
+             */
+            MessageContextBuilder messageResolver(MessageResolver messageResolver);
+
+            /**
+             * @param localeResolver a new locale resolver
+             * @return the instance of the current message context builder
+             */
+            MessageContextBuilder localeResolver(LocaleResolver localeResolver);
+
+            /**
+             * @return a new message context based on the current config
+             */
+            MessageContext create();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/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 85feab3..8180b8a 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
@@ -28,8 +28,8 @@ public interface MessageResolver extends Serializable
     String MISSING_RESOURCE_MARKER = "???";
 
     /**
-     * @param messageDescriptor the message key (or in-lined text) of the current message
+     * @param messageTemplate the message key (or in-lined text) of the current message
      * @return the final but not interpolated message text
      */
-    String getMessage(String messageDescriptor);
+    String getMessage(String messageTemplate);
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/Message.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/Message.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/Message.java
deleted file mode 100644
index 8c3130c..0000000
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/Message.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.annotation;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-@Target(METHOD)
-@Retention(RUNTIME)
-@Documented
-public @interface Message
-{
-    /**
-     * The default format string of this message.
-     *
-     * @return the format string
-     */
-    String value();
-}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/MessageTemplate.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/MessageTemplate.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/MessageTemplate.java
new file mode 100644
index 0000000..979d52b
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/annotation/MessageTemplate.java
@@ -0,0 +1,39 @@
+/*
+ * 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.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Target(METHOD)
+@Retention(RUNTIME)
+@Documented
+public @interface MessageTemplate
+{
+    /**
+     * The default format string of this message.
+     *
+     * @return the format string
+     */
+    String value();
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultLocaleResolver.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultLocaleResolver.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultLocaleResolver.java
new file mode 100644
index 0000000..81bdfc1
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultLocaleResolver.java
@@ -0,0 +1,41 @@
+/*
+ * 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.impl.message;
+
+
+import org.apache.deltaspike.core.api.message.LocaleResolver;
+
+import javax.enterprise.inject.Typed;
+import java.io.Serializable;
+import java.util.Locale;
+
+/**
+ * {@inheritDoc}
+ */
+@Typed()
+class DefaultLocaleResolver implements LocaleResolver, Serializable
+{
+    private static final long serialVersionUID = 2075618472090834156L;
+
+    @Override
+    public Locale getLocale()
+    {
+        return Locale.getDefault();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessage.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessage.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessage.java
new file mode 100644
index 0000000..59f8139
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessage.java
@@ -0,0 +1,180 @@
+/*
+ * 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.impl.message;
+
+import org.apache.deltaspike.core.api.message.Message;
+import org.apache.deltaspike.core.api.message.MessageContext;
+
+import javax.enterprise.inject.Typed;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * {@inheritDoc}
+ */
+@Typed()
+class DefaultMessage implements Message
+{
+    protected String messageTemplate;
+    protected List<Object> arguments = new ArrayList<Object>();
+
+    private MessageContext.Config messageContextConfig;
+
+    DefaultMessage(MessageContext.Config messageContextConfig,
+                   String messageTemplate,
+                   Object... arguments)
+    {
+        this.messageContextConfig = messageContextConfig;
+        this.messageTemplate = messageTemplate;
+        this.arguments.addAll(Arrays.asList(arguments));
+    }
+
+    @Override
+    public Message addArgument(Object... arguments)
+    {
+        Object argument;
+        for (Object currentArgument : arguments)
+        {
+            argument = currentArgument;
+
+            if (isHiddenArgument(argument))
+            {
+                addHiddenArgument(argument);
+            }
+            else
+            {
+                addArgumentToMessage(argument);
+            }
+        }
+        return this;
+    }
+
+    private void addArgumentToMessage(Object argument)
+    {
+        //TODO discuss Localizable
+        String result;
+
+        if (argument instanceof String)
+        {
+            result = (String) argument;
+        }
+        else if (argument == null)
+        {
+            result = "null";
+        }
+        else
+        {
+            result = argument.toString();
+        }
+
+        addNumberedArgument(result);
+    }
+
+    private boolean isHiddenArgument(Object argument)
+    {
+        return argument != null && argument.getClass().isArray();
+    }
+
+    private void addHiddenArgument(Object argument)
+    {
+        for (Object current : ((Object[]) argument))
+        {
+            addArgumentToMessage(current);
+        }
+    }
+
+    protected void addNumberedArgument(Serializable argument)
+    {
+        if (this.arguments == null)
+        {
+            this.arguments = new ArrayList<Object>();
+        }
+
+        this.arguments.add(argument);
+    }
+
+    @Override
+    public String getMessageTemplate()
+    {
+        return this.messageTemplate;
+    }
+
+    @Override
+    public Object[] getArguments()
+    {
+        return this.arguments.toArray();
+    }
+
+
+    @Override
+    public String toString()
+    {
+        return toString(new DefaultMessageContext(this.messageContextConfig));
+    }
+
+    public String toString(MessageContext messageContext)
+    {
+        return messageContext.message()
+                .text(getMessageTemplate())
+                .argument(getArguments())
+                .toText();
+    }
+
+    /*
+     * generated
+     */
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if (this == o)
+        {
+            return true;
+        }
+
+        if (!(o instanceof Message))
+        {
+            return false;
+        }
+
+        Message that = (Message) o;
+
+        if (!getMessageTemplate().equals(that.getMessageTemplate()))
+        {
+            return false;
+        }
+        //noinspection RedundantIfStatement
+        if (arguments != null ? !Arrays.equals(arguments.toArray(), that.getArguments()) : that.getArguments() != null)
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = getMessageTemplate().hashCode();
+        result = 31 * result + (arguments != null ? arguments.hashCode() : 0);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageBuilder.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageBuilder.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageBuilder.java
new file mode 100644
index 0000000..929b564
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageBuilder.java
@@ -0,0 +1,236 @@
+/*
+ * 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.impl.message;
+
+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 javax.enterprise.inject.Typed;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * {@inheritDoc}
+ */
+@Typed()
+class DefaultMessageBuilder implements MessageContext.MessageBuilder
+{
+    private String messageTemplate;
+    private ArrayList<Object> argumentList;
+
+    private final MessageContext messageContext;
+
+    /**
+     * Constructor for creating the builder which uses the given {@link MessageContext}
+     * @param messageContext current message-context
+     */
+    public DefaultMessageBuilder(MessageContext messageContext)
+    {
+        reset();
+        this.messageContext = new UnmodifiableMessageContext(messageContext.config().use().create() /*== clone*/);
+    }
+
+    @Override
+    public MessageContext.MessageBuilder text(String messageTemplate)
+    {
+        this.messageTemplate = messageTemplate;
+        return this;
+    }
+
+    @Override
+    public MessageContext.MessageBuilder argument(Object... arguments)
+    {
+        Collections.addAll(this.argumentList, arguments);
+
+        return this;
+    }
+
+    private Message buildMessageTemplate()
+    {
+        if (this.messageTemplate == null)
+        {
+            throw new IllegalStateException("messageTemplate is missing");
+        }
+
+        return new DefaultMessage(this.messageContext.config(), this.messageTemplate,
+                this.argumentList.toArray(new Object[this.argumentList.size()]));
+    }
+
+    protected void reset()
+    {
+        this.messageTemplate = null;
+        this.argumentList = new ArrayList<Object>();
+    }
+
+    @Override
+    public Message create()
+    {
+        Message result = buildMessageTemplate();
+        reset();
+        return result;
+    }
+
+    @Override
+    public String toText()
+    {
+        Message baseMessage = buildMessageTemplate();
+
+        return getMessageText(baseMessage);
+    }
+
+    private String getMessageText(Message baseMessage)
+    {
+        String messageTemplate = baseMessage.getMessageTemplate();
+
+        MessageResolver messageResolver = this.messageContext.config().getMessageResolver();
+        if (messageResolver != null)
+        {
+            messageTemplate = resolveMessage(messageResolver, baseMessage);
+        }
+
+        MessageInterpolator messageInterpolator = this.messageContext.config().getMessageInterpolator();
+
+        if (messageInterpolator != null && messageTemplate != null)
+        {
+            return checkedResult(
+                    interpolateMessage(messageInterpolator,
+                            messageTemplate,
+                            baseMessage.getArguments()),
+                    baseMessage);
+        }
+
+        return checkedResult(messageTemplate, baseMessage);
+    }
+
+    private String checkedResult(String result, Message baseMessage)
+    {
+        if (result == null || isKey(baseMessage.getMessageTemplate()) || isKeyWithoutMarkers(result, baseMessage))
+        {
+            //minor performance tweak for inline-msg
+            String oldTemplate = extractTemplate(baseMessage.getMessageTemplate());
+
+            if (result == null || result.equals(oldTemplate))
+            {
+                return MessageResolver.MISSING_RESOURCE_MARKER + oldTemplate +
+                        MessageResolver.MISSING_RESOURCE_MARKER + getArguments(baseMessage);
+            }
+        }
+        return result;
+    }
+
+    private boolean isKeyWithoutMarkers(String result, Message baseMessage)
+    {
+        return (!result.contains(" ") && result.endsWith(baseMessage.getMessageTemplate()));
+    }
+
+    private String getArguments(Message message)
+    {
+        StringBuilder result = new StringBuilder();
+
+        Object argument;
+        Object[] arguments = message.getArguments();
+        //TODO formatter
+
+        if (arguments == null || arguments.length == 0)
+        {
+            return "";
+        }
+
+        for (int i = 0; i < arguments.length; i++)
+        {
+            if (i == 0)
+            {
+                result.append(" (");
+            }
+            else
+            {
+                result.append(",");
+            }
+
+            argument = arguments[i];
+
+            //TODO discuss Localizable
+
+            result.append(argument.toString());
+        }
+        result.append(')');
+
+        return result.toString();
+    }
+
+    private void resolveAndProcessLazyNumberedArgument(
+            MessageContext messageContext, List<Object> result, String argument)
+    {
+        String resolvedArgumentValue = resolveValueOfArgumentDescriptor(messageContext, argument);
+
+        result.add(resolvedArgumentValue);
+    }
+
+    private String resolveValueOfArgumentDescriptor(MessageContext messageContext, String argumentAsKey)
+    {
+        return messageContext.message()
+                .text(argumentAsKey)
+                .toText();
+    }
+
+    private String extractTemplate(String template)
+    {
+        String result = getEscapedTemplate(template);
+
+        if (isKey(result))
+        {
+            result = extractTemplateKey(result);
+        }
+
+        return result;
+    }
+
+    private boolean isKey(String key)
+    {
+        return key.startsWith("{") && key.endsWith("}");
+    }
+
+    private String extractTemplateKey(String key)
+    {
+        return key.substring(1, key.length() - 1);
+    }
+
+    private String resolveMessage(MessageResolver messageResolver, Message baseMessage)
+    {
+        return messageResolver.getMessage(baseMessage.getMessageTemplate());
+    }
+
+    private String interpolateMessage(MessageInterpolator messageInterpolator,
+                                      String messageTemplate, Object... arguments)
+    {
+        return messageInterpolator.interpolate(getEscapedTemplate(messageTemplate), arguments);
+    }
+
+    private String getEscapedTemplate(String messageTemplate)
+    {
+        if (messageTemplate.startsWith("\\{"))
+        {
+            return messageTemplate.substring(1);
+        }
+        return messageTemplate;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/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
new file mode 100644
index 0000000..2dc2826
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageContext.java
@@ -0,0 +1,92 @@
+/*
+ * 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.impl.message;
+
+import org.apache.deltaspike.core.api.message.MessageContext;
+
+import javax.enterprise.inject.Typed;
+import java.util.Locale;
+
+@Typed()
+class DefaultMessageContext implements MessageContext
+{
+    private static final long serialVersionUID = -110779217295211303L;
+
+    private Config config = new DefaultMessageContextConfig();
+
+    DefaultMessageContext()
+    {
+    }
+
+    DefaultMessageContext(Config config)
+    {
+        this.config = config;
+    }
+
+    @Override
+    public MessageBuilder message()
+    {
+        return new DefaultMessageBuilder(this);
+    }
+
+    @Override
+    public Config config()
+    {
+        return config;
+    }
+
+    @Override
+    public Locale getLocale()
+    {
+        return config().getLocaleResolver().getLocale();
+    }
+
+    /*
+     * generated
+     */
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if (this == o)
+        {
+            return true;
+        }
+        if (!(o instanceof DefaultMessageContext))
+        {
+            return false;
+        }
+
+        DefaultMessageContext that = (DefaultMessageContext) o;
+
+        //noinspection RedundantIfStatement
+        if (!config.equals(that.config))
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return config.hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageContextConfig.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageContextConfig.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageContextConfig.java
new file mode 100644
index 0000000..c802477
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageContextConfig.java
@@ -0,0 +1,252 @@
+/*
+ * 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.impl.message;
+
+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 javax.enterprise.inject.Typed;
+
+/**
+ * {@inheritDoc}
+ */
+@Typed()
+class DefaultMessageContextConfig implements MessageContext.Config
+{
+    private static final long serialVersionUID = 2919944628020782545L;
+
+    private MessageInterpolator messageInterpolator;
+    private MessageResolver messageResolver;
+    private LocaleResolver localeResolver;
+
+    DefaultMessageContextConfig()
+    {
+        resetMessageContextConfig();
+    }
+
+    private DefaultMessageContextConfig(MessageContext.Config messageContextConfigTemplate)
+    {
+        this();
+        this.messageInterpolator = messageContextConfigTemplate.getMessageInterpolator();
+        this.messageResolver = messageContextConfigTemplate.getMessageResolver();
+        this.localeResolver = messageContextConfigTemplate.getLocaleResolver();
+    }
+
+    @Override
+    public MessageContextBuilder use()
+    {
+        return new MessageContextBuilder()
+        {
+            private DefaultMessageContextConfig newMessageContextConfig =
+                    new DefaultMessageContextConfig(DefaultMessageContextConfig.this);
+
+            @Override
+            public MessageContextBuilder messageInterpolator(MessageInterpolator messageInterpolator)
+            {
+                newMessageContextConfig.setMessageInterpolator(messageInterpolator);
+                return this;
+            }
+
+            @Override
+            public MessageContextBuilder messageResolver(MessageResolver messageResolver)
+            {
+                newMessageContextConfig.setMessageResolver(messageResolver);
+                return this;
+            }
+
+            @Override
+            public MessageContextBuilder localeResolver(LocaleResolver localeResolver)
+            {
+                newMessageContextConfig.setLocaleResolver(localeResolver);
+                return this;
+            }
+
+            @Override
+            public MessageContext create()
+            {
+                return new DefaultMessageContext(this.newMessageContextConfig);
+            }
+        };
+    }
+
+    @Override
+    public MessageContextBuilder change()
+    {
+        return new MessageContextBuilder()
+        {
+            @Override
+            public MessageContextBuilder messageInterpolator(MessageInterpolator messageInterpolator)
+            {
+                setMessageInterpolator(messageInterpolator);
+                return this;
+            }
+
+            @Override
+            public MessageContextBuilder messageResolver(MessageResolver messageResolver)
+            {
+                setMessageResolver(messageResolver);
+                return this;
+            }
+
+            @Override
+            public MessageContextBuilder localeResolver(LocaleResolver localeResolver)
+            {
+                setLocaleResolver(localeResolver);
+                return this;
+            }
+
+            @Override
+            public MessageContext create()
+            {
+                return new DefaultMessageContext(DefaultMessageContextConfig.this);
+            }
+        };
+    }
+
+    private void resetMessageContextConfig()
+    {
+        this.messageInterpolator = new DefaultMessageInterpolator();
+        this.messageResolver = null;
+        this.localeResolver = new DefaultLocaleResolver();
+    }
+
+    @Override
+    public MessageInterpolator getMessageInterpolator()
+    {
+        return this.messageInterpolator;
+    }
+
+    @Override
+    public MessageResolver getMessageResolver()
+    {
+        return this.messageResolver;
+    }
+
+    @Override
+    public LocaleResolver getLocaleResolver()
+    {
+        return this.localeResolver;
+    }
+
+    private void setMessageInterpolator(MessageInterpolator messageInterpolator)
+    {
+        this.messageInterpolator = messageInterpolator;
+    }
+
+    private void setMessageResolver(MessageResolver messageResolver)
+    {
+        this.messageResolver = messageResolver;
+    }
+
+    private void setLocaleResolver(LocaleResolver localeResolver)
+    {
+        this.localeResolver = localeResolver;
+    }
+
+    @Override
+    public String toString()
+    {
+        String newLine = System.getProperty("line.separator");
+
+        StringBuilder configInfo = new StringBuilder("MessageContextConfig class: ");
+        configInfo.append(getClass().getName());
+        configInfo.append(newLine);
+
+        if (this.messageInterpolator != null)
+        {
+            configInfo.append("   MessageInterpolator class: ").append(this.messageInterpolator.getClass());
+        }
+        else
+        {
+            configInfo.append("   no MessageInterpolator");
+        }
+        configInfo.append(newLine);
+
+        if (this.messageResolver != null)
+        {
+            configInfo.append("   MessageResolver class: ").append(this.messageResolver.getClass());
+        }
+        else
+        {
+            configInfo.append("   no MessageResolver");
+        }
+        configInfo.append(newLine);
+
+        configInfo.append(newLine);
+
+        if (this.localeResolver != null)
+        {
+            configInfo.append("   LocaleResolver class: ").append(this.localeResolver.getClass());
+        }
+        else
+        {
+            configInfo.append("   no LocaleResolver");
+        }
+        configInfo.append(newLine);
+
+        return configInfo.toString();
+    }
+
+    /*
+     * generated
+     */
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if (this == o)
+        {
+            return true;
+        }
+        if (!(o instanceof DefaultMessageContextConfig))
+        {
+            return false;
+        }
+
+        DefaultMessageContextConfig that = (DefaultMessageContextConfig) o;
+
+        if (!localeResolver.equals(that.localeResolver))
+        {
+            return false;
+        }
+        if (messageInterpolator != null
+                ? !messageInterpolator.equals(that.messageInterpolator) : that.messageInterpolator != null)
+        {
+            return false;
+        }
+        //noinspection RedundantIfStatement
+        if (messageResolver != null ? !messageResolver.equals(that.messageResolver) : that.messageResolver != null)
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = messageInterpolator != null ? messageInterpolator.hashCode() : 0;
+        result = 31 * result + (messageResolver != null ? messageResolver.hashCode() : 0);
+        result = 31 * result + localeResolver.hashCode();
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageInterpolator.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageInterpolator.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageInterpolator.java
new file mode 100644
index 0000000..b246170
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/DefaultMessageInterpolator.java
@@ -0,0 +1,39 @@
+/*
+ * 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.impl.message;
+
+import org.apache.deltaspike.core.api.message.MessageInterpolator;
+
+import javax.enterprise.inject.Typed;
+import java.io.Serializable;
+
+/**
+ * {@inheritDoc}
+ */
+@Typed()
+class DefaultMessageInterpolator implements MessageInterpolator, Serializable
+{
+    private static final long serialVersionUID = -8854087197813424812L;
+
+    @Override
+    public String interpolate(String messageTemplate, Object... arguments)
+    {
+        return messageTemplate;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/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 fda9712..0c1d5f3 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
@@ -50,21 +50,21 @@ class DefaultMessageResolver implements MessageResolver
     }
 
     @Override
-    public String getMessage(String messageDescriptor)
+    public String getMessage(String messageTemplate)
     {
-        if (this.messageBundle != null && messageDescriptor != null &&
-            messageDescriptor.startsWith("{") && messageDescriptor.endsWith("}"))
+        if (this.messageBundle != null && messageTemplate != null &&
+            messageTemplate.startsWith("{") && messageTemplate.endsWith("}"))
         {
             try
             {
-                return this.messageBundle.getString(messageDescriptor.substring(1, messageDescriptor.length() - 1));
+                return this.messageBundle.getString(messageTemplate.substring(1, messageTemplate.length() - 1));
             }
             catch (MissingResourceException e)
             {
-                return MISSING_RESOURCE_MARKER + messageDescriptor + MISSING_RESOURCE_MARKER;
+                return MISSING_RESOURCE_MARKER + messageTemplate + MISSING_RESOURCE_MARKER;
             }
         }
 
-        return messageDescriptor;
+        return messageTemplate;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java
index f832fba..d8fcfb8 100644
--- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java
@@ -18,6 +18,7 @@
  */
 package org.apache.deltaspike.core.impl.message;
 
+import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.HashSet;
 
@@ -33,7 +34,10 @@ import javax.enterprise.inject.spi.Extension;
 import javax.enterprise.inject.spi.ProcessAnnotatedType;
 import javax.enterprise.inject.spi.ProcessProducerMethod;
 
+import org.apache.deltaspike.core.api.message.Message;
+import org.apache.deltaspike.core.api.message.MessageContext;
 import org.apache.deltaspike.core.api.message.annotation.MessageBundle;
+import org.apache.deltaspike.core.api.message.annotation.MessageTemplate;
 import org.apache.deltaspike.core.spi.activation.Deactivatable;
 import org.apache.deltaspike.core.util.ClassDeactivationUtils;
 
@@ -59,12 +63,58 @@ public class MessageBundleExtension implements Extension, Deactivatable
         }
 
         AnnotatedType<?> type = event.getAnnotatedType();
+
         if (type.isAnnotationPresent(MessageBundle.class))
         {
+            validateMessageBundle(type.getJavaClass());
+
             messageBundleTypes.add(type);
         }
     }
 
+    private void validateMessageBundle(Class<?> currentClass)
+    {
+        for (Method currentMethod : currentClass.getDeclaredMethods())
+        {
+            if (!currentMethod.isAnnotationPresent(MessageTemplate.class))
+            {
+                continue;
+            }
+            
+            if (String.class.isAssignableFrom(currentMethod.getReturnType()))
+            {
+                continue;
+            }
+
+            if (Message.class.isAssignableFrom(currentMethod.getReturnType()))
+            {
+                validateMessageContextAwareMethod(currentMethod);
+            }
+            else
+            {
+                throw new IllegalStateException(
+                        currentMethod.getReturnType().getName() + " isn't supported. Details: " +
+                        currentMethod.getDeclaringClass().getName() + "#" + currentMethod.getName() +
+                        " only " + String.class.getName() + " or " + Message.class.getName());
+            }
+        }
+    }
+
+    private void validateMessageContextAwareMethod(Method currentMethod)
+    {
+        for (Class currentParameterType : currentMethod.getParameterTypes())
+        {
+            if (MessageContext.class.isAssignableFrom(currentParameterType))
+            {
+                return;
+            }
+        }
+
+        throw new IllegalStateException("No " + MessageContext.class.getName() + " parameter found at: " +
+                currentMethod.getDeclaringClass().getName() + "#" + currentMethod.getName() +
+                ". That is required for return-type " + Message.class.getName());
+    }
+
     // according to the Java EE 6 javadoc (the authority according to the powers
     // that be),
     // this is the correct order of type parameters

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/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 7fb8f87..6bf420f 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
@@ -20,15 +20,18 @@ package org.apache.deltaspike.core.impl.message;
 
 import org.apache.deltaspike.core.api.literal.MessageContextConfigLiteral;
 import org.apache.deltaspike.core.api.message.LocaleResolver;
-import org.apache.deltaspike.core.api.message.annotation.Message;
-import org.apache.deltaspike.core.api.message.annotation.MessageContextConfig;
+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.annotation.MessageContextConfig;
+import org.apache.deltaspike.core.api.message.annotation.MessageTemplate;
 import org.apache.deltaspike.core.api.provider.BeanProvider;
 import org.apache.deltaspike.core.util.ClassUtils;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
 
 class MessageBundleInvocationHandler implements InvocationHandler
@@ -40,63 +43,96 @@ class MessageBundleInvocationHandler implements InvocationHandler
     @Override
     public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable
     {
-        final Message message = method.getAnnotation(Message.class);
+        final MessageTemplate messageTemplate = method.getAnnotation(MessageTemplate.class);
 
-        if (message == null)
+        if (messageTemplate == null)
         {
-            // nothing to do...
+            // nothing to do... TODO discuss it
             return null;
         }
 
-        //X TODO discuss use-cases for a deeper lookup and qualifier support
-        MessageContextConfig messageContextConfig =
-            method.getDeclaringClass().getAnnotation(MessageContextConfig.class);
+        MessageContext messageContext = null;
 
-        if (messageContextConfig == null)
-        {
-            messageContextConfig = new MessageContextConfigLiteral();
-        }
+        List<Object> arguments = null;
 
-        String messageTemplate;
-
-        if (!MessageResolver.class.equals(messageContextConfig.messageResolver()))
+        if (args != null && args.length > 0)
         {
-            Class<? extends MessageResolver> messageResolverClass =
-                    ClassUtils.tryToLoadClassForName(messageContextConfig.messageResolver().getName());
+            arguments = new ArrayList<Object>(args.length);
 
-            MessageResolver messageResolver = BeanProvider.getContextualReference(messageResolverClass);
+            for (Object arg : args)
+            {
+                if (MessageContext.class.isAssignableFrom(arg.getClass()))
+                {
+                    messageContext = (MessageContext)arg;
+                    continue;
+                }
 
-            messageTemplate = messageResolver.getMessage(message.value());
+                arguments.add(arg);
+            }
         }
-        else 
+
+        if (messageContext == null)
         {
-            Class<? extends LocaleResolver> localeResolverClass =
-                    ClassUtils.tryToLoadClassForName(messageContextConfig.localeResolver().getName());
+            //X TODO discuss use-cases for a deeper lookup and qualifier support
+            MessageContextConfig messageContextConfig =
+                method.getDeclaringClass().getAnnotation(MessageContextConfig.class);
+
+            if (messageContextConfig == null)
+            {
+                messageContextConfig = new MessageContextConfigLiteral();
+            }
+
+            String resolvedMessageTemplate;
+
+            if (!MessageResolver.class.equals(messageContextConfig.messageResolver()))
+            {
+                Class<? extends MessageResolver> messageResolverClass =
+                        ClassUtils.tryToLoadClassForName(messageContextConfig.messageResolver().getName());
 
-            Locale resolvedLocale = Locale.getDefault();
+                MessageResolver messageResolver = BeanProvider.getContextualReference(messageResolverClass);
 
-            if (!LocaleResolver.class.equals(localeResolverClass))
+                resolvedMessageTemplate = messageResolver.getMessage(messageTemplate.value());
+            }
+            else
             {
-                LocaleResolver localeResolver = BeanProvider.getContextualReference(localeResolverClass);
+                Class<? extends LocaleResolver> localeResolverClass =
+                        ClassUtils.tryToLoadClassForName(messageContextConfig.localeResolver().getName());
+
+                Locale resolvedLocale = Locale.getDefault();
+
+                if (!LocaleResolver.class.equals(localeResolverClass))
+                {
+                    LocaleResolver localeResolver = BeanProvider.getContextualReference(localeResolverClass);
 
-                resolvedLocale = localeResolver.getLocale();
+                    resolvedLocale = localeResolver.getLocale();
+                }
+
+                String messageBundleName = method.getDeclaringClass().getName();
+                resolvedMessageTemplate = new DefaultMessageResolver(messageBundleName, resolvedLocale)
+                    .getMessage(messageTemplate.value());
             }
 
-            String messageBundleName = method.getDeclaringClass().getName();
-            messageTemplate = new DefaultMessageResolver(messageBundleName, resolvedLocale).getMessage(message.value());
-        }
+            Class<? extends MessageInterpolator> messageInterpolatorClass =
+                    ClassUtils.tryToLoadClassForName(messageContextConfig.messageInterpolator().getName());
 
-        Class<? extends MessageInterpolator> messageInterpolatorClass =
-                ClassUtils.tryToLoadClassForName(messageContextConfig.messageInterpolator().getName());
+            String result = resolvedMessageTemplate;
 
-        String result = messageTemplate;
+            if (!MessageInterpolator.class.equals(messageInterpolatorClass))
+            {
+                MessageInterpolator messageInterpolator = BeanProvider.getContextualReference(messageInterpolatorClass);
+                result = messageInterpolator.interpolate(resolvedMessageTemplate, args);
+            }
 
-        if (!MessageInterpolator.class.equals(messageInterpolatorClass))
-        {
-            MessageInterpolator messageInterpolator = BeanProvider.getContextualReference(messageInterpolatorClass);
-            result = messageInterpolator.interpolate(messageTemplate, args);
+            return result;
         }
+        else
+        {
+            if (String.class.isAssignableFrom(method.getReturnType()))
+            {
+                return messageContext.message().text(messageTemplate.value()).argument(arguments.toArray()).toText();
+            }
 
-        return result;
+            return messageContext.message().text(messageTemplate.value()).argument(arguments.toArray()).create();
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageContextProducer.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageContextProducer.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageContextProducer.java
new file mode 100644
index 0000000..b45398f
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageContextProducer.java
@@ -0,0 +1,62 @@
+/*
+ * 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.impl.message;
+
+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 javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.Typed;
+
+@ApplicationScoped
+@SuppressWarnings("UnusedDeclaration")
+public class MessageContextProducer
+{
+    @Produces
+    @Typed(MessageContext.class)
+    @Dependent
+    protected MessageContext createDefaultMessageContext(Instance<MessageResolver> customMessageResolver,
+                                                         Instance<MessageInterpolator> customMessageInterpolator,
+                                                         Instance<LocaleResolver> customLocalResolver)
+    {
+        MessageContext.Config messageContextConfig = new DefaultMessageContext().config();
+
+        if (!customMessageResolver.isUnsatisfied())
+        {
+            messageContextConfig.change().messageResolver(customMessageResolver.get());
+        }
+
+        if (!customMessageInterpolator.isUnsatisfied())
+        {
+            messageContextConfig.change().messageInterpolator(customMessageInterpolator.get());
+        }
+
+        if (!customLocalResolver.isUnsatisfied())
+        {
+            messageContextConfig.change().localeResolver(customLocalResolver.get());
+        }
+
+        return messageContextConfig.use().create();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/UnmodifiableMessageContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/UnmodifiableMessageContext.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/UnmodifiableMessageContext.java
new file mode 100644
index 0000000..859e4c5
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/UnmodifiableMessageContext.java
@@ -0,0 +1,61 @@
+/*
+ * 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.impl.message;
+
+import org.apache.deltaspike.core.api.message.MessageContext;
+
+import javax.enterprise.inject.Typed;
+import java.util.Locale;
+
+/**
+ * {@link MessageContext} which doesn't support changes
+ */
+@Typed()
+class UnmodifiableMessageContext implements MessageContext
+{
+    private static final long serialVersionUID = -4730350864157813259L;
+    private MessageContext messageContext;
+
+    UnmodifiableMessageContext(MessageContext messageContext)
+    {
+        this.messageContext = messageContext;
+    }
+
+    @Override
+    public MessageContext.Config config()
+    {
+        return new UnmodifiableMessageContextConfig(messageContext.config());
+    }
+
+    /*
+     * generated
+     */
+
+    @Override
+    public MessageBuilder message()
+    {
+        return messageContext.message();
+    }
+
+    @Override
+    public Locale getLocale()
+    {
+        return messageContext.getLocale();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/UnmodifiableMessageContextConfig.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/UnmodifiableMessageContextConfig.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/UnmodifiableMessageContextConfig.java
new file mode 100644
index 0000000..f224da0
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/UnmodifiableMessageContextConfig.java
@@ -0,0 +1,77 @@
+/*
+ * 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.impl.message;
+
+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 javax.enterprise.inject.Typed;
+
+/**
+ * generated
+ */
+@Typed()
+class UnmodifiableMessageContextConfig implements MessageContext.Config
+{
+    private MessageContext.Config messageContextConfig;
+
+    UnmodifiableMessageContextConfig(MessageContext.Config messageContextConfig)
+    {
+        this.messageContextConfig = messageContextConfig;
+    }
+
+    @Override
+    public MessageContextBuilder use()
+    {
+        //it's ok to delegate - the call of #use creates a new instance of the context - the old context is untouched
+        return this.messageContextConfig.use();
+    }
+
+
+    @Override
+    public MessageContextBuilder change()
+    {
+        throw new IllegalStateException(MessageContext.Config.class.getName() +
+                "is readonly after the call of MessageContext#message");
+    }
+
+    /*
+     * generated
+     */
+
+    @Override
+    public MessageInterpolator getMessageInterpolator()
+    {
+        return messageContextConfig.getMessageInterpolator();
+    }
+
+    @Override
+    public MessageResolver getMessageResolver()
+    {
+        return messageContextConfig.getMessageResolver();
+    }
+
+    @Override
+    public LocaleResolver getLocaleResolver()
+    {
+        return messageContextConfig.getLocaleResolver();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/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
new file mode 100644
index 0000000..bfcbb10
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageContextTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.LocaleResolver;
+import org.apache.deltaspike.core.api.message.MessageContext;
+import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
+import org.apache.deltaspike.core.impl.message.MessageBundleExtension;
+import org.apache.deltaspike.test.util.ArchiveUtils;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.enterprise.inject.spi.Extension;
+import javax.inject.Inject;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for {@link MessageContext}
+ */
+@RunWith(Arquillian.class)
+public class MessageContextTest
+{
+    @Inject
+    private SimpleMessage simpleMessage;
+
+    @Inject
+    private MessageContext messageContext;
+
+    /**
+     * X TODO creating a WebArchive is only a workaround because JavaArchive
+     * cannot contain other archives.
+     */
+    @Deployment
+    public static WebArchive deploy()
+    {
+        new BeanManagerProvider()
+        {
+            @Override
+            public void setTestMode()
+            {
+                super.setTestMode();
+            }
+        }.setTestMode();
+
+        JavaArchive testJar = ShrinkWrap
+                .create(JavaArchive.class, "messageContextTest.jar")
+                .addPackage("org.apache.deltaspike.test.core.api.message")
+                .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+
+        return ShrinkWrap
+                .create(WebArchive.class, "messageContextTest.war")
+                .addAsLibraries(ArchiveUtils.getDeltaSpikeCoreArchive())
+                .addAsLibraries(testJar)
+                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
+                .addAsServiceProvider(Extension.class,
+                        MessageBundleExtension.class);
+    }
+
+    @Test
+    public void testSimpleMessage()
+    {
+        assertEquals("Welcome to DeltaSpike",
+                this.simpleMessage.welcomeTo(this.messageContext, "DeltaSpike").toString());
+    }
+
+    @Test
+    public void resolveTextTest()
+    {
+        LocaleResolver localeResolver = new TestLocalResolver();
+
+        String messageText = this.messageContext.config()
+                .use()
+                    .localeResolver(localeResolver)
+                    .messageResolver(new TestMessageResolver(localeResolver))
+                .create().message().text("{hello}").toText();
+
+        assertEquals("test message", messageText);
+    }
+
+    @Test
+    public void resolveGermanMessageTextTest()
+    {
+        LocaleResolver localeResolver = new TestGermanLocaleResolver();
+        String messageText = this.messageContext.config()
+                .use()
+                    .localeResolver(localeResolver)
+                    .messageResolver(new TestMessageResolver(localeResolver))
+                .create().message().text("{hello}").toText();
+
+        assertEquals("Test Nachricht", messageText);
+    }
+
+    @Test
+    public void createInvalidMessageTest()
+    {
+        String messageText = this.messageContext.message().text("{xyz123}").toText();
+
+        assertEquals("???xyz123???", messageText);
+    }
+
+    @Test
+    public void createInvalidMessageWithArgumentsTest()
+    {
+        String messageText = this.messageContext.message().text("{xyz123}").argument("123").argument("456").argument("789").toText();
+
+        assertEquals("???xyz123??? (123,456,789)", messageText);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageTest.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageTest.java
index f5a8e6b..cf48f91 100644
--- a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageTest.java
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageTest.java
@@ -36,7 +36,7 @@ import javax.inject.Inject;
 import static org.junit.Assert.assertEquals;
 
 /**
- * Tests for {@link org.apache.deltaspike.core.api.message.annotation.Message}
+ * Tests for {@link org.apache.deltaspike.core.api.message.annotation.MessageTemplate}
  */
 @RunWith(Arquillian.class)
 public class MessageTest

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/SimpleMessage.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/SimpleMessage.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/SimpleMessage.java
index 1781682..e77805f 100644
--- a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/SimpleMessage.java
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/SimpleMessage.java
@@ -18,14 +18,17 @@
  */
 package org.apache.deltaspike.test.core.api.message;
 
-import org.apache.deltaspike.core.api.message.annotation.Message;
-import org.apache.deltaspike.core.api.message.annotation.Message;
-import org.apache.deltaspike.core.api.message.annotation.MessageBundle;
+import org.apache.deltaspike.core.api.message.Message;
+import org.apache.deltaspike.core.api.message.MessageContext;
+import org.apache.deltaspike.core.api.message.annotation.MessageTemplate;
 import org.apache.deltaspike.core.api.message.annotation.MessageBundle;
 
 @MessageBundle
 public interface SimpleMessage
 {
-    @Message("Welcome to DeltaSpike")
+    @MessageTemplate("Welcome to DeltaSpike")
     String welcomeToDeltaSpike();
+
+    @MessageTemplate("Welcome to %s")
+    Message welcomeTo(MessageContext messageContext, String name);
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/SimpleMessageTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/SimpleMessageTest.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/SimpleMessageTest.java
index 9d80a50..250ad52 100644
--- a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/SimpleMessageTest.java
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/SimpleMessageTest.java
@@ -36,7 +36,7 @@ import javax.inject.Inject;
 import static org.junit.Assert.assertEquals;
 
 /**
- * Tests for {@link org.apache.deltaspike.core.api.message.annotation.Message}
+ * Tests for {@link org.apache.deltaspike.core.api.message.annotation.MessageTemplate}
  */
 @RunWith(Arquillian.class)
 public class SimpleMessageTest
@@ -61,12 +61,12 @@ public class SimpleMessageTest
         }.setTestMode();
 
         JavaArchive testJar = ShrinkWrap
-                .create(JavaArchive.class, "messageTest.jar")
+                .create(JavaArchive.class, "simpleMessageTest.jar")
                 .addPackage("org.apache.deltaspike.test.core.api.message")
                 .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
 
         return ShrinkWrap
-                .create(WebArchive.class, "messageTest.war")
+                .create(WebArchive.class, "simpleMessageTest.war")
                 .addAsLibraries(ArchiveUtils.getDeltaSpikeCoreArchive())
                 .addAsLibraries(testJar)
                 .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestGermanLocaleResolver.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestGermanLocaleResolver.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestGermanLocaleResolver.java
new file mode 100644
index 0000000..4d2609a
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestGermanLocaleResolver.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;
+
+import org.apache.deltaspike.core.api.message.LocaleResolver;
+
+import javax.enterprise.inject.Typed;
+import java.util.Locale;
+
+@Typed()
+class TestGermanLocaleResolver implements LocaleResolver
+{
+    private static final long serialVersionUID = 1927000487639667775L;
+
+    @Override
+    public Locale getLocale()
+    {
+        return Locale.GERMAN;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestLocalResolver.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestLocalResolver.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestLocalResolver.java
new file mode 100644
index 0000000..611d524
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestLocalResolver.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;
+
+import org.apache.deltaspike.core.api.message.LocaleResolver;
+
+import javax.enterprise.context.ApplicationScoped;
+import java.util.Locale;
+
+@ApplicationScoped
+public class TestLocalResolver implements LocaleResolver
+{
+    private static final long serialVersionUID = 6947516315363672494L;
+
+    @Override
+    public Locale getLocale()
+    {
+        return Locale.ENGLISH;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessageInterpolator.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessageInterpolator.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessageInterpolator.java
index f521350..20f7e6e 100644
--- a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessageInterpolator.java
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessageInterpolator.java
@@ -25,6 +25,8 @@ import javax.enterprise.context.ApplicationScoped;
 @ApplicationScoped
 public class TestMessageInterpolator implements MessageInterpolator
 {
+    private static final long serialVersionUID = 5636914399691923602L;
+
     @Override
     public String interpolate(String messageText, Object[] arguments)
     {

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessageResolver.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessageResolver.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessageResolver.java
new file mode 100644
index 0000000..40fb4ed
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessageResolver.java
@@ -0,0 +1,78 @@
+/*
+ * 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.LocaleResolver;
+import org.apache.deltaspike.core.api.message.MessageResolver;
+import org.apache.deltaspike.core.util.PropertyFileUtils;
+
+import javax.enterprise.context.Dependent;
+import javax.inject.Inject;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+@Dependent
+public class TestMessageResolver implements MessageResolver
+{
+    private static final long serialVersionUID = -7977480064291950923L;
+
+    private ResourceBundle messageBundle;
+
+    protected TestMessageResolver()
+    {
+    }
+
+    @Inject
+    public TestMessageResolver(LocaleResolver localeResolver)
+    {
+        ResourceBundle resolvedBundle;
+        try
+        {
+            resolvedBundle = PropertyFileUtils
+                .getResourceBundle(TestMessages.class.getName(), localeResolver.getLocale());
+        }
+        catch (MissingResourceException e)
+        {
+            //X TODO log it
+            resolvedBundle = null;
+        }
+
+        this.messageBundle = resolvedBundle;
+    }
+
+    @Override
+    public String getMessage(String messageTemplate)
+    {
+        if (this.messageBundle != null && messageTemplate != null &&
+                messageTemplate.startsWith("{") && messageTemplate.endsWith("}"))
+        {
+            messageTemplate = messageTemplate.substring(1, messageTemplate.length() - 1);
+            try
+            {
+                return this.messageBundle.getString(messageTemplate);
+            }
+            catch (MissingResourceException e)
+            {
+                return messageTemplate;
+            }
+        }
+
+        return messageTemplate;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessages.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessages.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessages.java
index 1c3c230..d130db8 100644
--- a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessages.java
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/TestMessages.java
@@ -18,24 +18,24 @@
  */
 package org.apache.deltaspike.test.core.api.message;
 
-import org.apache.deltaspike.core.api.message.annotation.Message;
-import org.apache.deltaspike.core.api.message.annotation.Message;
+import org.apache.deltaspike.core.api.message.annotation.MessageTemplate;
 import org.apache.deltaspike.core.api.message.annotation.MessageBundle;
-import org.apache.deltaspike.core.api.message.annotation.MessageBundle;
-import org.apache.deltaspike.core.api.message.annotation.MessageContextConfig;
 import org.apache.deltaspike.core.api.message.annotation.MessageContextConfig;
 
 @MessageBundle
-@MessageContextConfig(messageInterpolator = TestMessageInterpolator.class)
+@MessageContextConfig(
+        messageInterpolator = TestMessageInterpolator.class,
+        localeResolver = TestLocalResolver.class
+)
 public interface TestMessages
 {
-    @Message("Spotted %s jays")
+    @MessageTemplate("Spotted %s jays")
     String numberOfJaysSpotted(int number);
 
-    @Message("{welcome_to_deltaspike}")
+    @MessageTemplate("{welcome_to_deltaspike}")
     String welcomeToDeltaSpike();
 
-    @Message("{welcome_to}")
+    @MessageTemplate("{welcome_to}")
     String welcomeTo(String name);
 
     //X TODO

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages.properties
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages.properties b/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages.properties
deleted file mode 100644
index 642921f..0000000
--- a/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#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.
-
-welcome_to=Welcome to %s
-welcome_to_deltaspike=Welcome to DeltaSpike
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages_de.properties
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages_de.properties b/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages_de.properties
new file mode 100644
index 0000000..f7ac5a5
--- /dev/null
+++ b/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages_de.properties
@@ -0,0 +1,18 @@
+#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.
+
+hello=Test Nachricht

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/2975d337/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages_en.properties
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages_en.properties b/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages_en.properties
new file mode 100644
index 0000000..1481e50
--- /dev/null
+++ b/deltaspike/core/impl/src/test/resources/org/apache/deltaspike/test/core/api/message/TestMessages_en.properties
@@ -0,0 +1,21 @@
+#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.
+
+welcome_to=Welcome to %s
+welcome_to_deltaspike=Welcome to DeltaSpike
+
+hello=test message