You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by ke...@apache.org on 2012/04/05 16:35:34 UTC

[3/3] git commit: DELTASPIKE-146: Submitted on behalf of a third-party: Red Hat, Inc. under the terms of the ALv2

DELTASPIKE-146: Submitted on behalf of a third-party: Red Hat, Inc. under the terms of the ALv2


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

Branch: refs/heads/master
Commit: 11f953895eeec2d321e7ffefe7eb4a4a590dbfd7
Parents: 3fe012a
Author: Ken Finnigan <ke...@kenfinnigan.me>
Authored: Thu Apr 5 09:47:46 2012 -0400
Committer: Ken Finnigan <ke...@kenfinnigan.me>
Committed: Thu Apr 5 09:53:38 2012 -0400

----------------------------------------------------------------------
 .../core/api/literal/MessageBundleLiteral.java     |   32 +
 .../apache/deltaspike/core/api/message/Cause.java  |   40 ++
 .../deltaspike/core/api/message/Message.java       |   68 ++
 .../deltaspike/core/api/message/MessageBundle.java |   40 ++
 .../core/impl/message/AbstractImmutableBean.java   |  219 +++++++
 .../deltaspike/core/impl/message/Arrays2.java      |   54 ++
 .../core/impl/message/ImmutableNarrowingBean.java  |  128 ++++
 .../core/impl/message/MessageBundleExtension.java  |  108 ++++
 .../message/MessageBundleInvocationHandler.java    |  121 ++++
 .../core/impl/message/MessageFactory.java          |   51 ++
 .../core/impl/message/NarrowingBeanBuilder.java    |  480 +++++++++++++++
 .../core/impl/message/TypedMessageBundle.java      |   44 ++
 .../impl/message/TypedMessageBundleProducer.java   |   44 ++
 .../services/javax.enterprise.inject.spi.Extension |    3 +-
 .../test/core/api/message/BirdMessages.java        |   28 +
 .../deltaspike/test/core/api/message/Jay.java      |   35 +
 .../test/core/api/message/MessageTest.java         |   81 +++
 17 files changed, 1575 insertions(+), 1 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageBundleLiteral.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageBundleLiteral.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageBundleLiteral.java
new file mode 100644
index 0000000..03b73bc
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageBundleLiteral.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.core.api.literal;
+
+import javax.enterprise.util.AnnotationLiteral;
+
+import org.apache.deltaspike.core.api.message.MessageBundle;
+
+/**
+ * Literal for {@link MessageBundle}
+ */
+public class MessageBundleLiteral extends AnnotationLiteral<MessageBundle>
+        implements MessageBundle
+{
+    private static final long serialVersionUID = 5116646785333766333L;
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Cause.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Cause.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Cause.java
new file mode 100644
index 0000000..de23600
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Cause.java
@@ -0,0 +1,40 @@
+/*
+ * 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 static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Mark a parameter as being the "exception cause" parameter rather than a
+ * positional format parameter.
+ * 
+ * @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
+ */
+@Retention(CLASS)
+@Target(PARAMETER)
+@Documented
+public @interface Cause
+{
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/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..fac3dda
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Message.java
@@ -0,0 +1,68 @@
+/*
+ * 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 static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target(METHOD)
+@Retention(RUNTIME)
+@Documented
+public @interface Message
+{
+
+    /**
+     * The default format string of this message.
+     *
+     * @return the format string
+     */
+    String value();
+
+    /**
+     * The format type of this method (defaults to {@link Format#PRINTF}).
+     *
+     * @return the format type
+     */
+    Format format() default Format.PRINTF;
+
+    /**
+     * The possible format types.
+     */
+    enum Format
+    {
+
+        /**
+         * A {@link java.util.Formatter}-type format string.
+         */
+        PRINTF,
+        /**
+         * A {@link java.text.MessageFormat}-type format string.
+         */
+        MESSAGE_FORMAT,
+        /**
+         * An expression language type format string.
+         */
+        EXP_LANG
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageBundle.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageBundle.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageBundle.java
new file mode 100644
index 0000000..96c50f7
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageBundle.java
@@ -0,0 +1,40 @@
+/*
+ * 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 static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+@Target({ TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Qualifier
+@Documented
+public @interface MessageBundle
+{
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/AbstractImmutableBean.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/AbstractImmutableBean.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/AbstractImmutableBean.java
new file mode 100644
index 0000000..58d1875
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/AbstractImmutableBean.java
@@ -0,0 +1,219 @@
+/*
+ * 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 java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.InjectionPoint;
+
+import org.apache.deltaspike.core.api.literal.DefaultLiteral;
+
+/**
+ * <p>
+ * A base class for implementing {@link Bean}. The attributes are immutable, and
+ * collections are defensively copied on instantiation. It uses the defaults
+ * from the specification for properties if not specified.
+ * </p>
+ * <p/>
+ * <p>
+ * This class does not provide any bean lifecycle operations
+ * </p>
+ * 
+ * @see ImmutableBean
+ * @see ImmutableNarrowingBean
+ */
+abstract class AbstractImmutableBean<T> implements Bean<T>
+{
+    private transient Logger log = Logger.getLogger(AbstractImmutableBean.class
+            .getName());
+
+    private final Class<?> beanClass;
+    private final String name;
+    private final Set<Annotation> qualifiers;
+    private final Class<? extends Annotation> scope;
+    private final Set<Class<? extends Annotation>> stereotypes;
+    private final Set<Type> types;
+    private final boolean alternative;
+    private final boolean nullable;
+    private final Set<InjectionPoint> injectionPoints;
+    private final String toString;
+
+    /**
+     * Create a new, immutable bean. All arguments passed as collections are
+     * defensively copied.
+     * 
+     * @param beanClass
+     *            The Bean class, may not be null
+     * @param name
+     *            The bean name
+     * @param qualifiers
+     *            The bean's qualifiers, if null, a singleton set of
+     *            {@link Default} is used
+     * @param scope
+     *            The bean's scope, if null, the default scope of
+     *            {@link Dependent} is used
+     * @param stereotypes
+     *            The bean's stereotypes, if null, an empty set is used
+     * @param types
+     *            The bean's types, if null, the beanClass and {@link Object}
+     *            will be used
+     * @param alternative
+     *            True if the bean is an alternative
+     * @param nullable
+     *            True if the bean is nullable
+     * @param injectionPoints
+     *            the bean's injection points, if null an empty set is used
+     * @param beanLifecycle
+     *            Handler for {@link #create(CreationalContext)} and
+     *            {@link #destroy(Object, CreationalContext)}
+     * @throws IllegalArgumentException
+     *             if the beanClass is null
+     */
+    public AbstractImmutableBean(Class<?> beanClass, String name,
+            Set<Annotation> qualifiers, Class<? extends Annotation> scope,
+            Set<Class<? extends Annotation>> stereotypes, Set<Type> types,
+            boolean alternative, boolean nullable,
+            Set<InjectionPoint> injectionPoints, String toString)
+    {
+        if (beanClass == null)
+        {
+            throw new IllegalArgumentException("beanClass cannot be null");
+        }
+        this.beanClass = beanClass;
+        this.name = name;
+        if (qualifiers == null)
+        {
+            this.qualifiers = Collections
+                    .<Annotation> singleton(new DefaultLiteral());
+            log.finest("No qualifers provided for bean class " + beanClass
+                    + ", using singleton set of @Default");
+        }
+        else
+        {
+            this.qualifiers = new HashSet<Annotation>(qualifiers);
+        }
+        if (scope == null)
+        {
+            this.scope = Dependent.class;
+            log.finest("No scope provided for bean class " + beanClass
+                    + ", using @Dependent");
+        }
+        else
+        {
+            this.scope = scope;
+        }
+        if (stereotypes == null)
+        {
+            this.stereotypes = Collections.emptySet();
+        }
+        else
+        {
+            this.stereotypes = new HashSet<Class<? extends Annotation>>(
+                    stereotypes);
+        }
+        if (types == null)
+        {
+            this.types = Arrays2.<Type> asSet(Object.class, beanClass);
+            log.finest("No types provided for bean class " + beanClass
+                    + ", using [java.lang.Object.class, " + beanClass.getName()
+                    + ".class]");
+        }
+        else
+        {
+            this.types = new HashSet<Type>(types);
+        }
+        if (injectionPoints == null)
+        {
+            this.injectionPoints = Collections.emptySet();
+        }
+        else
+        {
+            this.injectionPoints = new HashSet<InjectionPoint>(injectionPoints);
+        }
+        this.alternative = alternative;
+        this.nullable = nullable;
+        if (toString != null)
+        {
+            this.toString = toString;
+        }
+        else
+        {
+            this.toString = "Custom Bean with bean class " + beanClass
+                    + " and qualifiers " + qualifiers;
+        }
+    }
+
+    public Class<?> getBeanClass()
+    {
+        return beanClass;
+    }
+
+    public Set<InjectionPoint> getInjectionPoints()
+    {
+        return injectionPoints;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public Set<Annotation> getQualifiers()
+    {
+        return Collections.unmodifiableSet(qualifiers);
+    }
+
+    public Class<? extends Annotation> getScope()
+    {
+        return scope;
+    }
+
+    public Set<Class<? extends Annotation>> getStereotypes()
+    {
+        return Collections.unmodifiableSet(stereotypes);
+    }
+
+    public Set<Type> getTypes()
+    {
+        return Collections.unmodifiableSet(types);
+    }
+
+    public boolean isAlternative()
+    {
+        return alternative;
+    }
+
+    public boolean isNullable()
+    {
+        return nullable;
+    }
+
+    @Override
+    public String toString()
+    {
+        return toString;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/Arrays2.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/Arrays2.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/Arrays2.java
new file mode 100644
index 0000000..2c8a715
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/Arrays2.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.impl.message;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A collection of utilities for working with Arrays that goes beyond that in
+ * the JDK.
+ */
+class Arrays2
+{
+
+    private Arrays2()
+    {
+    }
+
+    /**
+     * Create a set from an array. If the array contains duplicate objects, the
+     * last object in the array will be placed in resultant set.
+     * 
+     * @param <T>
+     *            the type of the objects in the set
+     * @param array
+     *            the array from which to create the set
+     * @return the created sets
+     */
+    public static <T> Set<T> asSet(T... array)
+    {
+        Set<T> result = new HashSet<T>();
+        for (T a : array)
+        {
+            result.add(a);
+        }
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/ImmutableNarrowingBean.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/ImmutableNarrowingBean.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/ImmutableNarrowingBean.java
new file mode 100644
index 0000000..0c7fdc5
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/ImmutableNarrowingBean.java
@@ -0,0 +1,128 @@
+/*
+ * 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 java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Set;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+
+import org.apache.deltaspike.core.util.Reflections;
+
+/**
+ * <p>
+ * A narrowing bean allows you to build a general purpose bean (likely a
+ * producer method), and register it for a narrowed type (or qualifiers). For
+ * example, you could create a producer method which uses an a String ID to
+ * located an object (the object can have any class):
+ * </p>
+ * <p/>
+ * 
+ * <pre>
+ * &#064;Produces
+ * // Use some synthetic scope to prevent this from interfering with other
+ * // resolutions
+ * &#064;MyProducer
+ * Object produce(InjectionPoint ip)
+ * {
+ *     String id = ip.getAnnotated().getAnnotation(Id.class).value();
+ *     // Lookup and return the object for the id
+ * }
+ * </pre>
+ * <p/>
+ * <p>
+ * The delegate bean <em>must</em> return an object which can be cast to the
+ * type <code>T</code>, otherwise a {@link ClassCastException} will be thrown at
+ * runtime when the bean is created.
+ * </p>
+ * <p/>
+ * <p>
+ * You can then register a narrowing bean for each type you need:
+ * </p>
+ * <p/>
+ * 
+ * <pre>
+ * event.addBean(new NarrowingBeanBuilder&lt;T&gt;(delegateBean).readFromType(type)
+ *         .create());
+ * </pre>
+ * <p/>
+ * <p>
+ * {@link ImmutableNarrowingBean} will use the annotations on
+ * <code>defininingType</code> to discover the qualifiers, types, scope,
+ * stereotypes of the bean, as well as determine it's name (if any) and whether
+ * it is an alternative.
+ * </p>
+ * <p/>
+ * <p>
+ * The attributes are immutable, and collections are defensively copied on
+ * instantiation. It uses the defaults from the specification for properties if
+ * not specified.
+ * </p>
+ * 
+ * @see NarrowingBeanBuilder
+ * @see ImmutablePassivationCapableNarrowingBean
+ */
+class ImmutableNarrowingBean<T> extends AbstractImmutableBean<T>
+{
+
+    private final Bean<Object> delegate;
+
+    /**
+     * Instantiate a new {@link ImmutableNarrowingBean}.
+     * 
+     * @param delegate
+     *            the bean to delegate the lifecycle to
+     * @param name
+     *            the name of the bean
+     * @param qualifiers
+     *            the qualifiers of the bean
+     * @param scope
+     *            the scope of the bean
+     * @param stereotypes
+     *            the bean's stereotypes
+     * @param types
+     *            the types of the bean
+     * @param alternative
+     *            whether the bean is an alternative
+     */
+    public ImmutableNarrowingBean(Bean<Object> delegate, String name,
+            Set<Annotation> qualifiers, Class<? extends Annotation> scope,
+            Set<Class<? extends Annotation>> stereotypes, Set<Type> types,
+            boolean alternative, boolean nullable, String toString)
+    {
+        super(delegate.getBeanClass(), name, qualifiers, scope, stereotypes,
+                types, alternative, nullable, delegate.getInjectionPoints(),
+                toString);
+        this.delegate = delegate;
+    }
+
+    public T create(CreationalContext<T> creationalContext)
+    {
+        return Reflections.<T> cast(delegate.create(Reflections
+                .<CreationalContext<Object>> cast(creationalContext)));
+    }
+
+    public void destroy(T instance, CreationalContext<T> creationalContext)
+    {
+        delegate.destroy(instance,
+                Reflections.<CreationalContext<Object>> cast(creationalContext));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/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
new file mode 100644
index 0000000..a992c89
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java
@@ -0,0 +1,108 @@
+/*
+ * 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 java.util.Collection;
+import java.util.HashSet;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.AfterDeploymentValidation;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.enterprise.inject.spi.ProcessProducerMethod;
+
+import org.apache.deltaspike.core.api.literal.MessageBundleLiteral;
+import org.apache.deltaspike.core.api.message.MessageBundle;
+import org.apache.deltaspike.core.spi.activation.Deactivatable;
+
+public class MessageBundleExtension implements Extension, Deactivatable
+{
+    private final Collection<AnnotatedType<?>> messageBundleTypes;
+    private Bean<Object> bundleProducerBean;
+
+    public MessageBundleExtension()
+    {
+        this.messageBundleTypes = new HashSet<AnnotatedType<?>>();
+    }
+
+    void detectInterfaces(@Observes ProcessAnnotatedType<?> event,
+            BeanManager beanManager)
+    {
+        AnnotatedType<?> type = event.getAnnotatedType();
+        if (type.isAnnotationPresent(MessageBundle.class))
+        {
+            messageBundleTypes.add(type);
+        }
+    }
+
+    // according to the Java EE 6 javadoc (the authority according to the powers
+    // that be),
+    // this is the correct order of type parameters
+    void detectProducers(
+            @Observes ProcessProducerMethod<Object, TypedMessageBundleProducer> event)
+    {
+        captureProducers(event.getAnnotatedProducerMethod(), event.getBean());
+    }
+
+    // according to JSR-299 spec, this is the correct order of type parameters
+    @Deprecated
+    void detectProducersInverted(
+            @Observes ProcessProducerMethod<TypedMessageBundleProducer, Object> event)
+    {
+        captureProducers(event.getAnnotatedProducerMethod(), event.getBean());
+    }
+
+    @SuppressWarnings("unchecked")
+    void captureProducers(AnnotatedMethod<?> method, Bean<?> bean)
+    {
+        if (method.isAnnotationPresent(TypedMessageBundle.class))
+        {
+            this.bundleProducerBean = (Bean<Object>) bean;
+        }
+    }
+
+    void installBeans(@Observes AfterBeanDiscovery event,
+            BeanManager beanManager)
+    {
+        for (AnnotatedType<?> type : messageBundleTypes)
+        {
+            event.addBean(createMessageBundleBean(bundleProducerBean, type,
+                    beanManager));
+        }
+    }
+
+    private static <T> Bean<T> createMessageBundleBean(Bean<Object> delegate,
+            AnnotatedType<T> type, BeanManager beanManager)
+    {
+        return new NarrowingBeanBuilder<T>(delegate, beanManager)
+                .types(type.getBaseType(), Object.class)
+                .addQualifier(new MessageBundleLiteral()).create();
+    }
+
+    void cleanup(@Observes AfterDeploymentValidation event)
+    {
+        this.messageBundleTypes.clear();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/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
new file mode 100644
index 0000000..ca99a17
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleInvocationHandler.java
@@ -0,0 +1,121 @@
+/*
+ * 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 java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.deltaspike.core.api.message.Cause;
+import org.apache.deltaspike.core.api.message.Message;
+
+class MessageBundleInvocationHandler implements InvocationHandler
+{
+
+    /**
+     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
+     *      java.lang.reflect.Method, java.lang.Object[])
+     */
+    @Override
+    public Object invoke(final Object proxy, final Method method,
+            final Object[] args) throws Throwable
+    {
+        final Message message = method.getAnnotation(Message.class);
+        if (message == null)
+        {
+            // nothing to do...
+            return null;
+        }
+        final Annotation[][] parameterAnnotations = method
+                .getParameterAnnotations();
+        ArrayList<Object> newArgs = new ArrayList<Object>();
+        Throwable cause = extractCause(parameterAnnotations, args, newArgs);
+        String result;
+        switch (message.format())
+        {
+            case PRINTF:
+            {
+                result = String.format(message.value(), newArgs.toArray());
+                break;
+            }
+            case MESSAGE_FORMAT:
+            {
+                result = MessageFormat.format(message.value(),
+                        newArgs.toArray());
+                break;
+            }
+            default:
+                throw new IllegalStateException();
+        }
+        final Class<?> returnType = method.getReturnType();
+        if (Throwable.class.isAssignableFrom(returnType))
+        {
+            // the return type is an exception
+            if (cause != null)
+            {
+                final Constructor<?> constructor = returnType.getConstructor(
+                        String.class, Throwable.class);
+                return constructor.newInstance(result, cause);
+            }
+            else
+            {
+                final Constructor<?> constructor = returnType
+                        .getConstructor(String.class);
+                return constructor.newInstance(result);
+            }
+        }
+        else
+        {
+            return result;
+        }
+    }
+
+    protected static Throwable extractCause(
+            final Annotation[][] parameterAnnotations, final Object[] args,
+            final List<Object> newArgs)
+    {
+        Throwable cause = null;
+        for (int i = 0; i < parameterAnnotations.length; i++)
+        {
+            Annotation[] annotations = parameterAnnotations[i];
+            boolean found = false;
+            for (Annotation annotation : annotations)
+            {
+                if (annotation instanceof Cause)
+                {
+                    if (cause == null)
+                    {
+                        cause = (Throwable) args[i];
+                    }
+                    found = true;
+                }
+            }
+            if (!found)
+            {
+                newArgs.add(args[i]);
+            }
+        }
+        return cause;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageFactory.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageFactory.java
new file mode 100644
index 0000000..a966317
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageFactory.java
@@ -0,0 +1,51 @@
+/*
+ * 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 java.lang.reflect.Proxy;
+
+/**
+ * A factory class to produce message bundle implementations.
+ */
+final class MessageFactory
+{
+
+    private MessageFactory()
+    {
+    }
+
+    /**
+     * Get a message bundle of the given type. Equivalent to
+     * <code>{@link #getBundle(Class, java.util.Locale) getBundle}(type, Locale.getDefault())</code>
+     * .
+     * 
+     * @param type
+     *            the bundle type class
+     * @param <T>
+     *            the bundle type
+     * @return the bundle
+     */
+    public static <T> T getBundle(Class<T> type)
+    {
+        return type.cast(Proxy.newProxyInstance(type.getClassLoader(),
+                new Class<?>[]
+                { type }, new MessageBundleInvocationHandler()));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NarrowingBeanBuilder.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NarrowingBeanBuilder.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NarrowingBeanBuilder.java
new file mode 100644
index 0000000..49096a4
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NarrowingBeanBuilder.java
@@ -0,0 +1,480 @@
+/*
+ * 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 static org.apache.deltaspike.core.impl.message.Arrays2.asSet;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Alternative;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Named;
+
+import org.apache.deltaspike.core.api.literal.AnyLiteral;
+import org.apache.deltaspike.core.api.literal.DefaultLiteral;
+
+/**
+ * Builder for {@link ImmutableNarrowingBean} and
+ * {@link ImmutablePassivationCapableNarrowingBean}.
+ * 
+ * @see ImmutableNarrowingBean
+ * @see ImmutablePassivationCapableNarrowingBean
+ */
+class NarrowingBeanBuilder<T>
+{
+    private final Bean<Object> delegate;
+    private final BeanManager beanManager;
+    private Set<Type> types;
+    private Set<Annotation> qualifiers;
+    private String name;
+    private Class<? extends Annotation> scope;
+    private boolean alternative;
+    private boolean nullable;
+    private String toString;
+    private Set<Class<? extends Annotation>> stereotypes;
+    private boolean passivationCapable;
+    private String id;
+
+    /**
+     * Instantiate a new {@link NarrowingBeanBuilder}.
+     * 
+     * @param delegate
+     *            the delegate bean
+     */
+    public NarrowingBeanBuilder(Bean<Object> delegate, BeanManager beanManager)
+    {
+        this.delegate = delegate;
+        this.beanManager = beanManager;
+    }
+
+    /**
+     * Create a new {@link NarrowingBeanBuilder}, allowing Java to infer the
+     * type <code>T</code>.
+     * 
+     * @param <T>
+     *            the type of the bean
+     * @param delegate
+     *            the delegate bean
+     */
+    public static <T> NarrowingBeanBuilder<T> of(Bean<Object> delegate,
+            BeanManager beanManager)
+    {
+        return new NarrowingBeanBuilder<T>(delegate, beanManager);
+    }
+
+    /**
+     * <p>
+     * Read the {@link AnnotatedType}, creating a narrowing bean from the class
+     * and its annotations.
+     * </p>
+     * 
+     * @param type
+     *            the type to read
+     */
+    public NarrowingBeanBuilder<T> readFromType(AnnotatedType<T> type)
+    {
+        this.types = new HashSet<Type>(type.getTypeClosure());
+        this.qualifiers = new HashSet<Annotation>();
+        this.stereotypes = new HashSet<Class<? extends Annotation>>();
+        String name = null;
+        Class<? extends Annotation> scope = Dependent.class;
+        for (Annotation annotation : type.getAnnotations())
+        {
+            if (beanManager.isQualifier(annotation.annotationType()))
+            {
+                this.qualifiers.add(annotation);
+            }
+            else if (annotation.annotationType().equals(Named.class))
+            {
+                name = Named.class.cast(annotation).value();
+            }
+            else if (beanManager.isScope(annotation.annotationType()))
+            {
+                scope = annotation.annotationType();
+            }
+            else if (beanManager.isStereotype(annotation.annotationType()))
+            {
+                this.stereotypes.add(annotation.annotationType());
+            }
+        }
+        if (qualifiers.isEmpty())
+        {
+            this.qualifiers.add(new DefaultLiteral());
+        }
+        this.qualifiers.add(new AnyLiteral());
+        this.name = "".equals(name) ? null : name;
+        this.scope = scope;
+        this.alternative = type.isAnnotationPresent(Alternative.class);
+        return this;
+    }
+
+    /**
+     * Type closure currently defined for bean creation.
+     * 
+     * @return the type closure currently defined
+     */
+    public Set<Type> getTypes()
+    {
+        return types;
+    }
+
+    /**
+     * Define the type closure used for bean creation.
+     * 
+     * @param types
+     *            the type closure to use
+     */
+    public NarrowingBeanBuilder<T> types(Set<Type> types)
+    {
+        this.types = types;
+        return this;
+    }
+
+    /**
+     * Define the type closure used for bean creation.
+     * 
+     * @param types
+     *            the type closure to use
+     */
+    public NarrowingBeanBuilder<T> types(Type... types)
+    {
+        this.types = asSet(types);
+        return this;
+    }
+
+    /**
+     * Add to the type closure used for bean creation.
+     * 
+     * @param type
+     *            additional type to use
+     */
+    public NarrowingBeanBuilder<T> addType(Type type)
+    {
+        this.types.add(type);
+        return this;
+    }
+
+    /**
+     * Add to the type closure used for bean creation.
+     * 
+     * @param types
+     *            the additional types to use
+     */
+    public NarrowingBeanBuilder<T> addTypes(Type... types)
+    {
+        this.types.addAll(asSet(types));
+        return this;
+    }
+
+    /**
+     * Add to the type closure used for bean creation.
+     * 
+     * @param types
+     *            the additional types to use
+     */
+    public NarrowingBeanBuilder<T> addTypes(Collection<Type> types)
+    {
+        this.types.addAll(types);
+        return this;
+    }
+
+    /**
+     * Qualifiers currently defined for bean creation.
+     * 
+     * @return the qualifiers current defined
+     */
+    public Set<Annotation> getQualifiers()
+    {
+        return qualifiers;
+    }
+
+    /**
+     * Define the qualifiers used for bean creation.
+     * 
+     * @param qualifiers
+     *            the qualifiers to use
+     */
+    public NarrowingBeanBuilder<T> qualifiers(Set<Annotation> qualifiers)
+    {
+        this.qualifiers = qualifiers;
+        return this;
+    }
+
+    /**
+     * Define the qualifiers used for bean creation.
+     * 
+     * @param qualifiers
+     *            the qualifiers to use
+     */
+    public NarrowingBeanBuilder<T> qualifiers(Annotation... qualifiers)
+    {
+        this.qualifiers = asSet(qualifiers);
+        return this;
+    }
+
+    /**
+     * Add to the qualifiers used for bean creation.
+     * 
+     * @param qualifiers
+     *            the additional qualifier to use
+     */
+    public NarrowingBeanBuilder<T> addQualifier(Annotation qualifier)
+    {
+        this.qualifiers.add(qualifier);
+        return this;
+    }
+
+    /**
+     * Add to the qualifiers used for bean creation.
+     * 
+     * @param qualifiers
+     *            the additional qualifiers to use
+     */
+    public NarrowingBeanBuilder<T> addQualifiers(Annotation... qualifiers)
+    {
+        this.qualifiers.addAll(asSet(qualifiers));
+        return this;
+    }
+
+    /**
+     * Add to the qualifiers used for bean creation.
+     * 
+     * @param qualifiers
+     *            the additional qualifiers to use
+     */
+    public NarrowingBeanBuilder<T> addQualifiers(
+            Collection<Annotation> qualifiers)
+    {
+        this.qualifiers.addAll(qualifiers);
+        return this;
+    }
+
+    /**
+     * The name of the bean currently defined for bean creation.
+     * 
+     * @return the name of the bean or <code>null</code> if the bean has no name
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+    /**
+     * Define the name of the bean used for bean creation.
+     * 
+     * @param name
+     *            the name of the bean to use or <code>null</code> if the bean
+     *            should have no name
+     */
+    public NarrowingBeanBuilder<T> name(String name)
+    {
+        this.name = name;
+        return this;
+    }
+
+    /**
+     * Scope currently defined for bean creation.
+     * 
+     * @return the scope currently defined
+     */
+    public Class<? extends Annotation> getScope()
+    {
+        return scope;
+    }
+
+    /**
+     * Define the scope used for bean creation.
+     * 
+     * @param scope
+     *            the scope to use
+     */
+    public NarrowingBeanBuilder<T> scope(Class<? extends Annotation> scope)
+    {
+        this.scope = scope;
+        return this;
+    }
+
+    /**
+     * Whether the created bean will be an alternative.
+     * 
+     * @return <code>true</code> if the created bean will be an alternative,
+     *         otherwise <code>false</code>
+     */
+    public boolean isAlternative()
+    {
+        return alternative;
+    }
+
+    /**
+     * Define that the created bean will (or will not) be an alternative.
+     * 
+     * @param alternative
+     *            <code>true</code> if the created bean should be an
+     *            alternative, otherwise <code>false</code>
+     */
+    public NarrowingBeanBuilder<T> alternative(boolean alternative)
+    {
+        this.alternative = alternative;
+        return this;
+    }
+
+    /**
+     * Stereotypes currently defined for bean creation.
+     * 
+     * @return the stereotypes currently defined
+     */
+    public Set<Class<? extends Annotation>> getStereotypes()
+    {
+        return stereotypes;
+    }
+
+    /**
+     * Define the stereotypes used for bean creation.
+     * 
+     * @param stereotypes
+     *            the stereotypes to use
+     */
+    public NarrowingBeanBuilder<T> stereotypes(
+            Set<Class<? extends Annotation>> stereotypes)
+    {
+        this.stereotypes = stereotypes;
+        return this;
+    }
+
+    /**
+     * <p>
+     * Use the bean builder's current state to define the bean.
+     * </p>
+     * 
+     * @return the bean
+     */
+    public ImmutableNarrowingBean<T> create()
+    {
+        // Commented out due to it not being required for initial Message
+        // implementation
+        // if (isPassivationCapable()) {
+        // return new ImmutablePassivationCapableNarrowingBean<T>(delegate,
+        // name, qualifiers, scope, stereotypes, types, alternative,
+        // nullable, toString, id);
+        // } else {
+        return new ImmutableNarrowingBean<T>(delegate, name, qualifiers, scope,
+                stereotypes, types, alternative, nullable, toString);
+    }
+
+    // }
+
+    /**
+     * The string used when {@link #toString()} is called on the bean.
+     * 
+     * @return the string currently defined
+     */
+    public String getToString()
+    {
+        return toString;
+    }
+
+    /**
+     * Define the string used when {@link #toString()} is called on the bean.
+     * 
+     * @param toString
+     *            the string to use
+     */
+    public NarrowingBeanBuilder<T> toString(String toString)
+    {
+        this.toString = toString;
+        return this;
+    }
+
+    /**
+     * Whether the created bean will be nullable.
+     * 
+     * @return <code>true</code> if the created bean will be nullable, otherwise
+     *         <code>false</code>
+     */
+    public boolean isNullable()
+    {
+        return nullable;
+    }
+
+    /**
+     * Define that the created bean will (or will not) be nullable.
+     * 
+     * @param nullable
+     *            <code>true</code> if the created bean should be nullable,
+     *            otherwise <code>false</code>
+     */
+    public NarrowingBeanBuilder<T> nullable(boolean nullable)
+    {
+        this.nullable = nullable;
+        return this;
+    }
+
+    /**
+     * Whether the created bean will be passivation capable.
+     * 
+     * @return <code>true</code> if the created bean will be passivation
+     *         capable, otherwise <code>false</code>
+     */
+    public boolean isPassivationCapable()
+    {
+        return passivationCapable;
+    }
+
+    /**
+     * Define that the created bean will (or will not) be passivation capable.
+     * 
+     * @param nullable
+     *            <code>true</code> if the created bean should be passivation
+     *            capable, otherwise <code>false</code>
+     */
+    public NarrowingBeanBuilder<T> passivationCapable(boolean passivationCapable)
+    {
+        this.passivationCapable = passivationCapable;
+        return this;
+    }
+
+    /**
+     * The id currently defined for bean creation.
+     * 
+     * @return the id currently defined.
+     */
+    public String getId()
+    {
+        return id;
+    }
+
+    /**
+     * Define the id used for bean creation.
+     * 
+     * @param id
+     *            the id to use
+     */
+    public NarrowingBeanBuilder<T> id(String id)
+    {
+        this.id = id;
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundle.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundle.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundle.java
new file mode 100644
index 0000000..03996ec
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundle.java
@@ -0,0 +1,44 @@
+/*
+ * 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 java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Qualifier
+@Target({ TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+/**
+ * Internal-qualifier used to identify the typed message bundle producer for the
+ * wrapping bean.
+ */
+@interface TypedMessageBundle
+{
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundleProducer.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundleProducer.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundleProducer.java
new file mode 100644
index 0000000..029b4dc
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundleProducer.java
@@ -0,0 +1,44 @@
+/*
+ * 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 static org.apache.deltaspike.core.impl.message.MessageFactory.getBundle;
+import static org.apache.deltaspike.core.util.Reflections.getRawType;
+
+import java.io.Serializable;
+
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.InjectionPoint;
+
+/**
+ * The <code>TypedMessageBundleProducer</code> provides a producer method for
+ * injected typed message bundles.
+ */
+class TypedMessageBundleProducer implements Serializable
+{
+    private static final long serialVersionUID = -5077306523543940760L;
+
+    @Produces
+    @TypedMessageBundle
+    Object produceTypedMessageBundle(InjectionPoint injectionPoint)
+    {
+        return getBundle(getRawType(injectionPoint.getType()));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
index 03621ae..21051db 100644
--- a/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
+++ b/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -18,4 +18,5 @@
 #####################################################################################
 
 org.apache.deltaspike.core.impl.exclude.ExcludeExtension
-org.apache.deltaspike.core.impl.config.injectable.ConfigPropertyExtension
\ No newline at end of file
+org.apache.deltaspike.core.impl.config.injectable.ConfigPropertyExtension
+org.apache.deltaspike.core.impl.message.MessageBundleExtension
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/BirdMessages.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/BirdMessages.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/BirdMessages.java
new file mode 100644
index 0000000..8248933
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/BirdMessages.java
@@ -0,0 +1,28 @@
+/*
+ * 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.Message;
+import org.apache.deltaspike.core.api.message.MessageBundle;
+
+@MessageBundle
+public interface BirdMessages {
+	@Message("Spotted %s jays")
+	String numberOfJaysSpotted(int number);
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/Jay.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/Jay.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/Jay.java
new file mode 100644
index 0000000..3dabbcb
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/Jay.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;
+
+import javax.inject.Inject;
+
+import org.apache.deltaspike.core.api.message.MessageBundle;
+
+public class Jay {
+
+	@Inject
+	@MessageBundle
+	BirdMessages messages;
+
+	String getMessage() {
+		return messages.numberOfJaysSpotted(8);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/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
new file mode 100644
index 0000000..f196855
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+
+import javax.enterprise.inject.spi.Extension;
+
+import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
+import org.apache.deltaspike.core.impl.message.MessageBundleExtension;
+import org.apache.deltaspike.test.category.WebProfileCategory;
+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.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link org.apache.deltaspike.core.api.message.Message}
+ */
+@RunWith(Arquillian.class)
+@Category(WebProfileCategory.class)
+public class MessageTest
+{
+	/**
+	 * 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, "messageTest.jar")
+				.addPackage("org.apache.deltaspike.test.core.api.message")
+				.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+
+		return ShrinkWrap
+				.create(WebArchive.class, "messageTest.war")
+				.addAsLibraries(ArchiveUtils.getDeltaSpikeCoreArchive())
+				.addAsLibraries(testJar)
+				.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
+				.addAsServiceProvider(Extension.class,
+						MessageBundleExtension.class);
+	}
+
+    @Test
+    public void testMessageBundleInjection(Jay jay)
+	{
+        assertEquals("Spotted 8 jays", jay.getMessage());
+    }
+}