[weld-commits] Weld SVN: r5078 - doc/trunk/reference/en-US.
weld-commits at lists.jboss.org
weld-commits at lists.jboss.org
Mon Nov 16 18:41:00 EST 2009
Author: gavin.king at jboss.com
Date: 2009-11-16 18:41:00 -0500 (Mon, 16 Nov 2009)
New Revision: 5078
Modified:
doc/trunk/reference/en-US/extend.xml
Log:
much better portable extensions chapter
Modified: doc/trunk/reference/en-US/extend.xml
===================================================================
--- doc/trunk/reference/en-US/extend.xml 2009-11-16 04:46:28 UTC (rev 5077)
+++ doc/trunk/reference/en-US/extend.xml 2009-11-16 23:41:00 UTC (rev 5078)
@@ -79,6 +79,11 @@
into other beans once the initialization process is complete.
</para>
+ <programlisting>@Inject
+MyBean(MyExtension myExtension) {
+ myExtension.doSomething();
+}</programlisting>
+
<para>
And, like beans, extensions can have observer methods. Usually, the observer methods
observe <emphasis>container lifecycle events</emphasis>.
@@ -164,11 +169,7 @@
The observer method may inject a <literal>BeanManager</literal>
</para>
- <programlisting role="JAVA"><![CDATA[class MyExtension implements Extension {
-
- <T> void processAnnotatedType(ProcessAnnotatedType<T> pat, BeanManager beanManager) { ... }
-
-}]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[<T> void processAnnotatedType(ProcessAnnotatedType<T> pat, BeanManager beanManager) { ... }]]></programlisting>
</section>
@@ -213,7 +214,7 @@
<para>Any bean or other Java EE component which supports injection can obtain an instance of <literal>BeanManager</literal>
via injection:</para>
- <programlisting role="JAVA">@Inject BeanManager beanManager</programlisting>
+ <programlisting role="JAVA">@Inject BeanManager beanManager;</programlisting>
<para>
Java EE components may obtain an instance of <literal>BeanManager</literal> from JNDI by looking up the name
@@ -231,9 +232,21 @@
<para>
Instances of the interface <literal>Bean</literal> represent beans. There is an instance of
<literal>Bean</literal> registered with the <literal>BeanManager</literal> object for every bean in the
- application.
+ application. There are even <literal>Bean</literal> objects representing interceptors, decorators and
+ producer methods.
</para>
-
+
+ <para>
+ There's an easy way to find out what beans exist in the application:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[Set<Bean<?>> allBeans = beanManager.getBeans(Obect.class, new AnnotationLiteral<Any>() {});]]></programlisting>
+
+ <para>
+ The <literal>Bean</literal> interface exposes all the interesting things we dicussed in
+ <xref linkend="bean-anatomy"/>.
+ </para>
+
<programlisting role="JAVA"><![CDATA[public interface Bean<T> extends Contextual<T> {
public Set<Type> getTypes();
public Set<Annotation> getQualifiers();
@@ -247,41 +260,118 @@
}]]></programlisting>
<para>
- It's possible to implement the <literal>Bean</literal> interface and register instances by observing the
- <literal>AfterBeanDiscovery</literal> container lifecycle event and calling <literal>AfterBeanDiscovery.addBean()</literal>
- to provide support for new kinds of beans, beyond those defined by the CDI specification. For example, we could
- use the <literal>Bean</literal> interface to allow objects managed by another framework to be injected into beans.
+ The <literal>Bean</literal> interface makes it possible for a portable extension to provide
+ support for new kinds of beans, beyond those defined by the CDI specification. For example,
+ we could use the <literal>Bean</literal> interface to allow objects managed by another framework
+ to be injected into beans.
</para>
-
- <para>
- There are two subinterfaces of <literal>Bean</literal> defined by the CDI specification:
- <literal>Interceptor</literal> and <literal>Decorator</literal>.
- </para>
-
+
</section>
<section>
- <title>The <literal>Context</literal> interface</title>
-
+ <title>Registering a <literal>Bean</literal></title>
+
<para>
- The <literal>Context</literal> interface supports addition of new scopes to CDI, or extension of the built-in
- scopes to new environments.
+ The most common kind of CDI portable extension registers a bean (or beans) with the container.
</para>
+
+ <para>
+ In this example, we make a framework class, <literal>SecurityManager</literal> available
+ for injection. To make things a bit more interesting, we're going to delegate back to
+ the container's <literal>InjectionTarget</literal> to perform instantiation and injection
+ upon the <literal>SecurityManager</literal> instance.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public class SecurityManagerExtension implements Extension {
-<programlisting role="JAVA"><![CDATA[public interface Context {
- public Class<? extends Annotation> getScope();
- public <T> T get(Contextual<T> contextual, CreationalContext<T> creationalContext);
- public <T> T get(Contextual<T> contextual);
- boolean isActive();
+ void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) {
+
+ //use this to read annotations of the class
+ AnnotatedType<SecurityManager> at = bm.createAnnotatedType(SecurityManager.class);
+
+ //use this to instantiate the class and inject dependencies
+ final InjectionTarget<SecurityManager> it = bm.createInjectionTarget(at);
+
+ abd.addBean( new Bean<SecurityManager>() {
+
+ @Override
+ public Class<?> getBeanClass() {
+ return SecurityManager.class;
+ }
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return it.getInjectionPoints();
+ }
+
+ @Override
+ public String getName() {
+ return "securityManager";
+ }
+
+ @Override
+ public Set<Annotation> getQualifiers() {
+ Set<Annotation> qualifiers = new HashSet<Annotation>();
+ qualifiers.add( new AnnotationLiteral<Default>() {} );
+ qualifiers.add( new AnnotationLiteral<Any>() {} );
+ return qualifiers;
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return SessionScoped.class;
+ }
+
+ @Override
+ public Set<Class<? extends Annotation>> getStereotypes() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<Type> getTypes() {
+ Set<Type> types = new HashSet<Type>();
+ types.add(SecurityManager.class);
+ types.add(Object.class);
+ return types;
+ }
+
+ @Override
+ public boolean isAlternative() {
+ return false;
+ }
+
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+
+ @Override
+ public Object create(CreationalContext<SecurityManager> ctx) {
+ SecurityManager instance = it.produce(ctx);
+ it.inject(instance, ctx);
+ it.postConstruct(instance);
+ return instance;
+ }
+
+ @Override
+ public void destroy(SecurityManager instance, CreationalContext<SecurityManager> ctx) {
+ it.preDestroy(instance);
+ it.dispose(instance);
+ ctx.release();
+ }
+
+ } );
+ }
+ }
+
}]]></programlisting>
<para>
- For example, we might implement <literal>Context</literal> to add a business process scope to CDI, or to add
- support for the conversation scope to an application that uses Wicket.
+ But a portable extension can also mess with beans that are discovered automatically by the container.
</para>
-
+
</section>
-
+
<section>
<title>Wrapping an <literal>AnnotatedType</literal></title>
@@ -290,25 +380,134 @@
<emphasis>before</emphasis> the container builds its metamodel.
</para>
- <programlisting role="JAVA"><![CDATA[class MyExtension implements Extension {
+ <para>
+ Let's start with an example of an extension that provides support for the use of <literal>@Named</literal> at
+ the package level. The package-level name is used to qualify the EL names of all beans defined in that package.
+ The portable extension uses the <literal>ProcessAnnotatedType</literal> event to wrap the
+ <literal>AnnotatedType</literal> object and override the <literal>value()</literal> of the <literal>@Named</literal>
+ annotation.
+ </para>
+ <programlisting role="JAVA"><![CDATA[public class QualifiedNameExtension implements Extension {
+
+ <X> void processAnnotatedType(@Observes ProcessAnnotatedType<X> pat) {
+
+ //wrap this to override the annotations of the class
+ final AnnotatedType<X> at = pat.getAnnotatedType();
+
+ AnnotatedType<X> wrapped = new AnnotatedType<X>() {
+
+ @Override
+ public Set<AnnotatedConstructor<X>> getConstructors() {
+ return at.getConstructors();
+ }
+
+ @Override
+ public Set<AnnotatedField<? super X>> getFields() {
+ return at.getFields();
+ }
+
+ @Override
+ public Class<X> getJavaClass() {
+ return at.getJavaClass();
+ }
+
+ @Override
+ public Set<AnnotatedMethod<? super X>> getMethods() {
+ return at.getMethods();
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(final Class<T> annType) {
+ if ( Named.class.equals(annType) ) {
+ class NamedLiteral
+ extends AnnotationLiteral<Named>
+ implements Named {
+ @Override
+ public String value() {
+ Package pkg = at.getClass().getPackage();
+ String unqualifiedName = at.getAnnotation(Named.class).value();
+ final String qualifiedName;
+ if ( pkg.isAnnotationPresent(Named.class) ) {
+ qualifiedName = pkg.getAnnotation(Named.class).value()
+ + '.' + unqualifiedName;
+ }
+ else {
+ qualifiedName = unqualifiedName;
+ }
+ return qualifiedName;
+ }
+ }
+ return (T) new NamedLiteral();
+ }
+ else {
+ return at.getAnnotation(annType);
+ }
+ }
+
+ @Override
+ public Set<Annotation> getAnnotations() {
+ return at.getAnnotations();
+ }
+
+ @Override
+ public Type getBaseType() {
+ return at.getBaseType();
+ }
+
+ @Override
+ public Set<Type> getTypeClosure() {
+ return at.getTypeClosure();
+ }
+
+ @Override
+ public boolean isAnnotationPresent(Class<? extends Annotation> annType) {
+ return at.isAnnotationPresent(annType);
+ }
+
+ };
+
+ pat.setAnnotatedType(wrapped);
+ }
+
+}]]></programlisting>
+
+ <para>
+ Here's a second example, which adds the <literal>@Alternative</literal> annotation to any
+ class which implements a certain <literal>Service</literal> interface.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[class ServiceAlternativeExtension implements Extension {
+
<T> void processAnnotatedType(ProcessAnnotatedType<T> pat) {
+
final AnnotatedType<T> type = pat.getAnnotatedType();
+
if ( Service.class.isAssignableFrom( type.getJavaClass() ) ) {
+
//if the class implements Service, make it an @Alternative
AnnotatedType<T> wrapped = new AnnotatedType<T>() {
+
+ @Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
return annotationType.equals(Alternative.class) ?
true : type.isAnnotationPresent(annotationType);
}
+
+ //remaining methods of AnnotatedType
...
}
+
pat.setAnnotatedType(wrapped);
}
}
}]]></programlisting>
+ <para>
+
+ </para>
+
<para>The <literal>AnnotatedType</literal> is not the only thing that can be wrapped by an extension.</para>
</section>
@@ -323,32 +522,65 @@
to intercept any of these operations when they are invoked by the container.
</para>
- <programlisting role="JAVA"><![CDATA[class MyExtension implements Extension {
+ <programlisting role="JAVA"><![CDATA[class LogServletCreationExtension implements Extension {
<T extends Servlet> void processServlet(ProcessInjectionTarget<T> pit) {
+
+ //wrap this to intercept the component lifecycle
final InjectionTarget<T> it = pit.getInjectionTarget();
+
InjectionTarget<T> wrapped = new InjectionTarget<T>() {
+
+ @Override
public T produce(CreationalContext<T> ctx) {
Logger.global.debug("instantiating a servlet");
return it.produce(ctx);
}
+
+ @Override
public void inject(T instance, CreationalContext<T> ctx) {
Logger.global.debug("injecting servlet dependencies");
it.inject(instance, ctx);
}
+
+ //remaining methods of InjectionTarget
...
}
+
pit.setInjectionTarget(wrapped);
}
}]]></programlisting>
+ <para>
+ There's a lot more to the portable extension SPI than what we've discussed here. Check out the CDI spec or
+ Javadoc for more information. For now, we'll just mention one more extension point.
+ </para>
+
</section>
+
+ <section>
+ <title>The <literal>Context</literal> interface</title>
+
+ <para>
+ The <literal>Context</literal> interface supports addition of new scopes to CDI, or extension of the built-in
+ scopes to new environments.
+ </para>
+
+<programlisting role="JAVA"><![CDATA[public interface Context {
+ public Class<? extends Annotation> getScope();
+ public <T> T get(Contextual<T> contextual, CreationalContext<T> creationalContext);
+ public <T> T get(Contextual<T> contextual);
+ boolean isActive();
+}]]></programlisting>
- <!--
- TODO finish me!
- -->
-
+ <para>
+ For example, we might implement <literal>Context</literal> to add a business process scope to CDI, or to add
+ support for the conversation scope to an application that uses Wicket.
+ </para>
+
+ </section>
+
<!--
vim:et:ts=3:sw=3:tw=120
-->
More information about the weld-commits
mailing list