Weld SVN: r4948 - doc/trunk/reference/en-US.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-11-10 03:17:29 -0500 (Tue, 10 Nov 2009)
New Revision: 4948
Added:
doc/trunk/reference/en-US/beans.xml
Modified:
doc/trunk/reference/en-US/intro.xml
doc/trunk/reference/en-US/master.xml
doc/trunk/reference/en-US/part2.xml
doc/trunk/reference/en-US/part3.xml
Log:
neverending reorg
Added: doc/trunk/reference/en-US/beans.xml
===================================================================
--- doc/trunk/reference/en-US/beans.xml (rev 0)
+++ doc/trunk/reference/en-US/beans.xml 2009-11-10 08:17:29 UTC (rev 4948)
@@ -0,0 +1,749 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<chapter id="beanscdi">
+ <title>Beans in CDI</title>
+
+ <para>
+ A bean is usually an application class that contains business logic. It may be called directly from Java code,
+ or it may be invoked via the Unified EL. A bean may access transactional resources. Dependencies between beans
+ are managed automatically by the container. Most beans are <emphasis>stateful</emphasis> and
+ <emphasis>contextual</emphasis>. The lifecycle of a bean is always managed by the container.
+ </para>
+
+ <para>
+ Let's back up a second. What does it really mean to be <emphasis>contextual</emphasis>? Since beans may be
+ stateful, it matters <emphasis>which</emphasis> bean instance I have. Unlike a stateless component model (for
+ example, stateless session beans) or a singleton component model (such as servlets, or singleton beans),
+ different clients of a bean see the bean in different states. The client-visible state depends upon which
+ instance of the bean the client has a reference to.
+ </para>
+
+ <para>
+ However, like a stateless or singleton model, but <emphasis>unlike</emphasis> stateful session beans, the
+ client does not control the lifecycle of the instance by explicitly creating and destroying it. Instead, the
+ <emphasis>scope</emphasis> of the bean determines:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the lifecycle of each instance of the bean and</para>
+ </listitem>
+ <listitem>
+ <para>which clients share a reference to a particular instance of the bean.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ For a given thread in a CDI application, there may be an <emphasis>active context</emphasis> associated with
+ the scope of the bean. This context may be unique to the thread (for example, if the bean is request scoped),
+ or it may be shared with certain other threads (for example, if the bean is session scoped) or even all other
+ threads (if it is application scoped).
+ </para>
+
+ <para>
+ Clients (for example, other beans) executing in the same context will see the same instance of the bean. But
+ clients in a different context may see a different instance (depending on the relationship between the
+ contexts).
+ </para>
+
+ <para>
+ One great advantage of the contextual model is that it allows stateful beans to be treated like services! The
+ client need not concern itself with managing the lifecycle of the bean it's using, <emphasis>nor does it even
+ need to know what that lifecycle is.</emphasis> Beans interact by passing messages, and the bean implementations
+ define the lifecycle of their own state. The beans are loosely coupled because:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>they interact via well-defined public APIs</para>
+ </listitem>
+ <listitem>
+ <para>their lifecycles are completely decoupled</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ We can replace one bean with another different bean that implements the same interface and has a different lifecycle
+ (a different scope) without affecting the other bean implementation. In fact, CDI defines a simple facility for
+ overriding bean implementations at deployment time, as we will see in <xref linkend="alternatives"/>.
+ </para>
+
+ <para>
+ Note that not all clients of a bean are beans themselves. Other objects such as servlets or message-driven
+ beans—which are by nature not injectable, contextual objects—may also obtain references to beans by
+ injection.
+ </para>
+
+ <section id="bean-anatomy">
+ <title>The anatomy of a bean</title>
+
+ <para>Enough hand-waving. More formally, the anatomy of a bean, according to the spec:</para>
+
+ <blockquote>
+
+ <para>A bean comprises the following attributes:</para>
+
+ <itemizedlist>
+ <listitem><para>A (nonempty) set of bean types</para></listitem>
+ <listitem><para>A (nonempty) set of qualifiers</para></listitem>
+ <listitem><para>A scope</para></listitem>
+ <listitem><para>Optionally, a bean EL name</para></listitem>
+ <listitem><para>A set of interceptor bindings</para></listitem>
+ <listitem><para>A bean implementation</para></listitem>
+ </itemizedlist>
+
+ <para>Furthermore, a bean may or may not be an alternative.</para>
+
+ </blockquote>
+
+ <para>Let's see what all this new terminology means.</para>
+
+ <section>
+ <title>Bean types, qualifiers and dependency injection</title>
+
+ <para>
+ Beans usually acquire references to other beans via dependency injection. Any injected attribute specifies a
+ "contract" that must be satisfied by the bean to be injected. The contract is:
+ </para>
+
+ <itemizedlist>
+ <listitem><para>a bean type, together with</para></listitem>
+ <listitem><para>a set of qualifiers.</para></listitem>
+ </itemizedlist>
+
+ <para>
+ A bean type is a user-defined class or interface; a type that is client-visible. If the bean is an EJB
+ session bean, the bean type is the <literal>@Local</literal> interface or bean-class local view. A bean may
+ have multiple bean types. For example, the following bean has four bean types:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public class BookShop
+ extends Business
+ implements Shop<Book> {
+ ...
+}]]></programlisting>
+
+ <para>
+ The bean types are <literal>BookShop</literal>, <literal>Business</literal> and
+ <literal>Shop<Book></literal>, as well as the implicit type <literal>java.lang.Object</literal>.
+ (Notice that a parameterized type is a legal bean type).
+ </para>
+
+ <para>
+ Meanwhile, this session bean has only the local interfaces <literal>BookShop</literal>,
+ <literal>Auditable</literal> and <literal>java.lang.Object</literal> as bean types, since the bean class,
+ <literal>BookShopBean</literal> is not a client-visible type.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Stateful
+public class BookShopBean
+ extends Business
+ implements BookShop, Auditable {
+ ...
+}]]></programlisting>
+
+ <note>
+ <para>
+ Most bean types you can probably figure out. One gotcha is primitive types. All primitive types are assumed
+ to be identical to their corresponding wrapper types in <literal>java.lang</literal>.
+ </para>
+ </note>
+
+ <para>
+ Bean types may be restricted to an explicit set by annotating the bean with the <literal>@Typed</literal>
+ annotation and listing the classes that should be bean types. For instance, the bean types of this bean have
+ been restricted to <literal>Shop<Book></literal>, together with <literal>java.lang.Object</literal>:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[(a)Typed(Shop.class)
+public class BookShop
+ extends Business
+ implements Shop<Book> {
+ ...
+}]]></programlisting>
+
+ <para>
+ Sometimes, a bean type alone does not provide enough information for the container to know which bean to inject.
+ For instance, suppose we have two implementations of the <literal>PaymentProcessor</literal> interface:
+ <literal>CreditCardPaymentProcessor</literal> and <literal>DebitPaymentProcessor</literal>. Injecting a field of
+ type <literal>PaymentProcessor</literal> introduces an ambiguous condition. In these cases, the client must
+ specify some additional quality of the implementation it is interested in. We model this kind of "quality" using
+ a qualifier.
+ </para>
+
+ <para>
+ A qualifier is a user-defined annotation that is itself annotated <literal>@Qualifer</literal>. A qualifier
+ annotation is an extension of the type system. It lets us disambiguate a type without having to fall back to
+ string-based names. Here's an example of a qualifier annotation:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Qualifier
+@Target({TYPE, METHOD, PARAMETER, FIELD})
+@Retention(RUNTIME)
+public @interface CreditCard {}]]></programlisting>
+
+ <para>
+ You may not be used to seeing the definition of an annotation. In fact, this might be the first time you've
+ encountered one. With CDI, annotation definitions will become a familiar artifact as you'll be creating them
+ from time to time.
+ </para>
+
+ <tip>
+ <para>
+ Pay attention to the names of the built-in annotations in CDI and EJB. You'll notice that they are
+ often adjectives. We encourage you to follow this convention when creating your custom annotations,
+ since they serve to describe the behaviors and roles of the class.
+ </para>
+ </tip>
+
+ <para>
+ Now that we have defined a qualifier annotation, we can use it to disambiguate an injection point. The
+ following injection point has the bean type <literal>PaymentProcessor</literal> and qualifier
+ <literal>@CreditCard</literal>:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Inject @CreditCard PaymentProcessor paymentProcessor]]></programlisting>
+
+ <note>
+ <para>
+ If an injection point does not explicitly specify a qualifier, it has the default qualifier,
+ <literal>@Default</literal>.
+ </para>
+ </note>
+
+ <para>
+ For each injection point, the container searches for a bean which satisfies the contract, one which has
+ the bean type and all the qualifiers. If it finds exactly one matching bean, it injects an instance of
+ that bean. If it doesn't, it reports an error to the user.
+ </para>
+
+ <para>
+ How do we specify that qualifiers of a bean? By annotating the bean class, of course! The following bean
+ has the qualifier <literal>@CreditCard</literal> and implements the bean type <literal>PaymentProcessor</literal>.
+ Therefore, it satisfies our qualified injection point:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@CreditCard
+public class CreditCardPaymentProcessor
+ implements PaymentProcessor { ... }]]></programlisting>
+
+ <note>
+ <para>
+ If a bean does not explicitly specify a qualifier, it has the default qualifier, <literal>@Default</literal>.
+ </para>
+ </note>
+
+ <!--
+ <note>
+ <para>
+ All beans have the qualifier, <literal>@Any</literal>.
+ </para>
+ </note>
+ -->
+
+ <para>
+ That's not quite the end of the story. CDI also defines a simple <emphasis>resolution rule</emphasis> that helps
+ the container decide what to do if there is more than one bean that satisfies a particular contract. We'll get
+ into the details in <xref linkend="injection"/>.
+ </para>
+
+ <!--
+ <tip>
+ <para>
+ If you're expectng more than one bean to satisfy the contract, you can inject an <literal>Instance</literal>,
+ object which let's you iterate over all the beans which satisfy the contract. For example, we can iterate
+ over all our implementations of <literal>PaymentProcessor</literal> using:
+ </para>
+ <programlisting>@Inject void init(@Any Instance<PaymentProcessor> paymentProcessorInstance) {
+ for (PaymentProcessor pp: paymentProcessorInstance) { ... }
+}</programlisting>
+ </tip>
+ -->
+
+ </section>
+
+ <section>
+ <title>Scope</title>
+ <!-- I wonder whether the explaination of contextual above would fit better here -->
+
+ <para>
+ The <emphasis>scope</emphasis> of a bean defines the lifecycle and visibility of its instances.
+ The CDI context model is extensible, accommodating arbitrary scopes. However, certain important scopes are
+ built into the specification, and provided by the container. Each scope is represented by an annotation
+ type.
+ </para>
+
+ <para>
+ For example, any web application may have <emphasis>session scoped</emphasis> bean:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public @SessionScoped
+class ShoppingCart implements Serializable { ... }]]></programlisting>
+
+ <para>An instance of a session-scoped bean is bound to a user session
+ and is shared by all requests that execute in the context of that session.</para>
+
+ <note>
+ <para>
+ Keep in mind that once a bean is bound to a context, it remains in that context until the context is
+ destroyed. There is no way to explicitly remove a bean from a context. If you don't the bean to live in
+ the session indefinitely, consider using another scope such as the request or conversation scope instead.
+ </para>
+ </note>
+
+ <para>
+ If a scope is not explicitly specified, then the bean belongs to a special scope called the
+ <emphasis>dependent pseudo-scope</emphasis>. Beans with this scope live to serve the object into which they
+ were injected, which means their lifecycle is bound to the lifecycle of that object.
+ </para>
+
+ <para>We'll talk more about scopes in <xref linkend="scopescontexts"/>.</para>
+
+ </section>
+
+ <section>
+ <title>EL name</title>
+
+ <para>
+ If you want to reference a bean in non-Java code that supports Unified EL expressions, for example, in a
+ JSP or JSF page, you must assign the bean an <emphasis>EL name</emphasis>.
+ </para>
+
+ <para>
+ The EL name is specified using the <literal>@Named</literal> annotation, as shown here:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public @SessionScoped @Named("cart")
+class ShoppingCart implements Serializable { ... }]]></programlisting>
+
+ <para>Now we can easily use the bean in any JSF or JSP page:</para>
+
+ <programlisting role="XML"><![CDATA[<h:dataTable value="#{cart.lineItems}" var="item">
+ ...
+</h:dataTable>]]></programlisting>
+
+ <note>
+ <para>
+ The <literal>@Named</literal> annotation is not what makes the class a bean. Most classes in a bean
+ archive are already recognized as beans. The <literal>@Named</literal> annotation just makes it
+ possible to reference the bean from the EL, most commonly from a JSF view.
+ </para>
+ </note>
+
+ <para>
+ We can let CDI choose a name for us by leaving off the value of the <literal>@Named</literal> annotation:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public @SessionScoped @Named
+class ShoppingCart implements Serializable { ... }]]></programlisting>
+
+ <para>
+ The name defaults to the unqualified class name, decapitalized; in this case,
+ <literal>shoppingCart</literal>.
+ </para>
+
+ </section>
+
+ <!-- TODO the alternative section needs to be spruced up to support the text that comes in subsequent chapters. The
+ reader needs to feel confident than they would know how to create an alternative and enable it. -->
+ <section>
+ <title>Alternatives</title>
+
+ <para>
+ We've already seen how qualifiers let us choose between multiple implementations of an interface
+ at development time. But sometimes we have an interface (or other bean type) whose implementation
+ varies depending upon the deployment environment. For example, we may want to use a mock
+ implementation in a testing environment. An <emphasis>alternative</emphasis> may be declared by
+ annotating the bean class with the <literal>@Alternative</literal> annotation.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public @Alternative
+class MockPaymentProcessor extends PaymentProcessorImpl { ... }]]></programlisting>
+
+ <para>
+ We normally annotate a bean <literal>@Alternative</literal> only when there is some other
+ implementation of an interface it implements (or of any of its bean types). We can choose between
+ alternatives at deployment time by <emphasis>selecting</emphasis> an alternative in the CDI
+ deployment descriptor <literal>META-INF/beans.xml</literal> of the jar or Java EE module that uses
+ it. Different modules can specify that they use different alternatives.
+ </para>
+
+ <para>
+ We cover alternatives in more detail in <xref linkend="alternatives"/>.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Interceptor binding types</title>
+
+ <para>
+ You might be familiar with the use of interceptors in EJB 3.0. In Java EE 6, this functionality has
+ been generalized to work with other managed beans. That's right, you no longer have to make your bean
+ an EJB just to intercept its methods. Holler. So what does CDI have to offer above and beyond that? Well,
+ quite a lot actually. Let's cover some background.
+ </para>
+
+ <para>
+ The way that interceptors were defined in Java EE 5 was counter-intuitive. You were required to specify the
+ <emphasis>implementation</emphasis> of the interceptor directly on the <emphasis>implementation</emphasis>
+ of the EJB, either in the <literal>@Interceptors</literal> annotation or in the XML descriptor. You might as
+ well just put the interceptor code <emphasis>in</emphasis> the implementation! Second, the order in which
+ the interceptors are applied is taken from the order in which they are declared in the annotation or the XML
+ descriptor. Perhaps this isn't so bad if you're applying the interceptors to a single bean. But, if you are
+ applying them repeatedly, then there's a good chance that you'll inadvertently define a different order for
+ different beans. Now that's a problem.
+ </para>
+
+ <para>
+ CDI provides a new approach to binding interceptors to beans that introduces a level of indirection (and
+ thus control). We must define an <emphasis>interceptor binding type</emphasis> to describe the behavior
+ implemented by the interceptor.
+ </para>
+
+ <para>
+ An interceptor binding type is a user-defined annotation that is itself annotated <literal>@InterceptorBinding</literal>.
+ It lets us bind interceptor classes to bean classes with no direct dependency between the two classes.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@InterceptorBinding
+@Inherited
+@Target( { TYPE, METHOD })
+@Retention(RUNTIME)
+public @interface Transactional {}]]></programlisting>
+
+ <para>
+ The interceptor that implements transaction management declares this annotation:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public @Transactional @Interceptor
+class TransactionInterceptor { ... }]]></programlisting>
+
+ <para>
+ We can apply the interceptor to a bean by annotating the bean class with the same interceptor binding type:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public @SessionScoped @Transactional
+class ShoppingCart implements Serializable { ... }]]></programlisting>
+
+ <para>
+ Notice that <literal>ShoppingCart</literal> and <literal>TransactionInterceptor</literal> don't know
+ anything about each other.
+ </para>
+
+ <para>
+ Interceptors are deployment-specific. (We don't need a <literal>TransactionInterceptor</literal> in our
+ unit tests!) By default, an interceptor is disabled. We can enable an interceptor using the CDI deployment
+ descriptor <literal>META-INF/beans.xml</literal> of the jar or Java EE module. This is also where we
+ specify the interceptor ordering.
+ </para>
+
+ <para>
+ We'll discuss interceptors, and their cousins, decorators, in <xref linkend="interceptors"/> and <xref
+ linkend="decorators"/>.
+ </para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>What kinds of classes are beans?</title>
+
+ <para>
+ We've already seen two types of beans: JavaBeans and EJB session beans. Is that the whole story? Actually,
+ it's just the beginning. Let's explore the various kinds of beans that CDI implementations must support
+ out-of-the-box.
+ </para>
+
+ <section>
+ <title>Managed beans</title>
+
+ <para>
+ A managed bean is a Java class. The basic lifecycle and semantics of a managed bean are defined by the
+ Managed Beans specification. You can explicitly declare a managed bean by annotating the bean class
+ <literal>@ManagedBean</literal>, but in CDI you don't need to. According to the specification, the CDI
+ container treats any class that satisfies the following conditions as a managed bean:
+ </para>
+
+ <blockquote>
+
+ <itemizedlist>
+ <listitem>
+ <para>It is not a non-static inner class.</para>
+ </listitem>
+ <listitem>
+ <para>It is a concrete class, or is annotated <literal>@Decorator</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>
+ It is not annotated with an EJB component-defining annotation or declared as an EJB bean class in
+ <literal>ejb-jar.xml</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>It does not implement <literal>javax.enterprise.inject.spi.Extension</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>
+ It has an appropriate constructor—either:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>the class has a constructor with no parameters, or</para>
+ </listitem>
+ <listitem>
+ <para>the class declares a constructor annotated <literal>@Inject</literal>.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+
+ </blockquote>
+
+ <para>The unrestricted set of bean types for a managed bean contains the bean class, every superclass and all
+ interfaces it implements directly or indirectly.</para>
+
+ <para>If a managed bean has a public field, it must have the default scope <literal>@Dependent</literal>.</para>
+
+ <para>Managed beans support the <literal>@PostConstruct</literal> and <literal>@PreDestroy</literal> lifecycle
+ callbacks.</para>
+
+ <para>
+ Session beans are also, technically, managed beans. However, since they have their own special lifecycle and
+ take advantage of additional enterprise services, the CDI specification considers them to be a different
+ kind of bean.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Session beans</title>
+
+ <para>
+ Session beans belong to the EJB specification. They have a special lifecycle, state management and concurrency
+ model that is different to other managed beans and non-managed Java objects. But session beans participate in
+ CDI just like any other bean. You can inject one session bean into another session bean, a managed bean into a
+ session bean, a session bean into a managed bean, have a managed bean observe an event raised by a session bean,
+ and so on.
+ </para>
+
+ <note>
+ <para>
+ Message-driven and entity beans are by nature non-contextual objects and may not be injected into other
+ objects. However, message-driven beans can take advantage of some CDI functionality, such as dependency
+ injection, interceptors and decorators. In fact, CDI will perform injection into any session or
+ message-driven bean, even those which are not contextual instances.
+ </para>
+ </note>
+
+ <para>
+ The unrestricted set of bean types for a session bean contains all local interfaces of the bean and their
+ superinterfaces. If the session bean has a bean class local view, the unrestricted set of bean types
+ contains the bean class and all superclasses. In addition, <literal>java.lang.Object</literal> is a bean
+ type of every session bean. But remote interfaces are <emphasis>not</emphasis> included in the set of bean
+ types.
+ </para>
+
+ <para>There's no reason to explicitly declare the scope of a stateless session bean or singleton session bean.
+ The EJB container controls the lifecycle of these beans, according to the semantics of the <literal>@Stateless</literal>
+ or <literal>@Singleton</literal> declaration. On the other hand, a stateful session bean may have any scope.</para>
+
+ <para>
+ Stateful session beans may define a <emphasis>remove method</emphasis>, annotated <literal>@Remove</literal>,
+ that is used by the application to indicate that an instance should be destroyed. However, for a contextual
+ instance of the bean—an instance under the control of CDI—this method may only be called by the
+ application if the bean has scope <literal>@Dependent</literal>. For beans with other scopes, the application
+ must let the container destroy the bean.
+ </para>
+
+ <para>
+ So, when should we use a session bean instead of a plain managed bean? Whenever we need the advanced enterprise
+ services offered by EJB, such as:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>method-level transaction management and security,</para>
+ </listitem>
+ <listitem>
+ <para>concurrency management,</para>
+ </listitem>
+ <listitem>
+ <para>instance-level passivation for stateful session beans and
+ instance-pooling for stateless session beans,</para>
+ </listitem>
+ <listitem>
+ <para>remote or web service invocation, or</para>
+ </listitem>
+ <listitem>
+ <para>timers and asynchronous methods,</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>When we don't need any of these things, an ordinary managed bean will serve just fine.</para>
+
+ <para>
+ Many beans (including any <literal>@SessionScoped</literal> or <literal>@ApplicationScoped</literal>
+ beans) are available for concurrent access. Therefore, the concurrency management provided by EJB 3.1
+ is especially useful. Most session and application scoped beans should be EJBs.
+ </para>
+
+ <para>
+ Beans which hold references to heavy-weight resources, or hold a lot of internal state benefit from the
+ advanced container-managed lifecycle defined by the EJB stateless/stateful/singleton model, with its
+ support for passivation and instance pooling.
+ </para>
+
+ <para>
+ Finally, it's usually obvious when method-level transaction management, method-level security, timers,
+ remote methods or asynchronous methods are needed.
+ </para>
+
+ <para>
+ The point we're trying to make is: use a session bean when you need the services it provides, not just
+ because you want to use dependency injection, lifecycle management, or interceptors. Java EE 6 provides
+ a graduated programming model. It's usually easy to start with an ordinary managed bean, and later turn
+ it into an EJB just by adding one of the following annotations: <literal>@Stateless</literal>,
+ <literal>@Stateful</literal> or <literal>@Singleton</literal>.
+ </para>
+
+ <para>
+ On the other hand, don't be scared to use session beans just because you've heard your friends say
+ they're "heavyweight". It's nothing more than superstition to think that something is "heavier" just
+ because it's hosted natively within the Java EE container, instead of by a proprietary bean container
+ or dependency injection framework that runs as an additional layer of obfuscation. And as a general
+ principle, you should be skeptical of folks who use vaguely defined terminology like "heavyweight".
+ </para>
+
+ </section>
+
+ <section>
+ <title>Producer methods</title>
+
+ <para>
+ Not everything that needs to be injected can be boiled down to a bean class instantiated by the container
+ using <literal>new</literal>. There are plenty of cases where we need additional control. What if we need
+ to decide at runtime which implementation of a type to instantiate and inject? What if we need to inject
+ an object that is obtained by querying a service or transactional resource, for example by executing a JPA
+ query?
+ </para>
+
+ <para>
+ A <emphasis>producer method</emphasis> is a method that acts as a source of bean instances. The method
+ declaration itself describes the bean and the container invokes the method to obtain an instance of the
+ bean when no instance exists in the specified context. A producer method lets the application take full
+ control of the bean instantiation process.
+ </para>
+
+ <para>
+ A producer method is declared by annotating a method of a bean class with the <literal>@Produces</literal>
+ annotation.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@ApplicationScoped
+public class RandomNumberGenerator {
+
+ private Random random = new Random(System.currentTimeMillis());
+
+ @Produces @Named @Random int getRandomNumber() {
+ return random.nextInt(100);
+ }
+
+}]]></programlisting>
+
+ <para>
+ We can't write a bean class that is itself a random number. But we can certainly write a method that returns
+ a random number. By making the method a producer method, we allow the return value of the method—in this
+ case an <literal>Integer</literal>—to be injected. We can even specify a qualifier—in this case
+ <literal>@Random</literal>, a scope—which in this case defaults to <literal>@Dependent</literal>,
+ and an EL name—which in this case defaults to <literal>randomNumber</literal> according to the JavaBeans
+ property name convention. Now we can get a random number anywhere:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Inject @Random int randomNumber;]]></programlisting>
+
+ <para>
+ Even in a Unified EL expression:
+ </para>
+
+ <programlisting><![CDATA[<p>Your raffle number is #{randomNumber}.</p>]]></programlisting>
+
+ <para>
+ A producer method must be a non-abstract method of a managed bean class or session bean class. A producer
+ method may be either static or non-static. If the bean is a session bean, the producer method must be either
+ a business method of the EJB or a static method of the bean class.
+ </para>
+
+ <para>
+ The bean types of a producer method depend upon the method return type:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ If the return type is an interface, the unrestricted set of bean types contains the return type, all
+ interfaces it extends directly or indirectly and <literal>java.lang.Object</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a return type is primitive or is a Java array type, the unrestricted set of bean types contains
+ exactly two types: the method return type and <literal>java.lang.Object</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the return type is a class, the unrestricted set of bean types contains the return type, every
+ superclass and all interfaces it implements directly or indirectly.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ If the producer method has method parameters, the container will look for a bean that satisfies the type
+ and qualifiers of each parameter and pass it to the method automatically—another form of
+ dependency injection.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Produces Set<Roles> getRoles(User user) {
+ return user.getRoles();
+}]]></programlisting>
+
+ <para>We'll talk much more about producer methods in <xref linkend="producermethods"/>.</para>
+
+ </section>
+
+ <section>
+ <title>Producer fields</title>
+
+ <para>
+ A <emphasis>producer field</emphasis> is a simpler alternative to a producer method. A producer field is
+ declared by annotating a field of a bean class with the <literal>@Produces</literal> annotation—the
+ same annotation used for producer methods.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public class Shop {
+ @Produces PaymentProcessor paymentProcessor = ....;
+ @Produces @Catalog List<Product> products = ....;
+}]]></programlisting>
+
+ <para>
+ The rules for determining the bean types of a producer field parallel the rules for producer methods.
+ </para>
+
+ <para>
+ A producer field is really just a shortcut that lets us avoid writing a useless getter method. However,
+ in addition to convenience, producer fields serve a specific purpose as an adaptor for Java EE component
+ environment injection, but to learn more about that, you'll have to wait until <xref linkend="resources"/>.
+ Because we can't wait to get to work on some examples.
+ </para>
+
+ </section>
+
+ </section>
+
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
+</chapter>
Modified: doc/trunk/reference/en-US/intro.xml
===================================================================
--- doc/trunk/reference/en-US/intro.xml 2009-11-10 07:50:26 UTC (rev 4947)
+++ doc/trunk/reference/en-US/intro.xml 2009-11-10 08:17:29 UTC (rev 4948)
@@ -1,7 +1,7 @@
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
<chapter id="intro">
- <title>Getting started with CDI</title>
+ <title>Introduction</title>
<para>
So you're keen to get started writing your first bean? Or perhaps you're skeptical, wondering what kinds of hoops
@@ -13,8 +13,7 @@
<title>What is a bean?</title>
<para>
- In this section, you'll learn that a bean is exactly what you think it is. Only now, it has a true identity in
- the container environment.
+ A bean is exactly what you think it is. Only now, it has a true identity in the container environment.
</para>
<para>
@@ -214,746 +213,6 @@
</section>
- <section id="bean-anatomy">
- <title>The anatomy of a bean</title>
-
- <para>
- A bean is usually an application class that contains business logic. It may be called directly from Java code,
- or it may be invoked via the Unified EL. A bean may access transactional resources. Dependencies between beans
- are managed automatically by the container. Most beans are <emphasis>stateful</emphasis> and
- <emphasis>contextual</emphasis>. The lifecycle of a bean is always managed by the container.
- </para>
-
- <para>
- Let's back up a second. What does it really mean to be <emphasis>contextual</emphasis>? Since beans may be
- stateful, it matters <emphasis>which</emphasis> bean instance I have. Unlike a stateless component model (for
- example, stateless session beans) or a singleton component model (such as servlets, or singleton beans),
- different clients of a bean see the bean in different states. The client-visible state depends upon which
- instance of the bean the client has a reference to.
- </para>
-
- <para>
- However, like a stateless or singleton model, but <emphasis>unlike</emphasis> stateful session beans, the
- client does not control the lifecycle of the instance by explicitly creating and destroying it. Instead, the
- <emphasis>scope</emphasis> of the bean determines:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>the lifecycle of each instance of the bean and</para>
- </listitem>
- <listitem>
- <para>which clients share a reference to a particular instance of the bean.</para>
- </listitem>
- </itemizedlist>
-
- <para>
- For a given thread in a CDI application, there may be an <emphasis>active context</emphasis> associated with
- the scope of the bean. This context may be unique to the thread (for example, if the bean is request scoped),
- or it may be shared with certain other threads (for example, if the bean is session scoped) or even all other
- threads (if it is application scoped).
- </para>
-
- <para>
- Clients (for example, other beans) executing in the same context will see the same instance of the bean. But
- clients in a different context may see a different instance (depending on the relationship between the
- contexts).
- </para>
-
- <para>
- One great advantage of the contextual model is that it allows stateful beans to be treated like services! The
- client need not concern itself with managing the lifecycle of the bean it's using, <emphasis>nor does it even
- need to know what that lifecycle is.</emphasis> Beans interact by passing messages, and the bean implementations
- define the lifecycle of their own state. The beans are loosely coupled because:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>they interact via well-defined public APIs</para>
- </listitem>
- <listitem>
- <para>their lifecycles are completely decoupled</para>
- </listitem>
- </itemizedlist>
-
- <para>
- We can replace one bean with another different bean that implements the same interface and has a different lifecycle
- (a different scope) without affecting the other bean implementation. In fact, CDI defines a simple facility for
- overriding bean implementations at deployment time, as we will see in <xref linkend="alternatives"/>.
- </para>
-
- <para>
- Note that not all clients of a bean are beans themselves. Other objects such as servlets or message-driven
- beans—which are by nature not injectable, contextual objects—may also obtain references to beans by
- injection.
- </para>
-
- <para>Enough hand-waving. More formally, the anatomy of a bean, according to the spec:</para>
-
- <blockquote>
-
- <para>A bean comprises the following attributes:</para>
-
- <itemizedlist>
- <listitem><para>A (nonempty) set of bean types</para></listitem>
- <listitem><para>A (nonempty) set of qualifiers</para></listitem>
- <listitem><para>A scope</para></listitem>
- <listitem><para>Optionally, a bean EL name</para></listitem>
- <listitem><para>A set of interceptor bindings</para></listitem>
- <listitem><para>A bean implementation</para></listitem>
- </itemizedlist>
-
- <para>Furthermore, a bean may or may not be an alternative.</para>
-
- </blockquote>
-
- <para>Let's see what all this new terminology means.</para>
-
- <section>
- <title>Bean types, qualifiers and dependency injection</title>
-
- <para>
- Beans usually acquire references to other beans via dependency injection. Any injected attribute specifies a
- "contract" that must be satisfied by the bean to be injected. The contract is:
- </para>
-
- <itemizedlist>
- <listitem><para>a bean type, together with</para></listitem>
- <listitem><para>a set of qualifiers.</para></listitem>
- </itemizedlist>
-
- <para>
- A bean type is a user-defined class or interface; a type that is client-visible. If the bean is an EJB
- session bean, the bean type is the <literal>@Local</literal> interface or bean-class local view. A bean may
- have multiple bean types. For example, the following bean has four bean types:
- </para>
-
- <programlisting role="JAVA"><![CDATA[public class BookShop
- extends Business
- implements Shop<Book> {
- ...
-}]]></programlisting>
-
- <para>
- The bean types are <literal>BookShop</literal>, <literal>Business</literal> and
- <literal>Shop<Book></literal>, as well as the implicit type <literal>java.lang.Object</literal>.
- (Notice that a parameterized type is a legal bean type).
- </para>
-
- <para>
- Meanwhile, this session bean has only the local interfaces <literal>BookShop</literal>,
- <literal>Auditable</literal> and <literal>java.lang.Object</literal> as bean types, since the bean class,
- <literal>BookShopBean</literal> is not a client-visible type.
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Stateful
-public class BookShopBean
- extends Business
- implements BookShop, Auditable {
- ...
-}]]></programlisting>
-
- <note>
- <para>
- Most bean types you can probably figure out. One gotcha is primitive types. All primitive types are assumed
- to be identical to their corresponding wrapper types in <literal>java.lang</literal>.
- </para>
- </note>
-
- <para>
- Bean types may be restricted to an explicit set by annotating the bean with the <literal>@Typed</literal>
- annotation and listing the classes that should be bean types. For instance, the bean types of this bean have
- been restricted to <literal>Shop<Book></literal>, together with <literal>java.lang.Object</literal>:
- </para>
-
- <programlisting role="JAVA"><![CDATA[(a)Typed(Shop.class)
-public class BookShop
- extends Business
- implements Shop<Book> {
- ...
-}]]></programlisting>
-
- <para>
- Sometimes, a bean type alone does not provide enough information for the container to know which bean to inject.
- For instance, suppose we have two implementations of the <literal>PaymentProcessor</literal> interface:
- <literal>CreditCardPaymentProcessor</literal> and <literal>DebitPaymentProcessor</literal>. Injecting a field of
- type <literal>PaymentProcessor</literal> introduces an ambiguous condition. In these cases, the client must
- specify some additional quality of the implementation it is interested in. We model this kind of "quality" using
- a qualifier.
- </para>
-
- <para>
- A qualifier is a user-defined annotation that is itself annotated <literal>@Qualifer</literal>. A qualifier
- annotation is an extension of the type system. It lets us disambiguate a type without having to fall back to
- string-based names. Here's an example of a qualifier annotation:
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Qualifier
-@Target({TYPE, METHOD, PARAMETER, FIELD})
-@Retention(RUNTIME)
-public @interface CreditCard {}]]></programlisting>
-
- <para>
- You may not be used to seeing the definition of an annotation. In fact, this might be the first time you've
- encountered one. With CDI, annotation definitions will become a familiar artifact as you'll be creating them
- from time to time.
- </para>
-
- <tip>
- <para>
- Pay attention to the names of the built-in annotations in CDI and EJB. You'll notice that they are
- often adjectives. We encourage you to follow this convention when creating your custom annotations,
- since they serve to describe the behaviors and roles of the class.
- </para>
- </tip>
-
- <para>
- Now that we have defined a qualifier annotation, we can use it to disambiguate an injection point. The
- following injection point has the bean type <literal>PaymentProcessor</literal> and qualifier
- <literal>@CreditCard</literal>:
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Inject @CreditCard PaymentProcessor paymentProcessor]]></programlisting>
-
- <note>
- <para>
- If an injection point does not explicitly specify a qualifier, it has the default qualifier,
- <literal>@Default</literal>.
- </para>
- </note>
-
- <para>
- For each injection point, the container searches for a bean which satisfies the contract, one which has
- the bean type and all the qualifiers. If it finds exactly one matching bean, it injects an instance of
- that bean. If it doesn't, it reports an error to the user.
- </para>
-
- <para>
- How do we specify that qualifiers of a bean? By annotating the bean class, of course! The following bean
- has the qualifier <literal>@CreditCard</literal> and implements the bean type <literal>PaymentProcessor</literal>.
- Therefore, it satisfies our qualified injection point:
- </para>
-
- <programlisting role="JAVA"><![CDATA[@CreditCard
-public class CreditCardPaymentProcessor
- implements PaymentProcessor { ... }]]></programlisting>
-
- <note>
- <para>
- If a bean does not explicitly specify a qualifier, it has the default qualifier, <literal>@Default</literal>.
- </para>
- </note>
-
- <!--
- <note>
- <para>
- All beans have the qualifier, <literal>@Any</literal>.
- </para>
- </note>
- -->
-
- <para>
- That's not quite the end of the story. CDI also defines a simple <emphasis>resolution rule</emphasis> that helps
- the container decide what to do if there is more than one bean that satisfies a particular contract. We'll get
- into the details in <xref linkend="injection"/>.
- </para>
-
- <!--
- <tip>
- <para>
- If you're expectng more than one bean to satisfy the contract, you can inject an <literal>Instance</literal>,
- object which let's you iterate over all the beans which satisfy the contract. For example, we can iterate
- over all our implementations of <literal>PaymentProcessor</literal> using:
- </para>
- <programlisting>@Inject void init(@Any Instance<PaymentProcessor> paymentProcessorInstance) {
- for (PaymentProcessor pp: paymentProcessorInstance) { ... }
-}</programlisting>
- </tip>
- -->
-
- </section>
-
- <section>
- <title>Scope</title>
- <!-- I wonder whether the explaination of contextual above would fit better here -->
-
- <para>
- The <emphasis>scope</emphasis> of a bean defines the lifecycle and visibility of its instances.
- The CDI context model is extensible, accommodating arbitrary scopes. However, certain important scopes are
- built into the specification, and provided by the container. Each scope is represented by an annotation
- type.
- </para>
-
- <para>
- For example, any web application may have <emphasis>session scoped</emphasis> bean:
- </para>
-
- <programlisting role="JAVA"><![CDATA[public @SessionScoped
-class ShoppingCart implements Serializable { ... }]]></programlisting>
-
- <para>An instance of a session-scoped bean is bound to a user session
- and is shared by all requests that execute in the context of that session.</para>
-
- <note>
- <para>
- Keep in mind that once a bean is bound to a context, it remains in that context until the context is
- destroyed. There is no way to explicitly remove a bean from a context. If you don't the bean to live in
- the session indefinitely, consider using another scope such as the request or conversation scope instead.
- </para>
- </note>
-
- <para>
- If a scope is not explicitly specified, then the bean belongs to a special scope called the
- <emphasis>dependent pseudo-scope</emphasis>. Beans with this scope live to serve the object into which they
- were injected, which means their lifecycle is bound to the lifecycle of that object.
- </para>
-
- <para>We'll talk more about scopes in <xref linkend="scopescontexts"/>.</para>
-
- </section>
-
- <section>
- <title>EL name</title>
-
- <para>
- If you want to reference a bean in non-Java code that supports Unified EL expressions, for example, in a
- JSP or JSF page, you must assign the bean an <emphasis>EL name</emphasis>.
- </para>
-
- <para>
- The EL name is specified using the <literal>@Named</literal> annotation, as shown here:
- </para>
-
- <programlisting role="JAVA"><![CDATA[public @SessionScoped @Named("cart")
-class ShoppingCart implements Serializable { ... }]]></programlisting>
-
- <para>Now we can easily use the bean in any JSF or JSP page:</para>
-
- <programlisting role="XML"><![CDATA[<h:dataTable value="#{cart.lineItems}" var="item">
- ...
-</h:dataTable>]]></programlisting>
-
- <note>
- <para>
- The <literal>@Named</literal> annotation is not what makes the class a bean. Most classes in a bean
- archive are already recognized as beans. The <literal>@Named</literal> annotation just makes it
- possible to reference the bean from the EL, most commonly from a JSF view.
- </para>
- </note>
-
- <para>
- We can let CDI choose a name for us by leaving off the value of the <literal>@Named</literal> annotation:
- </para>
-
- <programlisting role="JAVA"><![CDATA[public @SessionScoped @Named
-class ShoppingCart implements Serializable { ... }]]></programlisting>
-
- <para>
- The name defaults to the unqualified class name, decapitalized; in this case,
- <literal>shoppingCart</literal>.
- </para>
-
- </section>
-
- <!-- TODO the alternative section needs to be spruced up to support the text that comes in subsequent chapters. The
- reader needs to feel confident than they would know how to create an alternative and enable it. -->
- <section>
- <title>Alternatives</title>
-
- <para>
- We've already seen how qualifiers let us choose between multiple implementations of an interface
- at development time. But sometimes we have an interface (or other bean type) whose implementation
- varies depending upon the deployment environment. For example, we may want to use a mock
- implementation in a testing environment. An <emphasis>alternative</emphasis> may be declared by
- annotating the bean class with the <literal>@Alternative</literal> annotation.
- </para>
-
- <programlisting role="JAVA"><![CDATA[public @Alternative
-class MockPaymentProcessor extends PaymentProcessorImpl { ... }]]></programlisting>
-
- <para>
- We normally annotate a bean <literal>@Alternative</literal> only when there is some other
- implementation of an interface it implements (or of any of its bean types). We can choose between
- alternatives at deployment time by <emphasis>selecting</emphasis> an alternative in the CDI
- deployment descriptor <literal>META-INF/beans.xml</literal> of the jar or Java EE module that uses
- it. Different modules can specify that they use different alternatives.
- </para>
-
- <para>
- We cover alternatives in more detail in <xref linkend="alternatives"/>.
- </para>
-
- </section>
-
- <section>
- <title>Interceptor binding types</title>
-
- <para>
- You might be familiar with the use of interceptors in EJB 3.0. In Java EE 6, this functionality has
- been generalized to work with other managed beans. That's right, you no longer have to make your bean
- an EJB just to intercept its methods. Holler. So what does CDI have to offer above and beyond that? Well,
- quite a lot actually. Let's cover some background.
- </para>
-
- <para>
- The way that interceptors were defined in Java EE 5 was counter-intuitive. You were required to specify the
- <emphasis>implementation</emphasis> of the interceptor directly on the <emphasis>implementation</emphasis>
- of the EJB, either in the <literal>@Interceptors</literal> annotation or in the XML descriptor. You might as
- well just put the interceptor code <emphasis>in</emphasis> the implementation! Second, the order in which
- the interceptors are applied is taken from the order in which they are declared in the annotation or the XML
- descriptor. Perhaps this isn't so bad if you're applying the interceptors to a single bean. But, if you are
- applying them repeatedly, then there's a good chance that you'll inadvertently define a different order for
- different beans. Now that's a problem.
- </para>
-
- <para>
- CDI provides a new approach to binding interceptors to beans that introduces a level of indirection (and
- thus control). We must define an <emphasis>interceptor binding type</emphasis> to describe the behavior
- implemented by the interceptor.
- </para>
-
- <para>
- An interceptor binding type is a user-defined annotation that is itself annotated <literal>@InterceptorBinding</literal>.
- It lets us bind interceptor classes to bean classes with no direct dependency between the two classes.
- </para>
-
- <programlisting role="JAVA"><![CDATA[@InterceptorBinding
-@Inherited
-@Target( { TYPE, METHOD })
-@Retention(RUNTIME)
-public @interface Transactional {}]]></programlisting>
-
- <para>
- The interceptor that implements transaction management declares this annotation:
- </para>
-
- <programlisting role="JAVA"><![CDATA[public @Transactional @Interceptor
-class TransactionInterceptor { ... }]]></programlisting>
-
- <para>
- We can apply the interceptor to a bean by annotating the bean class with the same interceptor binding type:
- </para>
-
- <programlisting role="JAVA"><![CDATA[public @SessionScoped @Transactional
-class ShoppingCart implements Serializable { ... }]]></programlisting>
-
- <para>
- Notice that <literal>ShoppingCart</literal> and <literal>TransactionInterceptor</literal> don't know
- anything about each other.
- </para>
-
- <para>
- Interceptors are deployment-specific. (We don't need a <literal>TransactionInterceptor</literal> in our
- unit tests!) By default, an interceptor is disabled. We can enable an interceptor using the CDI deployment
- descriptor <literal>META-INF/beans.xml</literal> of the jar or Java EE module. This is also where we
- specify the interceptor ordering.
- </para>
-
- <para>
- We'll discuss interceptors, and their cousins, decorators, in <xref linkend="interceptors"/> and <xref
- linkend="decorators"/>.
- </para>
-
- </section>
-
- </section>
-
- <section>
- <title>What kinds of classes are beans?</title>
-
- <para>
- We've already seen two types of beans: JavaBeans and EJB session beans. Is that the whole story? Actually,
- it's just the beginning. Let's explore the various kinds of beans that CDI implementations must support
- out-of-the-box.
- </para>
-
- <section>
- <title>Managed beans</title>
-
- <para>
- A managed bean is a Java class. The basic lifecycle and semantics of a managed bean are defined by the
- Managed Beans specification. You can explicitly declare a managed bean by annotating the bean class
- <literal>@ManagedBean</literal>, but in CDI you don't need to. According to the specification, the CDI
- container treats any class that satisfies the following conditions as a managed bean:
- </para>
-
- <blockquote>
-
- <itemizedlist>
- <listitem>
- <para>It is not a non-static inner class.</para>
- </listitem>
- <listitem>
- <para>It is a concrete class, or is annotated <literal>@Decorator</literal>.</para>
- </listitem>
- <listitem>
- <para>
- It is not annotated with an EJB component-defining annotation or declared as an EJB bean class in
- <literal>ejb-jar.xml</literal>.
- </para>
- </listitem>
- <listitem>
- <para>It does not implement <literal>javax.enterprise.inject.spi.Extension</literal>.</para>
- </listitem>
- <listitem>
- <para>
- It has an appropriate constructor—either:
- </para>
- <itemizedlist>
- <listitem>
- <para>the class has a constructor with no parameters, or</para>
- </listitem>
- <listitem>
- <para>the class declares a constructor annotated <literal>@Inject</literal>.</para>
- </listitem>
- </itemizedlist>
- </listitem>
- </itemizedlist>
-
- </blockquote>
-
- <para>The unrestricted set of bean types for a managed bean contains the bean class, every superclass and all
- interfaces it implements directly or indirectly.</para>
-
- <para>If a managed bean has a public field, it must have the default scope <literal>@Dependent</literal>.</para>
-
- <para>Managed beans support the <literal>@PostConstruct</literal> and <literal>@PreDestroy</literal> lifecycle
- callbacks.</para>
-
- <para>
- Session beans are also, technically, managed beans. However, since they have their own special lifecycle and
- take advantage of additional enterprise services, the CDI specification considers them to be a different
- kind of bean.
- </para>
-
- </section>
-
- <section>
- <title>Session beans</title>
-
- <para>
- Session beans belong to the EJB specification. They have a special lifecycle, state management and concurrency
- model that is different to other managed beans and non-managed Java objects. But session beans participate in
- CDI just like any other bean. You can inject one session bean into another session bean, a managed bean into a
- session bean, a session bean into a managed bean, have a managed bean observe an event raised by a session bean,
- and so on.
- </para>
-
- <note>
- <para>
- Message-driven and entity beans are by nature non-contextual objects and may not be injected into other
- objects. However, message-driven beans can take advantage of some CDI functionality, such as dependency
- injection, interceptors and decorators. In fact, CDI will perform injection into any session or
- message-driven bean, even those which are not contextual instances.
- </para>
- </note>
-
- <para>
- The unrestricted set of bean types for a session bean contains all local interfaces of the bean and their
- superinterfaces. If the session bean has a bean class local view, the unrestricted set of bean types
- contains the bean class and all superclasses. In addition, <literal>java.lang.Object</literal> is a bean
- type of every session bean. But remote interfaces are <emphasis>not</emphasis> included in the set of bean
- types.
- </para>
-
- <para>There's no reason to explicitly declare the scope of a stateless session bean or singleton session bean.
- The EJB container controls the lifecycle of these beans, according to the semantics of the <literal>@Stateless</literal>
- or <literal>@Singleton</literal> declaration. On the other hand, a stateful session bean may have any scope.</para>
-
- <para>
- Stateful session beans may define a <emphasis>remove method</emphasis>, annotated <literal>@Remove</literal>,
- that is used by the application to indicate that an instance should be destroyed. However, for a contextual
- instance of the bean—an instance under the control of CDI—this method may only be called by the
- application if the bean has scope <literal>@Dependent</literal>. For beans with other scopes, the application
- must let the container destroy the bean.
- </para>
-
- <para>
- So, when should we use a session bean instead of a plain managed bean? Whenever we need the advanced enterprise
- services offered by EJB, such as:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>method-level transaction management and security,</para>
- </listitem>
- <listitem>
- <para>concurrency management,</para>
- </listitem>
- <listitem>
- <para>instance-level passivation for stateful session beans and
- instance-pooling for stateless session beans,</para>
- </listitem>
- <listitem>
- <para>remote or web service invocation, or</para>
- </listitem>
- <listitem>
- <para>timers and asynchronous methods,</para>
- </listitem>
- </itemizedlist>
-
- <para>When we don't need any of these things, an ordinary managed bean will serve just fine.</para>
-
- <para>
- Many beans (including any <literal>@SessionScoped</literal> or <literal>@ApplicationScoped</literal>
- beans) are available for concurrent access. Therefore, the concurrency management provided by EJB 3.1
- is especially useful. Most session and application scoped beans should be EJBs.
- </para>
-
- <para>
- Beans which hold references to heavy-weight resources, or hold a lot of internal state benefit from the
- advanced container-managed lifecycle defined by the EJB stateless/stateful/singleton model, with its
- support for passivation and instance pooling.
- </para>
-
- <para>
- Finally, it's usually obvious when method-level transaction management, method-level security, timers,
- remote methods or asynchronous methods are needed.
- </para>
-
- <para>
- The point we're trying to make is: use a session bean when you need the services it provides, not just
- because you want to use dependency injection, lifecycle management, or interceptors. Java EE 6 provides
- a graduated programming model. It's usually easy to start with an ordinary managed bean, and later turn
- it into an EJB just by adding one of the following annotations: <literal>@Stateless</literal>,
- <literal>@Stateful</literal> or <literal>@Singleton</literal>.
- </para>
-
- <para>
- On the other hand, don't be scared to use session beans just because you've heard your friends say
- they're "heavyweight". It's nothing more than superstition to think that something is "heavier" just
- because it's hosted natively within the Java EE container, instead of by a proprietary bean container
- or dependency injection framework that runs as an additional layer of obfuscation. And as a general
- principle, you should be skeptical of folks who use vaguely defined terminology like "heavyweight".
- </para>
-
- </section>
-
- <section>
- <title>Producer methods</title>
-
- <para>
- Not everything that needs to be injected can be boiled down to a bean class instantiated by the container
- using <literal>new</literal>. There are plenty of cases where we need additional control. What if we need
- to decide at runtime which implementation of a type to instantiate and inject? What if we need to inject
- an object that is obtained by querying a service or transactional resource, for example by executing a JPA
- query?
- </para>
-
- <para>
- A <emphasis>producer method</emphasis> is a method that acts as a source of bean instances. The method
- declaration itself describes the bean and the container invokes the method to obtain an instance of the
- bean when no instance exists in the specified context. A producer method lets the application take full
- control of the bean instantiation process.
- </para>
-
- <para>
- A producer method is declared by annotating a method of a bean class with the <literal>@Produces</literal>
- annotation.
- </para>
-
- <programlisting role="JAVA"><![CDATA[@ApplicationScoped
-public class RandomNumberGenerator {
-
- private Random random = new Random(System.currentTimeMillis());
-
- @Produces @Named @Random int getRandomNumber() {
- return random.nextInt(100);
- }
-
-}]]></programlisting>
-
- <para>
- We can't write a bean class that is itself a random number. But we can certainly write a method that returns
- a random number. By making the method a producer method, we allow the return value of the method—in this
- case an <literal>Integer</literal>—to be injected. We can even specify a qualifier—in this case
- <literal>@Random</literal>, a scope—which in this case defaults to <literal>@Dependent</literal>,
- and an EL name—which in this case defaults to <literal>randomNumber</literal> according to the JavaBeans
- property name convention. Now we can get a random number anywhere:
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Inject @Random int randomNumber;]]></programlisting>
-
- <para>
- Even in a Unified EL expression:
- </para>
-
- <programlisting><![CDATA[<p>Your raffle number is #{randomNumber}.</p>]]></programlisting>
-
- <para>
- A producer method must be a non-abstract method of a managed bean class or session bean class. A producer
- method may be either static or non-static. If the bean is a session bean, the producer method must be either
- a business method of the EJB or a static method of the bean class.
- </para>
-
- <para>
- The bean types of a producer method depend upon the method return type:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- If the return type is an interface, the unrestricted set of bean types contains the return type, all
- interfaces it extends directly or indirectly and <literal>java.lang.Object</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- If a return type is primitive or is a Java array type, the unrestricted set of bean types contains
- exactly two types: the method return type and <literal>java.lang.Object</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- If the return type is a class, the unrestricted set of bean types contains the return type, every
- superclass and all interfaces it implements directly or indirectly.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- If the producer method has method parameters, the container will look for a bean that satisfies the type
- and qualifiers of each parameter and pass it to the method automatically—another form of
- dependency injection.
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Produces Set<Roles> getRoles(User user) {
- return user.getRoles();
-}]]></programlisting>
-
- <para>We'll talk much more about producer methods in <xref linkend="producermethods"/>.</para>
-
- </section>
-
- <section>
- <title>Producer fields</title>
-
- <para>
- A <emphasis>producer field</emphasis> is a simpler alternative to a producer method. A producer field is
- declared by annotating a field of a bean class with the <literal>@Produces</literal> annotation—the
- same annotation used for producer methods.
- </para>
-
- <programlisting role="JAVA"><![CDATA[public class Shop {
- @Produces PaymentProcessor paymentProcessor = ....;
- @Produces @Catalog List<Product> products = ....;
-}]]></programlisting>
-
- <para>
- The rules for determining the bean types of a producer field parallel the rules for producer methods.
- </para>
-
- <para>
- A producer field is really just a shortcut that lets us avoid writing a useless getter method. However,
- in addition to convenience, producer fields serve a specific purpose as an adaptor for Java EE component
- environment injection, but to learn more about that, you'll have to wait until <xref linkend="resources"/>.
- Because we can't wait to get to work on some examples.
- </para>
-
- </section>
-
- </section>
-
<!--
vim:et:ts=3:sw=3:tw=120
-->
Modified: doc/trunk/reference/en-US/master.xml
===================================================================
--- doc/trunk/reference/en-US/master.xml 2009-11-10 07:50:26 UTC (rev 4947)
+++ doc/trunk/reference/en-US/master.xml 2009-11-10 08:17:29 UTC (rev 4948)
@@ -38,40 +38,33 @@
<xi:include href="part1.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="intro.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="beans.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="example.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="injection.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="scopescontexts.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <!-- TODO <xi:include href="producerfields.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> -->
</part>
- <part id="1.5">
+ <part id="2">
<title>Weld, the CDI Reference Implementation</title>
- <xi:include href="part1.5.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="part2.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="gettingstarted.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="weldexamples.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
- <part id="2">
- <title>Developing loosely-coupled code</title>
+ <part id="3">
+ <title>Loose coupling with strong typing</title>
- <xi:include href="part2.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="part3.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="producermethods.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="interceptors.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="decorators.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="events.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- </part>
-
- <part id="3">
- <title>Making the most of strong typing</title>
- <xi:include href="part3.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
-
<xi:include href="stereotypes.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="specialization.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="resources.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
Modified: doc/trunk/reference/en-US/part2.xml
===================================================================
--- doc/trunk/reference/en-US/part2.xml 2009-11-10 07:50:26 UTC (rev 4947)
+++ doc/trunk/reference/en-US/part2.xml 2009-11-10 08:17:29 UTC (rev 4948)
@@ -3,64 +3,16 @@
<partintro>
<para>
- The first major theme of CDI is <emphasis>loose coupling</emphasis>. We've already seen three means of achieving
- loose coupling:
+ Weld, the JSR-299 Reference Implementation (RI), is being developed as part of the <ulink
+ url="http://seamframework.org/Weld">Seam project</ulink>. You can download the latest community release of Weld
+ from the <ulink url="http://seamframework.org/Download">download page</ulink>. Information about the Weld source
+ code repository and instructions about how to obtain and build the source can be found on the same page.
</para>
-
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>alternatives</emphasis> enable deployment time polymorphism,
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>producer methods</emphasis> enable runtime polymorphism, and</para>
- </listitem>
- <listitem>
- <para>
- <emphasis>contextual lifecycle management</emphasis> decouples bean lifecycles.
- </para>
- </listitem>
- </itemizedlist>
-
+
<para>
- These techniques serve to enable loose coupling of client and server. The client is no longer tightly bound to an
- implementation of an interface, nor is it required to manage the lifecycle of the implementation. This approach
- lets <emphasis>stateful objects interact as if they were services</emphasis>.
+ Weld comes with an extensive library of examples, which are a great starting point from which to learn CDI.
</para>
-
- <para>
- Loose coupling makes a system more <emphasis>dynamic</emphasis>. The system can respond to change in a
- well-defined manner. In the past, frameworks that attempted to provide the facilities listed above invariably did
- it by sacrificing type safety (most notably by using XML descriptors). CDI is the first technology, and certainly
- the first specification in the Java EE platform, that achieves this level of loose coupling in a typesafe way.
- </para>
-
- <para>
- CDI provides three extra important facilities that further the goal of loose coupling:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>interceptors</emphasis> decouple technical concerns from business logic,
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>decorators</emphasis> may be used to decouple some business concerns, and
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>event notifications</emphasis> decouple event producers from event consumers.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>Let's explore producer methods first.</para>
-
+
<!--
vim:et:ts=3:sw=3:tw=120
-->
Modified: doc/trunk/reference/en-US/part3.xml
===================================================================
--- doc/trunk/reference/en-US/part3.xml 2009-11-10 07:50:26 UTC (rev 4947)
+++ doc/trunk/reference/en-US/part3.xml 2009-11-10 08:17:29 UTC (rev 4948)
@@ -1,8 +1,65 @@
<!DOCTYPE partintro PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
<partintro>
-
+
<para>
+ The first major theme of CDI is <emphasis>loose coupling</emphasis>. We've already seen three means of achieving
+ loose coupling:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>alternatives</emphasis> enable deployment time polymorphism,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>producer methods</emphasis> enable runtime polymorphism, and</para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>contextual lifecycle management</emphasis> decouples bean lifecycles.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ These techniques serve to enable loose coupling of client and server. The client is no longer tightly bound to an
+ implementation of an interface, nor is it required to manage the lifecycle of the implementation. This approach
+ lets <emphasis>stateful objects interact as if they were services</emphasis>.
+ </para>
+
+ <para>
+ Loose coupling makes a system more <emphasis>dynamic</emphasis>. The system can respond to change in a
+ well-defined manner. In the past, frameworks that attempted to provide the facilities listed above invariably did
+ it by sacrificing type safety (most notably by using XML descriptors). CDI is the first technology, and certainly
+ the first specification in the Java EE platform, that achieves this level of loose coupling in a typesafe way.
+ </para>
+
+ <para>
+ CDI provides three extra important facilities that further the goal of loose coupling:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>interceptors</emphasis> decouple technical concerns from business logic,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>decorators</emphasis> may be used to decouple some business concerns, and
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>event notifications</emphasis> decouple event producers from event consumers.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
The second major theme of CDI is <emphasis>strong typing</emphasis>. The information about the dependencies,
interceptors and decorators of a bean, and the information about event consumers for an event producer, is
contained in typesafe Java constructs that may be validated by the compiler.
@@ -84,7 +141,7 @@
<emphasis>need</emphasis> to use these features, but if you use them wisely, you'll come to appreciate their
power.
</para>
-
+
<!--
vim:et:ts=3:sw=3:tw=120
-->
14 years, 7 months
Weld SVN: r4947 - doc/trunk/reference/en-US.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-11-10 02:50:26 -0500 (Tue, 10 Nov 2009)
New Revision: 4947
Modified:
doc/trunk/reference/en-US/intro.xml
doc/trunk/reference/en-US/master.xml
doc/trunk/reference/en-US/part2.xml
Log:
more reorg
Modified: doc/trunk/reference/en-US/intro.xml
===================================================================
--- doc/trunk/reference/en-US/intro.xml 2009-11-10 07:35:33 UTC (rev 4946)
+++ doc/trunk/reference/en-US/intro.xml 2009-11-10 07:50:26 UTC (rev 4947)
@@ -455,7 +455,7 @@
<para>
That's not quite the end of the story. CDI also defines a simple <emphasis>resolution rule</emphasis> that helps
the container decide what to do if there is more than one bean that satisfies a particular contract. We'll get
- into the details in <xref linkend="alternatives"/>.
+ into the details in <xref linkend="injection"/>.
</para>
<!--
@@ -578,10 +578,9 @@
deployment descriptor <literal>META-INF/beans.xml</literal> of the jar or Java EE module that uses
it. Different modules can specify that they use different alternatives.
</para>
-
+
<para>
- Details on how to enable alternative beans, and how you can use them to specialize (override) beans
- and producer methods is covered in <xref linkend="3"/>.
+ We cover alternatives in more detail in <xref linkend="alternatives"/>.
</para>
</section>
Modified: doc/trunk/reference/en-US/master.xml
===================================================================
--- doc/trunk/reference/en-US/master.xml 2009-11-10 07:35:33 UTC (rev 4946)
+++ doc/trunk/reference/en-US/master.xml 2009-11-10 07:50:26 UTC (rev 4947)
@@ -41,7 +41,6 @@
<xi:include href="example.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="injection.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="scopescontexts.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="producermethods.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<!-- TODO <xi:include href="producerfields.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> -->
</part>
@@ -61,6 +60,7 @@
<xi:include href="part2.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="producermethods.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="interceptors.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="decorators.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="events.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
Modified: doc/trunk/reference/en-US/part2.xml
===================================================================
--- doc/trunk/reference/en-US/part2.xml 2009-11-10 07:35:33 UTC (rev 4946)
+++ doc/trunk/reference/en-US/part2.xml 2009-11-10 07:50:26 UTC (rev 4947)
@@ -59,7 +59,7 @@
</listitem>
</itemizedlist>
- <para>Let's explore interceptors first.</para>
+ <para>Let's explore producer methods first.</para>
<!--
vim:et:ts=3:sw=3:tw=120
14 years, 7 months
Weld SVN: r4946 - doc/trunk/reference/en-US.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-11-10 02:35:33 -0500 (Tue, 10 Nov 2009)
New Revision: 4946
Added:
doc/trunk/reference/en-US/resources.xml
Modified:
doc/trunk/reference/en-US/ee.xml
doc/trunk/reference/en-US/interceptors.xml
doc/trunk/reference/en-US/intro.xml
doc/trunk/reference/en-US/master.xml
doc/trunk/reference/en-US/part3.xml
Log:
more reorg
Modified: doc/trunk/reference/en-US/ee.xml
===================================================================
--- doc/trunk/reference/en-US/ee.xml 2009-11-10 07:10:46 UTC (rev 4945)
+++ doc/trunk/reference/en-US/ee.xml 2009-11-10 07:35:33 UTC (rev 4946)
@@ -6,14 +6,48 @@
<para>
CDI is fully integrated into the Java EE environment. Beans have access to Java EE resources and JPA persistence
contexts. They may be used in Unified EL expressions in JSF and JSP pages. They may even be injected into other
- platform components, such as Servlets and Message-Driven Beans, which are not beans themselves.
+ platform components, such as servlets and message-driven Beans, which are not beans themselves.
</para>
+ <section>
+ <title>Built-in beans</title>
+
+ <para>
+ In the Java EE environment, the container provides the following built-in beans, all with the qualifier
+ <literal>@Default</literal>:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ the current JTA <literal>UserTransaction</literal>,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a <literal>Principal</literal> representing the current caller identity,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the default <ulink src="http://jcp.org/en/jsr/detail?id=303">Bean Validation</ulink>
+ <literal>ValidationFactory</literal>, and
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a <literal>Validator</literal> for the default <literal>ValidationFactory</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </section>
+
<section>
<title>Injecting Java EE resources into a bean</title>
<para>
- All managed beans may take advantage of Java EE dependency injection using <literal>@Resource</literal>,
+ All managed beans may take advantage of Java EE component environment injection using <literal>@Resource</literal>,
<literal>@EJB</literal>, <literal>@PersistenceContext</literal>, <literal>@PeristenceUnit</literal> and
<literal>@WebServiceRef</literal>. We've already seen a couple of examples of this, though we didn't pay
much attention at the time:
@@ -38,6 +72,11 @@
for all managed beans. The <literal>@PostConstruct</literal> method is called after <emphasis>all</emphasis>
injection has been performed.
</para>
+
+ <para>
+ Of course, we advise that component environment injection be used to define CDI resources, and that typesafe
+ injection be used in application code.
+ </para>
</section>
Modified: doc/trunk/reference/en-US/interceptors.xml
===================================================================
--- doc/trunk/reference/en-US/interceptors.xml 2009-11-10 07:10:46 UTC (rev 4945)
+++ doc/trunk/reference/en-US/interceptors.xml 2009-11-10 07:35:33 UTC (rev 4946)
@@ -112,7 +112,7 @@
<programlisting role="JAVA"><![CDATA[@Transactional @Interceptor
public class TransactionInterceptor {
- @Inject UserTransaction transaction;
+ @Resource UserTransaction transaction;
@AroundInvoke
public Object manageTransaction(InvocationContext ctx) throws Exception { ... }
Modified: doc/trunk/reference/en-US/intro.xml
===================================================================
--- doc/trunk/reference/en-US/intro.xml 2009-11-10 07:10:46 UTC (rev 4945)
+++ doc/trunk/reference/en-US/intro.xml 2009-11-10 07:35:33 UTC (rev 4946)
@@ -947,122 +947,11 @@
<para>
A producer field is really just a shortcut that lets us avoid writing a useless getter method. However,
in addition to convenience, producer fields serve a specific purpose as an adaptor for Java EE component
- environment injection.
+ environment injection, but to learn more about that, you'll have to wait until <xref linkend="resources"/>.
+ Because we can't wait to get to work on some examples.
</para>
</section>
-
- <section>
- <title>Java EE resources</title>
-
- <para>
- Java EE 5 already introduced some limited support for dependency injection, in the form of component
- environment injection. A component environment resource is a Java EE component, for example a JDBC
- datasource, JMS queue or topic, JPA persistence context, remote EJB or web service.
- </para>
-
- <para>
- Naturally, there is now a slight mismatch with the new style of dependency injection in CDI. Most notably,
- component environment injection relies on string-based names to qualify ambiguous types, and there is no
- real consistency as to the nature of the names (sometimes a JNDI name, sometimes a persistence unit name,
- sometimes an EJB link, sometimes a nonportable "mapped name"). Producer fields turned out to be an elegant
- adaptor to reduce all this complexity to a common model and get component environment resources to
- participate in the CDI system just like any other kind of bean.
- </para>
-
- <para>
- Fields have a duality in that they can both be the target of Java EE component environment injection and be
- declared as a CDI producer field. Therefore, they can define a mapping from a string-based name in the
- component environment, to a combination of type and qualifiers used in the world of typesafe injection. We
- call a producer field that represents a reference to an object in the Java EE component environment a
- <emphasis>resource</emphasis>.
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Produces @WebServiceRef(lookup="java:app/service/Catalog")
-Catalog catalog;]]></programlisting>
-
- <programlisting role="JAVA"><![CDATA[@Produces @Resource(lookup="java:global/env/jdbc/CustomerDatasource")
-@CustomerDatabase Datasource customerDatabase;]]></programlisting>
-
- <programlisting role="JAVA"><![CDATA[@Produces @PersistenceContext(unitName="CustomerDatabase")
-@CustomerDatabase EntityManager customerDatabasePersistenceContext;]]></programlisting>
-
- <programlisting role="JAVA"><![CDATA[@Produces @PersistenceUnit(unitName="CustomerDatabase")
-@CustomerDatabase EntityManagerFactory customerDatabasePersistenceUnit;]]></programlisting>
-
- <programlisting role="JAVA"><![CDATA[@Produces @EJB(ejbLink="../their.jar#PaymentService")
-PaymentService paymentService;]]></programlisting>
-
- <para>
- These resources can then be injected in the usual way.
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Inject Catalog catalog;]]></programlisting>
- <programlisting role="JAVA"><![CDATA[@Inject @CustomerDatabase Datasource customerDatabase;]]></programlisting>
- <programlisting role="JAVA"><![CDATA[@Inject @CustomerDatabase EntityManager customerDatabaseEntityManager;]]></programlisting>
- <programlisting role="JAVA"><![CDATA[@Inject @CustomerDatabase EntityManagerFactory customerDatabaseEntityManagerFactory;]]></programlisting>
- <programlisting role="JAVA"><![CDATA[@Inject PaymentService paymentService;]]></programlisting>
-
- <para>
- The bean type and qualifiers of the resource are determined by the producer field declaration.
- </para>
-
- <para>
- It might seem like a pain to have to write these extra producer field declarations, just to gain an additional
- level of indirection. You could just as well use component environment injection directly, right? But remember
- that you're going to be using resources like the <literal>EntityManager</literal> in several different beans.
- Isn't it nicer and more typesafe to write
- </para>
-
- <programlisting>@Inject @CustomerDatabase EntityManager</programlisting>
-
- <para>instead of</para>
-
- <programlisting>@PersistenceContext(unitName="CustomerDatabase") EntityManager</programlisting>
-
- <para>
- all over the place?
- </para>
-
- </section>
-
- <section>
- <title>Built-in beans</title>
-
- <para>
- In the Java EE environment, we get some additional goodies. The container provides the following
- built-in beans, all with the qualifier <literal>@Default</literal>:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- the current JTA <literal>UserTransaction</literal>,
- </para>
- </listitem>
- <listitem>
- <para>
- a <literal>Principal</literal> representing the current caller identity,
- </para>
- </listitem>
- <listitem>
- <para>
- the default <ulink src="http://jcp.org/en/jsr/detail?id=303">Bean Validation</ulink>
- <literal>ValidationFactory</literal>, and
- </para>
- </listitem>
- <listitem>
- <para>
- a <literal>Validator</literal> for the default <literal>ValidationFactory</literal>.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Can't wait to get started? Great! In the next two chapters, we'll start working on some examples.
- </para>
-
- </section>
</section>
Modified: doc/trunk/reference/en-US/master.xml
===================================================================
--- doc/trunk/reference/en-US/master.xml 2009-11-10 07:10:46 UTC (rev 4945)
+++ doc/trunk/reference/en-US/master.xml 2009-11-10 07:35:33 UTC (rev 4946)
@@ -74,6 +74,7 @@
<xi:include href="stereotypes.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="specialization.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="resources.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
Modified: doc/trunk/reference/en-US/part3.xml
===================================================================
--- doc/trunk/reference/en-US/part3.xml 2009-11-10 07:10:46 UTC (rev 4945)
+++ doc/trunk/reference/en-US/part3.xml 2009-11-10 07:35:33 UTC (rev 4946)
@@ -3,7 +3,7 @@
<partintro>
<para>
- The second major theme of Weld is <emphasis>strong typing</emphasis>. The information about the dependencies,
+ The second major theme of CDI is <emphasis>strong typing</emphasis>. The information about the dependencies,
interceptors and decorators of a bean, and the information about event consumers for an event producer, is
contained in typesafe Java constructs that may be validated by the compiler.
</para>
Added: doc/trunk/reference/en-US/resources.xml
===================================================================
--- doc/trunk/reference/en-US/resources.xml (rev 0)
+++ doc/trunk/reference/en-US/resources.xml 2009-11-10 07:35:33 UTC (rev 4946)
@@ -0,0 +1,96 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<chapter id="resources">
+
+ <title>Java EE component environment resources</title>
+
+ <para>
+ Java EE 5 already introduced some limited support for dependency injection, in the form of component
+ environment injection. A component environment resource is a Java EE component, for example a JDBC
+ datasource, JMS queue or topic, JPA persistence context, remote EJB or web service.
+ </para>
+
+ <para>
+ Naturally, there is now a slight mismatch with the new style of dependency injection in CDI. Most notably,
+ component environment injection relies on string-based names to qualify ambiguous types, and there is no
+ real consistency as to the nature of the names (sometimes a JNDI name, sometimes a persistence unit name,
+ sometimes an EJB link, sometimes a nonportable "mapped name"). Producer fields turned out to be an elegant
+ adaptor to reduce all this complexity to a common model and get component environment resources to
+ participate in the CDI system just like any other kind of bean.
+ </para>
+
+ <para>
+ Fields have a duality in that they can both be the target of Java EE component environment injection and be
+ declared as a CDI producer field. Therefore, they can define a mapping from a string-based name in the
+ component environment, to a combination of type and qualifiers used in the world of typesafe injection. We
+ call a producer field that represents a reference to an object in the Java EE component environment a
+ <emphasis>resource</emphasis>.
+ </para>
+
+ <section>
+ <title>Defining a resource</title>
+
+ <para>We declare a resource by annotating a producer field with a component environment injection
+ annotation: <literal>@Resource</literal>, <literal>@EJB</literal>, <literal>@PersistenceContext</literal>,
+ <literal>@PersistenceUnit</literal> or <literal>@WebServiceRef</literal>.</para>
+
+ <programlisting role="JAVA"><![CDATA[@Produces @WebServiceRef(lookup="java:app/service/Catalog")
+Catalog catalog;]]></programlisting>
+
+ <programlisting role="JAVA"><![CDATA[@Produces @Resource(lookup="java:global/env/jdbc/CustomerDatasource")
+@CustomerDatabase Datasource customerDatabase;]]></programlisting>
+
+ <programlisting role="JAVA"><![CDATA[@Produces @PersistenceContext(unitName="CustomerDatabase")
+@CustomerDatabase EntityManager customerDatabasePersistenceContext;]]></programlisting>
+
+ <programlisting role="JAVA"><![CDATA[@Produces @PersistenceUnit(unitName="CustomerDatabase")
+@CustomerDatabase EntityManagerFactory customerDatabasePersistenceUnit;]]></programlisting>
+
+ <programlisting role="JAVA"><![CDATA[@Produces @EJB(ejbLink="../their.jar#PaymentService")
+PaymentService paymentService;]]></programlisting>
+
+ <para>The field may be static (but not final).</para>
+
+ <para>It might feel strange to be declaring resources in Java code. Isn't this stuff that might be
+ deployment-specific? Certainly, and that's why it makes sense to declare your resources in a class
+ annotation <literal>@Alternative</literal>.</para>
+
+ </section>
+
+ <section>
+ <title>Typesafe resource injection</title>
+
+ <para>
+ These resources can now be injected in the usual way.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Inject Catalog catalog;]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[@Inject @CustomerDatabase Datasource customerDatabase;]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[@Inject @CustomerDatabase EntityManager customerDatabaseEntityManager;]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[@Inject @CustomerDatabase EntityManagerFactory customerDatabaseEntityManagerFactory;]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[@Inject PaymentService paymentService;]]></programlisting>
+
+ <para>
+ The bean type and qualifiers of the resource are determined by the producer field declaration.
+ </para>
+
+ <para>
+ It might seem like a pain to have to write these extra producer field declarations, just to gain an additional
+ level of indirection. You could just as well use component environment injection directly, right? But remember
+ that you're going to be using resources like the <literal>EntityManager</literal> in several different beans.
+ Isn't it nicer and more typesafe to write
+ </para>
+
+ <programlisting>@Inject @CustomerDatabase EntityManager</programlisting>
+
+ <para>instead of</para>
+
+ <programlisting>@PersistenceContext(unitName="CustomerDatabase") EntityManager</programlisting>
+
+ <para>
+ all over the place?
+ </para>
+
+ </section>
+
+</chapter>
14 years, 7 months
Weld SVN: r4945 - doc/trunk/reference/en-US.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-11-10 02:10:46 -0500 (Tue, 10 Nov 2009)
New Revision: 4945
Modified:
doc/trunk/reference/en-US/ee.xml
Log:
revisions
Modified: doc/trunk/reference/en-US/ee.xml
===================================================================
--- doc/trunk/reference/en-US/ee.xml 2009-11-10 06:29:16 UTC (rev 4944)
+++ doc/trunk/reference/en-US/ee.xml 2009-11-10 07:10:46 UTC (rev 4945)
@@ -14,13 +14,14 @@
<para>
All managed beans may take advantage of Java EE dependency injection using <literal>@Resource</literal>,
- <literal>@EJB</literal> and <literal>@PersistenceContext</literal>. We've already seen a couple of examples of
- this, though we didn't pay much attention at the time:
+ <literal>@EJB</literal>, <literal>@PersistenceContext</literal>, <literal>@PeristenceUnit</literal> and
+ <literal>@WebServiceRef</literal>. We've already seen a couple of examples of this, though we didn't pay
+ much attention at the time:
</para>
<programlisting role="JAVA"><![CDATA[@Transactional @Interceptor
public class TransactionInterceptor {
- @Resource Transaction transaction;
+ @Resource UserTransaction transaction;
@AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}]]></programlisting>
@@ -38,18 +39,13 @@
injection has been performed.
</para>
- <para>
- There is one restriction to be aware of here: <literal>@PersistenceContext(type=EXTENDED)</literal> is not
- supported for non-session beans (that's strictly a feature of stateful session beans).
- </para>
-
</section>
<section>
- <title>Calling a bean from a Servlet</title>
+ <title>Calling a bean from a servlet</title>
<para>
- It's easy to use a bean from a Servlet in Java EE 6. Simply inject the bean using field or initializer method
+ It's easy to use a bean from a servlet in Java EE 6. Simply inject the bean using field or initializer method
injection.
</para>
@@ -74,23 +70,22 @@
}]]></programlisting>
<para>
- Since instances of Servlets are shared across all incoming threads, the bean client proxy takes care of routing
- method invocations from the Servlet to the correct instances of <literal>Credentials</literal> and
+ Since instances of servlets are shared across all incoming threads, the bean client proxy takes care of routing
+ method invocations from the servlet to the correct instances of <literal>Credentials</literal> and
<literal>Login</literal> for the current request and HTTP session.
</para>
</section>
<section>
- <title>Calling a bean from a Message-Driven Bean</title>
+ <title>Calling a bean from a message-driven bean</title>
<para>
CDI injection applies to all EJBs, even when they aren't managed beans. In particular, you can use CDI
- injection in Message-Driven Beans, which are not considered beans because you can't inject them and their
- instances are not contextual (not even dependent).
+ injection in message-driven beans, which are by nature not contextual objects.
</para>
- <para>You can even use CDI interceptor bindings for Message-Driven Beans.</para>
+ <para>You can even use CDI interceptor bindings for message-driven Beans.</para>
<programlisting role="JAVA"><![CDATA[@Transactional @MessageDriven
public class ProcessOrder implements MessageListener {
@@ -103,14 +98,13 @@
}]]></programlisting>
<para>
- Thus, receiving messages is super-easy in an environment with CDI (e.g., Java EE 6). But beware that there is
- no session or conversation context available when a message is delivered to a Message-Driven Bean. Only
- <literal>@RequestScoped</literal> and <literal>@ApplicationScoped</literal> beans are available.
+ Please note that there is no session or conversation context available when a message is delivered to a
+ message-driven bean. Only <literal>@RequestScoped</literal> and <literal>@ApplicationScoped</literal>
+ beans are available.
</para>
<para>
- It's also easy to send messages using beans, if you require the full event bus of JMS rather than the
- architecturally simpler CDI event notification facility.
+ But how about beans which <emphasis>send</emphasis> JMS messages?
</para>
</section>
@@ -206,21 +200,17 @@
<title>Packaging and deployment</title>
<para>
- CDI doesn't define any special deployment archive. You can package beans in JARs, EJB-JARs or WARs — any
+ CDI doesn't define any special deployment archive. You can package beans in JARs, EJB-JARs or WARs—any
deployment location in the application classpath. However, the archive must be a "bean archive". That means
each archive that contains beans <emphasis>must</emphasis> include a file named <literal>beans.xml</literal> in
the <literal>META-INF</literal> directory of the classpath or <literal>WEB-INF</literal> directory of the web
root (for WAR archives). The file may be empty. Beans deployed in archives that do not have a
- <literal>beans.xml</literal> file (i.e., not in a bean archive) will not be available for use in the
- application.
-
+ <literal>beans.xml</literal> file will not be available for use in the application.
</para>
<para>
- For Java SE execution, beans may be deployed in any location in which EJBs may be deployed for execution by the
- embeddable EJB Lite container. Again, each location must contain a <literal>beans.xml</literal> file. (That
- doesn't rule out the possibility of having an extension which provides support for normal Java SE execution,
- like the Weld Java SE module).
+ In an embeddable EJB container, beans may be deployed in any location in which EJBs may be deployed. Again, each
+ location must contain a <literal>beans.xml</literal> file.
</para>
</section>
14 years, 7 months
Weld SVN: r4944 - doc/trunk/reference/en-US.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-11-10 01:29:16 -0500 (Tue, 10 Nov 2009)
New Revision: 4944
Modified:
doc/trunk/reference/en-US/injection.xml
doc/trunk/reference/en-US/specialization.xml
Log:
fallout from reorg
Modified: doc/trunk/reference/en-US/injection.xml
===================================================================
--- doc/trunk/reference/en-US/injection.xml 2009-11-10 05:59:22 UTC (rev 4943)
+++ doc/trunk/reference/en-US/injection.xml 2009-11-10 06:29:16 UTC (rev 4944)
@@ -315,14 +315,51 @@
<programlisting role="JAVA"><![CDATA[@Synchronous @Reliable
public class SynchronousReliablePaymentProcessor implements PaymentProcessor {
public void process(Payment payment) { ... }
-}]]></programlisting>
+}]]></programlisting>
</section>
</section>
+
+ <section id="alternatives">
+ <title>Alternatives</title>
+
+ <para>Alternatives are beans whose implementation is specific to a particular client module or deployment
+ scenario. This alternative defines a mock implementation of both <literal>@Synchronous PaymentProcessor</literal>
+ and <literal>@Asynchronous PaymentProcessor</literal>, all in one:</para>
+
+ <programlisting role="JAVA"><![CDATA[@Alternative @Synchronous @Asynchronous
+public class MockPaymentProcessor implements PaymentProcessor {
+ public void process(Payment payment) { ... }
+}]]></programlisting>
+
+ <para>
+ By default, <literal>@Alternative</literal> beans are disabled. We need to <emphasis>enable</emphasis> an
+ alternative in the <literal>beans.xml</literal> descriptor of a bean archive to make it available for
+ instantiation and injection. This activation only applies to the beans in that archive.
+ </para>
+ <programlisting role="XML"><![CDATA[<beans
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+ <alternatives>
+ <class>org.mycompany.mock.MockPaymentProcessor</class>
+ </alternatives>
+</beans>]]></programlisting>
+
+ <para>
+ When an ambiguous dependency exists at an injection point, the container attempts to resolve the ambiguity
+ by looking for an enabled alternative among the beans that could be injected. If there is exactly one
+ enabled alternative, that's the bean that will be injected.
+ </para>
+
+ </section>
+
<section>
- <title>Fixing unsatisfied dependencies</title>
+ <title>Fixing unsatisfied and ambiguous dependencies</title>
<para>
The typesafe resolution algorithm fails when, after considering the qualifier annotations on all beans that
Modified: doc/trunk/reference/en-US/specialization.xml
===================================================================
--- doc/trunk/reference/en-US/specialization.xml 2009-11-10 05:59:22 UTC (rev 4943)
+++ doc/trunk/reference/en-US/specialization.xml 2009-11-10 06:29:16 UTC (rev 4944)
@@ -47,68 +47,53 @@
alternatives and then show the guarantees that specialization adds.
</para>
- <section id="alternatives">
- <title>Alternatives</title>
+ <section id="alternativestereotypes">
+ <title>Using alternative stereotypes</title>
<para>
CDI lets you <emphasis>override</emphasis> the implementation of a bean type at deployment time using an
- alternative. For example, the following bean provides an implementation of the
- <literal>PaymentProcessor</literal> bean type in the default environment:
+ alternative. For example, the following bean provides a default implementation of the
+ <literal>PaymentProcessor</literal> interface:
</para>
- <programlisting role="JAVA"><![CDATA[@CreditCard
-public class CreditCardPaymentProcessor
+ <programlisting role="JAVA"><![CDATA[public class DefaultPaymentProcessor
implements PaymentProcessor {
...
}]]></programlisting>
<para>
- But in our staging environment, we override that implementation of <literal>PaymentProcessor</literal> with a
- different bean:
+ But in our staging environment, we don't really want to submit payments to the external system, so we override
+ that implementation of <literal>PaymentProcessor</literal> with a different bean:
</para>
- <programlisting role="JAVA"><![CDATA[@CreditCard @Alternative
-public class StagingCreditCardPaymentProcessor
+ <programlisting role="JAVA"><![CDATA[public @Alternative
+class StagingPaymentProcessor
implements PaymentProcessor {
...
}]]></programlisting>
<para>or</para>
- <programlisting role="JAVA"><![CDATA[@CreditCard @Alternative
-public class StagingCreditCardPaymentProcessor
- extends CreditCardPaymentProcessor {
+ <programlisting role="JAVA"><![CDATA[public @Alternative
+class StagingPaymentProcessor
+ extends DefaultPaymentProcessor {
...
}]]></programlisting>
<para>
- By default, <literal>@Alternative</literal> beans are disabled. We need to <emphasis>enable</emphasis> the
- alternative—effectively replacing the bean implementation without the <literal>@Alternative</literal>
- annotation—in the <literal>beans.xml</literal> descriptor of a bean archive by specifying the bean
- class (or the class that contains the alternative producer method or field). This activation only applies
- to the beans in that archive.
+ We've already seen how we can enable this alternative by listing its class in the <literal>beans.xml</literal>
+ descriptor.
</para>
- <programlisting role="XML"><![CDATA[<beans
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="
- http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
- <alternatives>
- <class>org.mycompany.myapp.StagingCreditCardProcessor</class>
- </alternatives>
-</beans>]]></programlisting>
-
<para>
- Of course, if the goal is to enable all the alternatives for the staging environment, it would make much more
- sense to make <literal>@Staging</literal> an <literal>@Alternative</literal> stereotype and annotate the
- staging beans with this stereotype instead. You'll see how this level of indirection pays off. First, we create
- the stereotype:
+ But suppose we have many alternatives in the staging environment. It would be much more convenient to be able
+ to enable them all at once. So let's make <literal>@Staging</literal> an <literal>@Alternative</literal> stereotype
+ and annotate the staging beans with this stereotype instead. You'll see how this level of indirection pays off.
+ First, we create the stereotype:
</para>
- <programlisting role="JAVA"><![CDATA[@Stereotype
-@Alternative
+ <programlisting role="JAVA"><![CDATA[@Alternative
+@Stereotype
@Retention(RUNTIME)
@Target(TYPE)
public @interface Staging {}]]></programlisting>
@@ -117,14 +102,14 @@
Then we replace the <literal>@Alternative</literal> annotation on our bean with <literal>@Staging</literal>:
</para>
- <programlisting role="JAVA"><![CDATA[@CreditCard @Staging
-public class StagingCreditCardPaymentProcessor
- extends CreditCardPaymentProcessor {
+ <programlisting role="JAVA"><![CDATA[@Staging
+public class StagingPaymentProcessor
+ implements PaymentProcessor {
...
}]]></programlisting>
<para>
- Finally, we activate the <literal>@Staging</literal> stereotype in the beans.xml descriptor:
+ Finally, we activate the <literal>@Staging</literal> stereotype in the <literal>beans.xml</literal> descriptor:
</para>
<programlisting role="XML"><![CDATA[<beans
@@ -139,20 +124,28 @@
</beans>]]></programlisting>
<para>
- Now, no matter how many staging beans we have, they will all be enabled at once. Does that mean the default
- implementation is disabled? Well, not exactly. If the default implementation has a qualifier, for instance
- <literal>@LargeTransaction</literal>, and the alternative does not, you could still inject the default
- implementation.
+ Now, no matter how many staging beans we have, they will all be enabled at once.
</para>
+
+ </section>
+
+ <section>
+ <title>A minor problem with alternatives</title>
+
+ <para>
+ When we enable an alternative, does that mean the default implementation is disabled? Well, not exactly. If the
+ default implementation has a qualifier, for instance <literal>@LargeTransaction</literal>, and the alternative
+ does not, you could still inject the default implementation.
+ </para>
- <programlisting role="JAVA"><![CDATA[@LargeTransaction @CreditCard PaymentProcessor paymentProcessor;]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[@Inject @LargeTransaction PaymentProcessor paymentProcessor;]]></programlisting>
<para>
- So we haven't completely replaced the default implementation in this deployment of the system. The only
- way one bean can completely override a second bean at all injection points is if it implements all the bean
- types and declares all the qualifiers of the second bean. However, if the second bean declares a producer
- method or observer method, then even this is not enough to ensure that the second bean is never called! We need
- something extra.
+ So we haven't completely replaced the default implementation in this deployment of the system. The only way one
+ bean can completely override a second bean at all injection points is if it implements all the bean types and
+ declares all the qualifiers of the second bean. However, if the second bean declares a producer method or
+ observer method, then even this is not enough to ensure that the second bean is never called! We need something
+ extra.
</para>
<para>
@@ -160,6 +153,7 @@
these traps. Specialization is a way of informing the system of your intent to completely replace and disable
an implementation of a bean.
</para>
+
</section>
<section>
14 years, 7 months
Weld SVN: r4943 - doc/trunk/reference/en-US.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-11-10 00:59:22 -0500 (Tue, 10 Nov 2009)
New Revision: 4943
Added:
doc/trunk/reference/en-US/part1.5.xml
doc/trunk/reference/en-US/weldexamples.xml
Modified:
doc/trunk/reference/en-US/example.xml
doc/trunk/reference/en-US/gettingstarted.xml
doc/trunk/reference/en-US/intro.xml
doc/trunk/reference/en-US/master.xml
Log:
reorg
Modified: doc/trunk/reference/en-US/example.xml
===================================================================
--- doc/trunk/reference/en-US/example.xml 2009-11-10 05:13:46 UTC (rev 4942)
+++ doc/trunk/reference/en-US/example.xml 2009-11-10 05:59:22 UTC (rev 4943)
@@ -115,7 +115,8 @@
</h:panelGroup>]]></programlisting>
<para>
- In the next chapter, we'll explore examples from the CDI reference implementation, Weld, in greater depth.
+ Hopefully, this example gave you a taste of the CDI programming model. In the next chapter, we'll explore
+ dependency injection in greater depth.
</para>
<!--
Modified: doc/trunk/reference/en-US/gettingstarted.xml
===================================================================
--- doc/trunk/reference/en-US/gettingstarted.xml 2009-11-10 05:13:46 UTC (rev 4942)
+++ doc/trunk/reference/en-US/gettingstarted.xml 2009-11-10 05:59:22 UTC (rev 4943)
@@ -2,16 +2,9 @@
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
<chapter id="gettingstarted">
- <title>Getting started with Weld, the JSR-299 reference implementation</title>
+ <title>Getting started with Weld</title>
<para>
- Weld, the JSR-299 Reference Implementation (RI), is being developed as part of the <ulink
- url="http://seamframework.org/Weld">Seam project</ulink>. You can download the latest community release of Weld
- from the <ulink url="http://seamframework.org/Download">download page</ulink>. Information about the Weld source
- code repository and instructions about how to obtain and build the source can be found on the same page.
- </para>
-
- <para>
Weld comes with two starter example applications, in addition to more specialized examples. The first,
<literal>weld-numberguess</literal>, is a web (WAR) example containing only non-transactional managed beans.
This example can be run on a wide range of servers, including JBoss AS, GlassFish, Apache Tomcat, Jetty, Google
@@ -215,26 +208,9 @@
pseudo-translating.
</para>
- <tip>
- <para>
- There are a number of other examples that use CDI and JSF together. Consult the readme.txt file in the
- following directories for introductions about how to run these examples.
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- examples/jsf/login - A basic login using a session-scoped bean.
- </para>
- </listitem>
- <listitem>
- <para>
- examples/jsf/permalink - A basic blog that demonstrates JSF 2.0 bookmarkable URL support using view
- parameters and pre-render view listeners. The build and deployment is based exclusively on Maven 2.
- </para>
- </listitem>
- </itemizedlist>
- </tip>
+ <para>
+ TODO Insert note about upgrading the Weld deployer that directs reader to section on the JBoss AS environment
+ </para>
</section>
@@ -568,1352 +544,13 @@
the lack of a trailing context path.
</para>
- <!-- NOTE Transition paragraph into the example explanation sections. -->
<para>
Now that you have gotten the starter applications deployed on the server of your choice, you probably want to
- know a little bit about how they actually work. It's time to pull the covers back and dive into the internals
- of these two examples. Let's start with the simpler of the two examples, <literal>weld-numberguess</literal>.
+ know a little bit about how they actually work.
</para>
</section>
-
- <section id="numberguess">
- <title>The numberguess example in depth</title>
-
- <para>
- In the numberguess application you get 10 attempts to guess a number between 1 and 100. After each
- attempt, you're told whether your guess was too high or too low.
- </para>
-
- <para>
- The numberguess example is comprised of a number of beans, configuration files and Facelets (JSF) views,
- packaged as a WAR module. Let's start by examining the configuration files.
- </para>
-
- <para>
- All the configuration files for this example are located in <literal>WEB-INF/</literal>, which can be found in
- the <literal>src/main/webapp</literal> directory of the example. First, we have the JSF 2.0 version of
- <literal>faces-config.xml</literal>. A standardized version of Facelets is the default view handler in JSF
- 2.0, so there's really nothing that we have to configure. Thus, the configuration consists of only the root
- element.
- </para>
-
- <programlisting role="XML"><![CDATA[<faces-config version="2.0"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="
- http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
-</faces-config>]]></programlisting>
- <para>
- There's also an empty <literal>beans.xml</literal> file, which tells the container to look for beans in this
- application and to activate the CDI services.
- </para>
-
- <para>
- Finally, there's the familiar <literal>web.xml</literal>:
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="faces.servlet" coords="10" />
- <area id="faces.servlet.mapping" coords="16" />
- <area id="faces.default.suffix" coords="21" />
- <area id="session.timeout" coords="26" />
- </areaspec>
- <programlisting role="XML"><![CDATA[<web-app version="2.5"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="
- http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
-
- <display-name>weld-jsf-numberguess-war</display-name>
- <description>Weld JSF numberguess example (WAR)</description>
-
- <servlet>
- <servlet-name>Faces Servlet</servlet-name>
- <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>Faces Servlet</servlet-name>
- <url-pattern>*.jsf</url-pattern>
- </servlet-mapping>
-
- <context-param>
- <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
- <param-value>.xhtml</param-value>
- </context-param>
-
- <session-config>
- <session-timeout>10</session-timeout>
- </session-config>
-
-</web-app>]]></programlisting>
- <calloutlist>
- <callout arearefs="faces.servlet">
- <para>
- Enable and initialize the JSF servlet
- </para>
- </callout>
- <callout arearefs="faces.servlet.mapping">
- <para>
- Configure requests for URLs ending in <literal>.jsf</literal> to be
- handled by JSF
- </para>
- </callout>
- <callout arearefs="faces.default.suffix">
- <para>
- Tell JSF that we will be giving our JSF views (Facelets templates) an
- extension of <literal>.xhtml</literal>
- </para>
- </callout>
- <callout arearefs="session.timeout">
- <para>
- Configure a session timeout of 10 minutes
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <note>
- <para>
- This demo uses JSF 2 as the view framework, but you can use Weld with any servlet-based web framework, such
- as JSF 1.2 or Wicket.
- </para>
- </note>
-
- <para>
- Let's take a look at the main JSF view, <literal>src/main/webapp/home.xhtml</literal>.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="template" coords="8" />
- <area id="statusMessages" coords="12" />
- <area id="instructions" coords="20" />
- <area id="guess" coords="27" />
- <area id="validator" coords="29" />
- <area id="submit" coords="30" />
- </areaspec>
- <programlisting role="HTML"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:ui="http://java.sun.com/jsf/facelets"
- xmlns:h="http://java.sun.com/jsf/html"
- xmlns:f="http://java.sun.com/jsf/core">
-
- <ui:composition template="/template.xhtml">
- <ui:define name="content">
- <h1>Guess a number...</h1>
- <h:form id="numberGuess">
- <div style="color: red">
- <h:messages id="messages" globalOnly="false"/>
- <h:outputText id="Higher" value="Higher!"
- rendered="#{game.number gt game.guess and game.guess ne 0}"/>
- <h:outputText id="Lower" value="Lower!"
- rendered="#{game.number lt game.guess and game.guess ne 0}"/>
- </div>
-
- <div>
- I'm thinking of a number between #{game.smallest} and #{game.biggest}.
- You have #{game.remainingGuesses} guesses remaining.
- </div>
-
- <div>
- Your guess:
- <h:inputText id="inputGuess" value="#{game.guess}"
- size="3" required="true" disabled="#{game.number eq game.guess}"
- validator="#{game.validateNumberRange}"/>
- <h:commandButton id="guessButton" value="Guess"
- action="#{game.check}" disabled="#{game.number eq game.guess}"/>
- </div>
- <div>
- <h:commandButton id="restartButton" value="Reset" action="#{game.reset}" immediate="true"/>
- </div>
- </h:form>
- </ui:define>
- </ui:composition>
-</html>]]></programlisting>
- <calloutlist>
- <callout arearefs="template">
- <para>
- Facelets is the built-in templating language for JSF. Here we are
- wrapping our page in a template which defines the layout.
- </para>
- </callout>
- <callout arearefs="statusMessages">
- <para>
- There are a number of messages which can be sent to the user,
- "Higher!", "Lower!" and "Correct!"
- </para>
- </callout>
- <callout arearefs="instructions">
- <para>
- As the user guesses, the range of numbers they can guess gets
- smaller - this sentence changes to make sure they know the
- number range of a valid guess.
- </para>
- </callout>
- <callout arearefs="guess">
- <para>
- This input field is bound to a bean property using a value
- expression.
- </para>
- </callout>
- <callout arearefs="validator">
- <para>
- A validator binding is used to make sure the user doesn't
- accidentally input a number outside of the range in which they
- can guess - if the validator wasn't here, the user might use
- up a guess on an out of bounds number.
- </para>
- </callout>
- <callout arearefs="submit">
- <para>
- And, of course, there must be a way for the user to send their
- guess to the server. Here we bind to an action method on the bean.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- The example exists of 4 classes, the first two of which are qualifiers. First, there is the
- <literal>@Random</literal> qualifier, used for injecting a random number:
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Qualifier
-@Target( { TYPE, METHOD, PARAMETER, FIELD })
-@Retention(RUNTIME)
-public @interface Random {}]]></programlisting>
-
- <para>
- There is also the <literal>@MaxNumber</literal> qualifier, used for
- injecting the maximum number that can be injected:
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Qualifier
-@Target( { TYPE, METHOD, PARAMETER, FIELD })
-@Retention(RUNTIME)
-public @interface MaxNumber {}
-]]></programlisting>
-
- <para>
- The application-scoped <literal>Generator</literal> class is responsible for creating the random number, via a
- producer method. It also exposes the maximum possible number via a producer method:
- </para>
-
- <programlisting role="JAVA"><![CDATA[@ApplicationScoped
-public class Generator implements Serializable {
-
- private java.util.Random random = new java.util.Random(System.currentTimeMillis());
-
- private int maxNumber = 100;
-
- java.util.Random getRandom() {
- return random;
- }
-
- @Produces @Random int next() {
- return getRandom().nextInt(maxNumber);
- }
-
- @Produces @MaxNumber int getMaxNumber() {
- return maxNumber;
- }
-
-}]]></programlisting>
-
- <para>
- The <literal>Generator</literal> is application scoped, so we don't get a different random each time.
- </para>
-
- <note>
- <para>
- The package declaration and imports have been excluded from these listings. The complete listing is
- available in the example source code.
- </para>
- </note>
-
- <para>
- The final bean in the application is the session-scoped <literal>Game</literal> class. This is the primary
- entry point of the application. It's responsible for setting up or resetting the game, capturing and validating
- the user's guess and providing feedback to the user with a <literal>FacesMessage</literal>. We've used the
- post-construct lifecycle method to initialize the game by retrieving a random number from the <literal>@Random
- Instance<Integer></literal> bean.
- </para>
-
- <para>
- You'll notice that we've also added the <literal>@Named</literal> annotation to this class. This annotation is
- only required when you want to make the bean accessible to a JSF view via EL (i.e., #{game}).
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Named
-@SessionScoped
-public class Game implements Serializable {
-
- private int number;
- private int guess;
- private int smallest;
- private int biggest;
- private int remainingGuesses;
-
- @Inject @MaxNumber private int maxNumber;
- @Inject @Random Instance<Integer> randomNumber;
-
- public Game() {}
-
- public void check() {
- if (guess > number) {
- biggest = guess - 1;
- }
- else if (guess < number) {
- smallest = guess + 1;
- }
- else if (guess == number) {
- FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
- }
- remainingGuesses--;
- }
-
- @PostConstruct
- public void reset() {
- this.smallest = 0;
- this.guess = 0;
- this.remainingGuesses = 10;
- this.biggest = maxNumber;
- this.number = randomNumber.get();
- }
-
- public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) {
- if (remainingGuesses <= 0) {
- FacesMessage message = new FacesMessage("No guesses left!");
- context.addMessage(toValidate.getClientId(context), message);
- ((UIInput) toValidate).setValid(false);
- return;
- }
- int input = (Integer) value;
-
- if (input < smallest || input > biggest) {
- ((UIInput) toValidate).setValid(false);
-
- FacesMessage message = new FacesMessage("Invalid guess");
- context.addMessage(toValidate.getClientId(context), message);
- }
- }
-
- public int getNumber() {
- return number;
- }
-
- public int getGuess() {
- return guess;
- }
-
- public void setGuess(int guess) {
- this.guess = guess;
- }
-
- public int getSmallest() {
- return smallest;
- }
-
- public int getBiggest() {
- return biggest;
- }
-
- public int getRemainingGuesses() {
- return remainingGuesses;
- }
-
-}]]></programlisting>
-
- <section id="numberguess-servlet">
- <title>The numberguess example in Apache Tomcat or Jetty</title>
-
- <para>
- A couple of modifications must be made to the numberguess artifact in order to deploy it to Tomcat or Jetty.
- First, Weld must be deployed as a Web Application library under <literal>WEB-INF/lib</literal> since the
- servlet container does not provide the CDI services. For your convenience we provide a single JAR suitable
- for running Weld in any servlet container (including Jetty), <literal>weld-servlet.jar</literal>.
- </para>
-
- <tip>
- <para>
- You must also include the JARs for JSF, EL, and the common annotations
- (<literal>jsr250-api.jar</literal>), all of which are provided by the Java EE platform (a Java EE
- application server). Are you starting to appreciate why a Java EE platform is worth using?
- </para>
- </tip>
-
- <para>
- Second, we need to explicitly specify the servlet listener in <literal>web.xml</literal>, again because the
- container isn't doing this stuff for you. The servlet listener boots Weld and controls it's interaction with
- requests.
- </para>
-
- <programlisting role="XML"><![CDATA[<listener>
- <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
-</listener>]]></programlisting>
-
- <para>
- When Weld boots, it places the <literal>javax.enterprise.inject.spi.BeanManager</literal>, the portable SPI
- for obtaining bean instances, in the ServletContext under a variable name equal to the fully-qualified
- interface name. You generally don't need to access this interface, but Weld makes use of it.
- </para>
-
- </section>
-
- <section id="numberguess-wicket">
- <title>The numberguess example for Apache Wicket</title>
- <para>
- Weld includes a number of portable extensions for JSR-299, including an extension for Wicket, which allows
- you to inject beans into Wicket components and leverage the conversation context. In this section, we'll
- walk you through the Wicket version of the numberguess example.
- </para>
-
- <tip>
- <para>
- You may want to review the Wicket documentation at <ulink
- url="http://wicket.apache.org/">http://wicket.apache.org/</ulink> before reading this section, if you
- aren't already familiar with the framework.
- </para>
- </tip>
-
- <para>
- Wicket is another environment that relies on the Weld servlet extension. The use of <ulink
- url="http://jetty.mortbay.org">Jetty</ulink> is common in the Wicket community, and is thus chosen here as
- the runtime container. You've seen already that Jetty is perfectly capable of running CDI applications with
- Weld add-ons, and this environment is no different.
- </para>
-
- <note>
- <para>
- We'll also be using the Eclipse IDE in these examples. Instructions are provided later for running the
- example from the command line, but since you'll likely need to do more than just deploy examples, we'll get
- setup in this full development environment.
- </para>
- </note>
-
- <section>
- <title>Creating the Eclipse project</title>
-
- <para>
- To use the Wicket example in Eclipse, you have one of two choices. You can either use a Maven plugin to
- generate a regular Eclipse Web project, or you can open the example natively using the <ulink
- src="http://m2eclipse.sonatype.org/">m2eclipse plugin</ulink>. Since the Weld source code relies so
- heavily on Maven, we encourage you to bite the bullet and adopt the m2eclipse plugin. Both approaches are
- described here for your convenience..
- </para>
-
- <para>
- If you have m2eclipse installed, you can open any Maven project directly. From within Eclipse, select
- <emphasis>File -> Import... -> Maven Projects</emphasis>. Then, browse to the location of the Wicket
- numberguess example. You should see that Eclipse recognizes the existence of a Maven project.
- </para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/m2eclipse-wicket-numberguess-import.png" format="PNG"/>
- </imageobject>
- </mediaobject>
-
- <para>
- This will create a project in your workspace called <literal>weld-wicket-numberguess</literal>.
- </para>
-
- <para>
- You'll notice after importing, the project has a build error. That's because we need to enable a Maven
- profile. Right-click on the project and select <emphasis>Properties</emphasis>, then select the
- <emphasis>Maven</emphasis> tab in the window that appears. In the form field labeled "Active Maven
- Profiles (comma separated):", type <literal>jetty</literal>. That will enable some extra dependencies
- that allow the project to compile. You're now ready to develop!
- </para>
-
- <note>
- <para>
- You are also advised to uncheck the box "Skip Maven compiler when processing resources" in the Maven
- properties screen because of conflicts with the Maven enforcer plugin.
- </para>
- </note>
-
- <para>
- If you are not using the m2eclipse plugin, you have to follow different steps to import the project.
- First, switch into the Wicket numberguess example, then execute the Maven Eclipse plugin with the jetty
- profile activated, as follows:
- </para>
-
- <programlisting><![CDATA[$> cd examples/wicket/numberguess
-mvn -Pjetty eclipse:eclipse]]></programlisting>
-
- <para>
- Then, from Eclipse, choose <emphasis>File -> Import... -> General -> Existing Projects into
- Workspace</emphasis>, select the root directory of the numberguess example, and click Finish. This will
- create a project in your workspace called <literal>weld-wicket-numberguess</literal>.
- </para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/wicket-numberguess-project.png" format="PNG"/>
- </imageobject>
- </mediaobject>
-
- <para>
- It's time to get the example running!
- </para>
-
- </section>
-
- <section>
- <title>Running the example from Eclipse</title>
-
- <para>
- This project follows the <literal>wicket-quickstart</literal> approach of creating an instance of Jetty
- in the <literal>Start</literal> class. So running the example is as simple as right-clicking on that
- Start class in <literal>src/test/java</literal> in the <emphasis>Package Explorer</emphasis> and choosing
- <emphasis>Run as Java Application</emphasis>. You should see console output related to Jetty starting up;
- then visit able <literal>http://localhost:9090</literal> to view the app. To debug choose <emphasis>Debug
- as Java Application</emphasis> instead.
- </para>
- </section>
-
- <section>
- <title>Running the example from the command line in JBoss AS or Tomcat</title>
-
- <para>
- This example can also be deployed from the command line in a (similar to the other examples). Assuming
- you have set up the <literal>local.build.properties</literal> file in the <literal>examples</literal>
- directory to specify the location of JBoss AS or Tomcat, as previously described, you can run:
- </para>
-
- <programlisting><![CDATA[$> ant deploy]]></programlisting>
-
- <para>to deploy the example to JBoss AS, and:</para>
-
- <programlisting><![CDATA[$> ant tomcat.deploy]]></programlisting>
-
- <para>
- to deploy the example to Tomcat. You can then access application at
- <literal>http://localhost:9090/weld-numberguess-wicket</literal>.
- </para>
-
- <para>
- Alternatively, you can run the application in place on an embedded Jetty container using the following
- Maven command:
- </para>
-
- <programlisting><![CDATA[$> mvn jetty:run -Pjetty]]></programlisting>
-
- <para>
- Enough toying with deployment, let's dive into the code.
- </para>
-
- </section>
-
- <section>
- <title>Understanding the code</title>
-
- <para>
- The code in the wicket numberguess example is very similar to the JSF-based numberguess example. The
- business layer is identical! Where things differ is in view binding. JSF uses Unified EL expressions to
- bind XML-based view layer components in JSF views to beans. In contrast, Wicket defines its components in
- Java. These Java-based view components have a one-to-one mapping with HTML elements in an adjacent (pure)
- HTML file. All view logic, including binding of components to models and controlling the response of view
- actions, is handled in Java.
- </para>
-
- <para>
- The integration of Weld with Wicket takes advantage of the same qualifier annotations used in your
- business layer to provide injection into your <literal>WebPage</literal> subclass (or into other custom
- Wicket component subclasses).
- </para>
-
- <para>
- Here's where things differ from the JSF numberguess example:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- Each wicket application must have a <literal>WeldApplication</literal> subclass. In our case, our
- application class is <literal>NumberGuessApplication</literal>:
- </para>
- <programlisting role="JAVA"><![CDATA[public class NumberGuessApplication extends WeldApplication {
- @Override public Class getHomePage() {
- return HomePage.class;
- }
-}]]></programlisting>
- <para>
- This class specifies which page Wicket should treat as our home page, in our case,
- <literal>HomePage.class</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- In <literal>HomePage</literal>, we see typical Wicket code to set up page elements. The bit that is
- interesting is the injection of the <literal>Game</literal> bean:
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Inject Game game;]]></programlisting>
-
- <para>
- The <literal>Game</literal> bean is can then be used, for example, by the code for submitting a
- guess:
- </para>
-
- <programlisting role="JAVA"><![CDATA[final Component guessButton = new AjaxButton("GuessButton") {
- protected void onSubmit(AjaxRequestTarget target, Form form) {
- if (game.check()) {
- info("Correct!");
- setVisible(false);
- prompt.setVisible(false);
- guessLabel.setVisible(false);
- inputGuess.setVisible(false);
- }
- else if (game.getRemainingGuesses() == 0) {
- info("Sorry, the answer was " + game.getNumber());
- setVisible(false);
- guessLabel.setVisible(false);
- inputGuess.setVisible(false);
- }
- else if (game.getNumber() > game.getGuess()) {
- info("Higher!");
- }
- else if (game.getNumber() < game.getGuess()) {
- info("Lower");
- }
- target.addComponent(form);
- }
-}; ]]></programlisting>
-
- <note>
- <para>
- All injections may be serialized; actual storage of the bean is managed by JSR-299. Note that
- Wicket components, like the <literal>HomePage</literal> and it subcomponents, are
- <emphasis>not</emphasis> JSR-299 beans.
- </para>
- <para>
- Wicket components allow injection, but they <emphasis>cannot</emphasis> use interceptors,
- decorators or lifecycle callbacks such as <literal>@PostConstruct</literal> or methods. The
- components would need to delegate to actual beans to leverage these features.
- </para>
- </note>
- </listitem>
- <listitem>
- <para>
- The example uses AJAX for processing of button events, and dynamically hides buttons that are no
- longer relevant, for example when the user has won the game.
- </para>
- </listitem>
-
- <listitem>
- <para>
- In order to activate Wicket for this webapp, the Wicket filter is added to <literal>web.xml</literal>,
- and our application class is specified in <literal>web.xml</literal>:
- </para>
-
- <programlisting role="XML"><![CDATA[<filter>
- <filter-name>Wicket Filter</filter-name>
- <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
- <init-param>
- <param-name>applicationClassName</param-name>
- <param-value>org.jboss.weld.examples.wicket.NumberGuessApplication</param-value>
- </init-param>
-</filter>
-
-<filter-mapping>
- <filter-name>Wicket Filter</filter-name>
- <url-pattern>/*</url-pattern>
-</filter-mapping>]]></programlisting>
-
- <para>
- The servlet listener is still required, as in the Tomcat example, to bootstrap CDI when Jetty
- starts and to hook CDI into the Jetty servlet request and session lifecycles. However, rather than
- putting it into the web.xml, it is placed into an override file,
- <literal>src/main/webapp/WEB-INF/jetty-additions-to-web.xml</literal>, that is passed to Jetty as
- an extra descriptor to be appended to the <literal>web.xml</literal> configuration.
- </para>
-
- <programlisting role="XML"><![CDATA[<web-app version="2.4" ...>
- <listener>
- <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
- </listener>
-</web-app>]]></programlisting>
-
- </listitem>
-
- </itemizedlist>
- </section>
- </section>
-
- <section id="numberguess-se">
- <title>The numberguess example for Java SE with Swing</title>
-
- <para>
- This example shows how to use the Weld SE extension to in a
- Java SE based Swing application with no EJB or servlet dependencies.
- This example can be found in the <literal>examples/se/numberguess</literal>
- folder of the Weld distribution.
- </para>
-
- <para>
- To run the example:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- Ensure that Maven 2 (version 2.0.10+) is installed and in your PATH
- </para>
- </listitem>
- <listitem>
- <para>
- Ensure that the <literal>JAVA_HOME</literal> environment
- variable is pointing to your JDK installation
- </para>
- </listitem>
- <listitem>
- <para>
- Open a command line or terminal window in the
- <literal>examples/se/numberguess</literal> directory
- </para>
- </listitem>
- <listitem>
- <para>
- Execute the following command
- </para>
- <programlisting>mvn -Drun</programlisting>
- </listitem>
- </itemizedlist>
-
- <para>
- Let's have a look at the significant code and configuration
- files that make up this example.
- </para>
-
- <para>
- As usual, there is an empty <literal>beans.xml</literal> file in the root
- package (<literal>src/main/resources/beans.xml</literal>), which
- marks this application as a CDI application.
- </para>
-
- <para>
- The game's main logic is located in <literal>Game.java</literal>.
- Here is the code for that class, highlighting the ways in which this
- differs from the web application version:
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="scope" coords="1" />
- <area id="name" coords="2" />
- <area id="messages1" coords="26" />
- <area id="validation" coords="41" />
- <area id="reset" coords="73" />
- </areaspec>
- <programlisting role="JAVA"><![CDATA[@ApplicationScoped
-public class Game implements Serializable
-{
-
- public static final int MAX_NUM_GUESSES = 10;
-
- private Integer number;
- private int guess = 0;
- private int smallest = 0;
-
- @Inject
- @MaxNumber
- private int maxNumber;
-
- private int biggest;
- private int remainingGuesses = MAX_NUM_GUESSES;
- private boolean validNumberRange = true;
-
- @Inject
- Generator rndGenerator;
-
- public Game()
- {
- }
-
- ...
-
- public boolean isValidNumberRange()
- {
- return validNumberRange;
- }
-
- public boolean isGameWon()
- {
- return guess == number;
- }
-
- public boolean isGameLost()
- {
- return guess != number && remainingGuesses <= 0;
- }
-
- public boolean check()
- {
- boolean result = false;
-
- if (checkNewNumberRangeIsValid())
- {
- if (guess > number)
- {
- biggest = guess - 1;
- }
-
- if (guess < number)
- {
- smallest = guess + 1;
- }
-
- if (guess == number)
- {
- result = true;
- }
-
- remainingGuesses--;
- }
-
- return result;
- }
-
- private boolean checkNewNumberRangeIsValid()
- {
- return validNumberRange = ((guess >= smallest) && (guess <= biggest));
- }
-
- @PostConstruct
- public void reset()
- {
- this.smallest = 0;
- this.guess = 0;
- this.remainingGuesses = 10;
- this.biggest = maxNumber;
- this.number = rndGenerator.next();
- }
-}]]></programlisting>
- <calloutlist>
- <callout arearefs="scope">
- <para>
- The bean is application scoped rather than session scoped,
- since an instance of a Swing application typically represents
- a single 'session'.
- </para>
- </callout>
- <callout arearefs="name">
- <para>
- Notice that the bean is not named, since it doesn't need to
- be accessed via EL.
- </para>
- </callout>
- <callout arearefs="messages1">
- <para>
- In Java SE there is no JSF <literal>FacesContext</literal>
- to which messages can be added. Instead the <literal>Game</literal>
- class provides additional information about the state of the
- current game including:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- If the game has been won or lost
- </para>
- </listitem>
- <listitem>
- <para>
- If the most recent guess was invalid
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- This allows the Swing UI to query the state of the game,
- which it does indirectly via a class called
- <literal>MessageGenerator</literal>, in order to determine
- the appropriate messages to display to the user during the
- game.
- </para>
- </callout>
- <callout arearefs="validation">
- <para>
- Since there is no dedicated validation phase, validation of
- user input is performed during the <literal>check()</literal> method.
- </para>
- </callout>
- <callout arearefs="reset">
- <para>
- The <literal>reset()</literal> method makes a call to the
- injected <literal>rndGenerator</literal> in order to get
- the random number at the start of each game. Note that it
- cannot use <literal>manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random>(){})</literal>
- as the JSF example does because there will not be any active
- contexts like there is during a JSF request.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- The <literal>MessageGenerator</literal> class depends on the
- current instance of <literal>Game</literal> and queries its
- state in order to determine the appropriate messages to provide
- as the prompt for the user's next guess and the response to the
- previous guess. The code for <literal>MessageGenerator</literal>
- is as follows:
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="game" coords="3" />
- <area id="challenge" coords="6" />
- <area id="result" coords="17" />
- </areaspec>
- <programlisting role="JAVA"><![CDATA[public class MessageGenerator
-{
- @Inject
- private Game game;
-
- public String getChallengeMessage()
- {
- StringBuilder challengeMsg = new StringBuilder("I'm thinking of a number between ");
- challengeMsg.append(game.getSmallest());
- challengeMsg.append(" and ");
- challengeMsg.append(game.getBiggest());
- challengeMsg.append(". Can you guess what it is?");
-
- return challengeMsg.toString();
- }
-
- public String getResultMessage()
- {
- if (game.isGameWon())
- {
- return "You guessed it! The number was " + game.getNumber();
- }
- else if (game.isGameLost())
- {
- return "You are fail! The number was " + game.getNumber();
- }
- else if (!game.isValidNumberRange())
- {
- return "Invalid number range!";
- }
- else if (game.getRemainingGuesses() == Game.MAX_NUM_GUESSES)
- {
- return "What is your first guess?";
- }
- else
- {
- String direction = null;
-
- if (game.getGuess() < game.getNumber())
- {
- direction = "Higher";
- }
- else
- {
- direction = "Lower";
- }
-
- return direction + "! You have " + game.getRemainingGuesses() + " guesses left.";
- }
- }
-}]]></programlisting>
- <calloutlist>
- <callout arearefs="game">
- <para>
- The instance of <literal>Game</literal> for the application
- is injected here.
- </para>
- </callout>
- <callout arearefs="challenge">
- <para>
- The <literal>Game</literal>'s state is interrogated to
- determine the appropriate challenge message ...
- </para>
- </callout>
- <callout arearefs="result">
- <para>
- ... and again to determine whether to congratulate, console or
- encourage the user to continue.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- Finally we come to the <literal>NumberGuessFrame</literal> class
- which provides the Swing front end to our guessing game.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="gameIn" coords="3" />
- <area id="messagesIn" coords="6" />
- <area id="start" coords="9" />
- <area id="init" coords="21" />
- <area id="guess1" coords="38" />
- <area id="replay" coords="48" />
- </areaspec>
- <programlisting role="JAVA"><![CDATA[public class NumberGuessFrame extends javax.swing.JFrame
-{
- @Inject
- private Game game;
-
- @Inject
- private MessageGenerator msgGenerator;
-
- public void start(@Observes ContainerInitialized event)
- {
- java.awt.EventQueue.invokeLater(new Runnable()
- {
- public void run()
- {
- initComponents();
- setVisible(true);
- }
- });
- }
-
- private void initComponents()
- {
-
- buttonPanel = new javax.swing.JPanel();
- mainMsgPanel = new javax.swing.JPanel();
- mainLabel = new javax.swing.JLabel();
- messageLabel = new javax.swing.JLabel();
- guessText = new javax.swing.JTextField();
- ...
- mainLabel.setText(msgGenerator.getChallengeMessage());
- mainMsgPanel.add(mainLabel);
-
- messageLabel.setText(msgGenerator.getResultMessage());
- mainMsgPanel.add(messageLabel);
- ...
- }
-
- private void guessButtonActionPerformed( java.awt.event.ActionEvent evt )
- {
- int guess = Integer.parseInt(guessText.getText());
- game.setGuess( guess );
- game.check();
- refreshUI();
- }
-
- private void replayBtnActionPerformed(java.awt.event.ActionEvent evt)
- {
- game.reset();
- refreshUI();
- }
-
- private void refreshUI() {
- mainLabel.setText( msgGenerator.getChallengeMessage() );
- messageLabel.setText( msgGenerator.getResultMessage() );
- guessText.setText( "" );
- guessesLeftBar.setValue( game.getRemainingGuesses() );
- guessText.requestFocus();
- }
-
- // swing components
- private javax.swing.JPanel borderPanel;
- ...
- private javax.swing.JButton replayBtn;
-
-}]]></programlisting>
- <calloutlist>
- <callout arearefs="gameIn">
- <para>
- The injected instance of the game (logic and state).
- </para>
- </callout>
- <callout arearefs="messagesIn">
- <para>
- The injected message generator for UI messages.
- </para>
- </callout>
- <callout arearefs="start">
- <para>
- This application is started in the prescribed Weld SE way,
- by observing the <literal>ContainerInitialized</literal> event.
- </para>
- </callout>
- <callout arearefs="init">
- <para>
- This method initializes all of the Swing components. Note
- the use of the <literal>msgGenerator</literal> here.
- </para>
- </callout>
- <callout arearefs="guess1">
- <para>
- <literal>guessButtonActionPerformed</literal> is called
- when the 'Guess' button is clicked, and it does the
- following:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- Gets the guess entered by the user and sets it as the
- current guess in the <literal>Game</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- Calls <literal>game.check()</literal> to validate and
- perform one 'turn' of the game
- </para>
- </listitem>
- <listitem>
- <para>
- Calls <literal>refreshUI</literal>. If there were
- validation errors with the input, this will have been
- captured during <literal>game.check()</literal> and
- as such will be reflected in the messages returned by
- <literal>MessageGenerator</literal> and subsequently
- presented to the user. If there are no validation
- errors then the user will be told to guess again
- (higher or lower) or that the game has ended either
- in a win (correct guess) or a loss (ran out of
- guesses).
- </para>
- </listitem>
- </itemizedlist>
- </callout>
- <callout arearefs="replay">
- <para>
- <literal>replayBtnActionPerformed</literal> simply calls
- <literal>game.reset()</literal> to start a new game and
- refreshes the messages in the UI.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- </section>
- </section>
-
- <section id="translator">
- <title>The translator example in depth</title>
-
- <para>
- The translator example will take any sentences you enter, and translate them to Latin. (Well, not really, but
- the stub is there for you to implement, at least. Good luck!)
- </para>
-
- <para>
- The translator example is built as an EAR and contains EJBs. As a result, it's structure is more complex than
- the numberguess example.
- </para>
-
- <note>
- <para>
- Java EE 6, which bundles EJB 3.1, allows you to package EJBs in a WAR, which will make this structure much
- simpler! Still, there are other advantages of using an EAR.
- </para>
- </note>
-
- <para>
- First, let's take a look at the EAR aggregator, which is located in the example's <literal>ear</literal> directory. Maven
- automatically generates the <literal>application.xml</literal> for us from this plugin configuration:
- </para>
-
- <programlisting role="XML"><![CDATA[<plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-ear-plugin</artifactId>
- <configuration>
- <modules>
- <webModule>
- <groupId>org.jboss.weld.examples.jsf.translator</groupId>
- <artifactId>weld-jsf-translator-war</artifactId>
- <contextRoot>/weld-translator</contextRoot>
- </webModule>
- </modules>
- </configuration>
-</plugin>]]></programlisting>
-
- <para>
- This configuration overrides the web context path, resulting in this application URL: <ulink
- url="http://localhost:8080/weld-translator">http://localhost:8080/weld-translator</ulink>.
- </para>
-
- <tip>
- <para>
- If you weren't using Maven to generate these files, you would need
- <literal>META-INF/application.xml</literal>:
- </para>
-
- <programlisting role="XML"><![CDATA[<application version="5"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="
- http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/application_5.xsd">
-
- <display-name>weld-jsf-translator-ear</display-name>
- <description>The Weld JSF translator example (EAR)</description>
-
- <module>
- <web>
- <web-uri>weld-translator.war</web-uri>
- <context-root>/weld-translator</context-root>
- </web>
- </module>
- <module>
- <ejb>weld-translator.jar</ejb>
- </module>
-</application>]]></programlisting>
- </tip>
-
- <para>
- Next, lets look at the WAR, which is located in the example's <literal>war</literal> directory. Just as in the
- numberguess example, we have a <literal>faces-config.xml</literal> for JSF 2.0 and a <literal>web.xml</literal>
- (to activate JSF) under WEB-INF, both sourced from <literal>src/main/webapp/WEB-INF</literal>.
- </para>
-
- <para>
- More interesting is the JSF view used to translate text. Just as in the numberguess example we have a template,
- which surrounds the form (ommitted here for brevity):
- </para>
-
- <programlisting role="XML"><![CDATA[<h:form id="translator">
-
- <table>
- <tr align="center" style="font-weight: bold">
- <td>
- Your text
- </td>
- <td>
- Translation
- </td>
- </tr>
- <tr>
- <td>
- <h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80"/>
- </td>
- <td>
- <h:outputText value="#{translator.translatedText}"/>
- </td>
- </tr>
- </table>
- <div>
- <h:commandButton id="button" value="Translate" action="#{translator.translate}"/>
- </div>
-
-</h:form>]]></programlisting>
-
- <para>
- The user can enter some text in the left-hand textarea, and hit the translate button to see the result to the
- right.
- </para>
-
- <para>
- Finally, let's look at the EJB module, which is located in the example's <literal>ejb</literal> directory. In
- <literal>src/main/resources/META-INF</literal> there is just an empty <literal>beans.xml</literal>, used to
- mark the archive as containing beans.
- </para>
-
- <para>
- We've saved the most interesting bit to last, the code! The project has two simple beans,
- <literal>SentenceParser</literal> and <literal>TextTranslator</literal> and two session beans,
- <literal>TranslatorControllerBean</literal> and <literal>SentenceTranslator</literal>. You should be getting
- quite familiar with what a bean looks like by now, so we'll just highlight the most interesting bits here.
- </para>
-
- <para>
- Both <literal>SentenceParser</literal> and <literal>TextTranslator</literal> are dependent beans, and
- <literal>TextTranslator</literal> uses constructor injection:
- </para>
-
- <programlisting role="JAVA"><![CDATA[public class TextTranslator implements Serializable {
-
- private SentenceParser sentenceParser;
-
- @EJB private Translator translator;
-
- @Inject public TextTranslator(SentenceParser sentenceParser) {
- this.sentenceParser = sentenceParser;
- }
-
- public String translate(String text) {
- StringBuilder sb = new StringBuilder();
- for (String sentence: sentenceParser.parse(text)) {
- sb.append(translator.translate(sentence)).append(". ");
- }
- return sb.toString().trim();
- }
-
-}]]></programlisting>
-
- <para>
- <literal>TextTranslator</literal> uses the simple bean (really just a plain Java class!)
- <literal>SentenceParser</literal> to parse the sentence and then calls on the stateless bean with the local
- business interface <literal>Translator</literal> to perform the translation. That's where the magic happens.
- Of course, we couldn't develop a full translator, but it's convincing enough to anyone who doesn't understand
- Latin!
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Stateless
-public class SentenceTranslator implements Translator {
-
- public String translate(String sentence) {
- return "Lorem ipsum dolor sit amet";
- }
-
-}]]></programlisting>
-
- <para>
- Finally, there is UI orientated controller. This is a request scoped, named, stateful session bean, which
- injects the translator. It collects the text from the user and dispatches it to the translator. The bean also
- has getters and setters for all the fields on the page.
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Stateful
-@RequestScoped
-@Named("translator")
-public class TranslatorControllerBean implements TranslatorController {
-
- @Inject private TextTranslator translator;
-
- private String inputText;
-
- private String translatedText;
-
- public void translate() {
- translatedText = translator.translate(inputText);
- }
-
- public String getText() {
- return inputText;
- }
-
- public void setText(String text) {
- this.inputText = text;
- }
-
- public String getTranslatedText() {
- return translatedText;
- }
-
- @Remove public void remove() {}
-
-}]]></programlisting>
-
- </section>
-
- <para>
- That concludes our short tour of the Weld starter examples. For more information on Weld, or to help out with
- development, please visit <ulink
- url="http://www.seamframework.org/Weld/Development">http://www.seamframework.org/Weld/Development</ulink>.
- </para>
-
<!--
vim:et:ts=3:sw=3:tw=120
-->
Modified: doc/trunk/reference/en-US/intro.xml
===================================================================
--- doc/trunk/reference/en-US/intro.xml 2009-11-10 05:13:46 UTC (rev 4942)
+++ doc/trunk/reference/en-US/intro.xml 2009-11-10 05:59:22 UTC (rev 4943)
@@ -194,7 +194,7 @@
<para>
Notice that it isn't necessary to create a getter or setter method to inject one bean into another. CDI can
- access an injected field directly (even if it's private!), which sometimes help eliminate some wasteful code.
+ access an injected field directly (even if it's private!), which sometimes helps eliminate some wasteful code.
The name of the field is arbitrary. It's the field's type that determines what is injected.
</para>
Modified: doc/trunk/reference/en-US/master.xml
===================================================================
--- doc/trunk/reference/en-US/master.xml 2009-11-10 05:13:46 UTC (rev 4942)
+++ doc/trunk/reference/en-US/master.xml 2009-11-10 05:59:22 UTC (rev 4943)
@@ -39,13 +39,22 @@
<xi:include href="intro.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="example.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="gettingstarted.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="injection.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="scopescontexts.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="producermethods.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<!-- TODO <xi:include href="producerfields.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> -->
</part>
+
+ <part id="1.5">
+ <title>Weld, the CDI Reference Implementation</title>
+
+ <xi:include href="part1.5.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="gettingstarted.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="weldexamples.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ </part>
<part id="2">
<title>Developing loosely-coupled code</title>
Added: doc/trunk/reference/en-US/part1.5.xml
===================================================================
--- doc/trunk/reference/en-US/part1.5.xml (rev 0)
+++ doc/trunk/reference/en-US/part1.5.xml 2009-11-10 05:59:22 UTC (rev 4943)
@@ -0,0 +1,16 @@
+<!DOCTYPE partintro PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<partintro>
+
+ <para>
+ Weld, the JSR-299 Reference Implementation (RI), is being developed as part of the <ulink
+ url="http://seamframework.org/Weld">Seam project</ulink>. You can download the latest community release of Weld
+ from the <ulink url="http://seamframework.org/Download">download page</ulink>. Information about the Weld source
+ code repository and instructions about how to obtain and build the source can be found on the same page.
+ </para>
+
+ <para>
+ Weld comes with an extensive library of examples, which are a great starting point from which to learn CDI.
+ </para>
+
+</partintro>
\ No newline at end of file
Added: doc/trunk/reference/en-US/weldexamples.xml
===================================================================
--- doc/trunk/reference/en-US/weldexamples.xml (rev 0)
+++ doc/trunk/reference/en-US/weldexamples.xml 2009-11-10 05:59:22 UTC (rev 4943)
@@ -0,0 +1,1345 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<chapter id="weldexamples">
+
+ <title>Diving into the Weld examples</title>
+
+ <para>
+ It's time to pull the covers back and dive into the internals of Weld example applications. Let's start with the
+ simpler of the two examples, <literal>weld-numberguess</literal>.
+ </para>
+
+ <section id="numberguess">
+ <title>The numberguess example in depth</title>
+
+ <para>
+ In the numberguess application you get 10 attempts to guess a number between 1 and 100. After each
+ attempt, you're told whether your guess was too high or too low.
+ </para>
+
+ <para>
+ The numberguess example is comprised of a number of beans, configuration files and Facelets (JSF) views,
+ packaged as a WAR module. Let's start by examining the configuration files.
+ </para>
+
+ <para>
+ All the configuration files for this example are located in <literal>WEB-INF/</literal>, which can be found in
+ the <literal>src/main/webapp</literal> directory of the example. First, we have the JSF 2.0 version of
+ <literal>faces-config.xml</literal>. A standardized version of Facelets is the default view handler in JSF
+ 2.0, so there's really nothing that we have to configure. Thus, the configuration consists of only the root
+ element.
+ </para>
+
+ <programlisting role="XML"><![CDATA[<faces-config version="2.0"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
+</faces-config>]]></programlisting>
+
+ <para>
+ There's also an empty <literal>beans.xml</literal> file, which tells the container to look for beans in this
+ application and to activate the CDI services.
+ </para>
+
+ <para>
+ Finally, there's the familiar <literal>web.xml</literal>:
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="faces.servlet" coords="10" />
+ <area id="faces.servlet.mapping" coords="16" />
+ <area id="faces.default.suffix" coords="21" />
+ <area id="session.timeout" coords="26" />
+ </areaspec>
+ <programlisting role="XML"><![CDATA[<web-app version="2.5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <display-name>weld-jsf-numberguess-war</display-name>
+ <description>Weld JSF numberguess example (WAR)</description>
+
+ <servlet>
+ <servlet-name>Faces Servlet</servlet-name>
+ <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Faces Servlet</servlet-name>
+ <url-pattern>*.jsf</url-pattern>
+ </servlet-mapping>
+
+ <context-param>
+ <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
+ <param-value>.xhtml</param-value>
+ </context-param>
+
+ <session-config>
+ <session-timeout>10</session-timeout>
+ </session-config>
+
+</web-app>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="faces.servlet">
+ <para>
+ Enable and initialize the JSF servlet
+ </para>
+ </callout>
+ <callout arearefs="faces.servlet.mapping">
+ <para>
+ Configure requests for URLs ending in <literal>.jsf</literal> to be
+ handled by JSF
+ </para>
+ </callout>
+ <callout arearefs="faces.default.suffix">
+ <para>
+ Tell JSF that we will be giving our JSF views (Facelets templates) an
+ extension of <literal>.xhtml</literal>
+ </para>
+ </callout>
+ <callout arearefs="session.timeout">
+ <para>
+ Configure a session timeout of 10 minutes
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <note>
+ <para>
+ This demo uses JSF 2 as the view framework, but you can use Weld with any servlet-based web framework, such
+ as JSF 1.2 or Wicket.
+ </para>
+ </note>
+
+ <para>
+ Let's take a look at the main JSF view, <literal>src/main/webapp/home.xhtml</literal>.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="template" coords="8" />
+ <area id="statusMessages" coords="12" />
+ <area id="instructions" coords="20" />
+ <area id="guess" coords="27" />
+ <area id="validator" coords="29" />
+ <area id="submit" coords="30" />
+ </areaspec>
+ <programlisting role="HTML"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core">
+
+ <ui:composition template="/template.xhtml">
+ <ui:define name="content">
+ <h1>Guess a number...</h1>
+ <h:form id="numberGuess">
+ <div style="color: red">
+ <h:messages id="messages" globalOnly="false"/>
+ <h:outputText id="Higher" value="Higher!"
+ rendered="#{game.number gt game.guess and game.guess ne 0}"/>
+ <h:outputText id="Lower" value="Lower!"
+ rendered="#{game.number lt game.guess and game.guess ne 0}"/>
+ </div>
+
+ <div>
+ I'm thinking of a number between #{game.smallest} and #{game.biggest}.
+ You have #{game.remainingGuesses} guesses remaining.
+ </div>
+
+ <div>
+ Your guess:
+ <h:inputText id="inputGuess" value="#{game.guess}"
+ size="3" required="true" disabled="#{game.number eq game.guess}"
+ validator="#{game.validateNumberRange}"/>
+ <h:commandButton id="guessButton" value="Guess"
+ action="#{game.check}" disabled="#{game.number eq game.guess}"/>
+ </div>
+ <div>
+ <h:commandButton id="restartButton" value="Reset" action="#{game.reset}" immediate="true"/>
+ </div>
+ </h:form>
+ </ui:define>
+ </ui:composition>
+</html>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="template">
+ <para>
+ Facelets is the built-in templating language for JSF. Here we are
+ wrapping our page in a template which defines the layout.
+ </para>
+ </callout>
+ <callout arearefs="statusMessages">
+ <para>
+ There are a number of messages which can be sent to the user,
+ "Higher!", "Lower!" and "Correct!"
+ </para>
+ </callout>
+ <callout arearefs="instructions">
+ <para>
+ As the user guesses, the range of numbers they can guess gets
+ smaller - this sentence changes to make sure they know the
+ number range of a valid guess.
+ </para>
+ </callout>
+ <callout arearefs="guess">
+ <para>
+ This input field is bound to a bean property using a value
+ expression.
+ </para>
+ </callout>
+ <callout arearefs="validator">
+ <para>
+ A validator binding is used to make sure the user doesn't
+ accidentally input a number outside of the range in which they
+ can guess - if the validator wasn't here, the user might use
+ up a guess on an out of bounds number.
+ </para>
+ </callout>
+ <callout arearefs="submit">
+ <para>
+ And, of course, there must be a way for the user to send their
+ guess to the server. Here we bind to an action method on the bean.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ The example exists of 4 classes, the first two of which are qualifiers. First, there is the
+ <literal>@Random</literal> qualifier, used for injecting a random number:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Qualifier
+@Target( { TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+public @interface Random {}]]></programlisting>
+
+ <para>
+ There is also the <literal>@MaxNumber</literal> qualifier, used for
+ injecting the maximum number that can be injected:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Qualifier
+@Target( { TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+public @interface MaxNumber {}
+]]></programlisting>
+
+ <para>
+ The application-scoped <literal>Generator</literal> class is responsible for creating the random number, via a
+ producer method. It also exposes the maximum possible number via a producer method:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@ApplicationScoped
+public class Generator implements Serializable {
+
+ private java.util.Random random = new java.util.Random(System.currentTimeMillis());
+
+ private int maxNumber = 100;
+
+ java.util.Random getRandom() {
+ return random;
+ }
+
+ @Produces @Random int next() {
+ return getRandom().nextInt(maxNumber);
+ }
+
+ @Produces @MaxNumber int getMaxNumber() {
+ return maxNumber;
+ }
+
+}]]></programlisting>
+
+ <para>
+ The <literal>Generator</literal> is application scoped, so we don't get a different random each time.
+ </para>
+
+ <note>
+ <para>
+ The package declaration and imports have been excluded from these listings. The complete listing is
+ available in the example source code.
+ </para>
+ </note>
+
+ <para>
+ The final bean in the application is the session-scoped <literal>Game</literal> class. This is the primary
+ entry point of the application. It's responsible for setting up or resetting the game, capturing and validating
+ the user's guess and providing feedback to the user with a <literal>FacesMessage</literal>. We've used the
+ post-construct lifecycle method to initialize the game by retrieving a random number from the <literal>@Random
+ Instance<Integer></literal> bean.
+ </para>
+
+ <para>
+ You'll notice that we've also added the <literal>@Named</literal> annotation to this class. This annotation is
+ only required when you want to make the bean accessible to a JSF view via EL (i.e., #{game}).
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Named
+@SessionScoped
+public class Game implements Serializable {
+
+ private int number;
+ private int guess;
+ private int smallest;
+ private int biggest;
+ private int remainingGuesses;
+
+ @Inject @MaxNumber private int maxNumber;
+ @Inject @Random Instance<Integer> randomNumber;
+
+ public Game() {}
+
+ public void check() {
+ if (guess > number) {
+ biggest = guess - 1;
+ }
+ else if (guess < number) {
+ smallest = guess + 1;
+ }
+ else if (guess == number) {
+ FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
+ }
+ remainingGuesses--;
+ }
+
+ @PostConstruct
+ public void reset() {
+ this.smallest = 0;
+ this.guess = 0;
+ this.remainingGuesses = 10;
+ this.biggest = maxNumber;
+ this.number = randomNumber.get();
+ }
+
+ public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) {
+ if (remainingGuesses <= 0) {
+ FacesMessage message = new FacesMessage("No guesses left!");
+ context.addMessage(toValidate.getClientId(context), message);
+ ((UIInput) toValidate).setValid(false);
+ return;
+ }
+ int input = (Integer) value;
+
+ if (input < smallest || input > biggest) {
+ ((UIInput) toValidate).setValid(false);
+
+ FacesMessage message = new FacesMessage("Invalid guess");
+ context.addMessage(toValidate.getClientId(context), message);
+ }
+ }
+
+ public int getNumber() {
+ return number;
+ }
+
+ public int getGuess() {
+ return guess;
+ }
+
+ public void setGuess(int guess) {
+ this.guess = guess;
+ }
+
+ public int getSmallest() {
+ return smallest;
+ }
+
+ public int getBiggest() {
+ return biggest;
+ }
+
+ public int getRemainingGuesses() {
+ return remainingGuesses;
+ }
+
+}]]></programlisting>
+
+ <section id="numberguess-servlet">
+ <title>The numberguess example in Apache Tomcat or Jetty</title>
+
+ <para>
+ A couple of modifications must be made to the numberguess artifact in order to deploy it to Tomcat or Jetty.
+ First, Weld must be deployed as a Web Application library under <literal>WEB-INF/lib</literal> since the
+ servlet container does not provide the CDI services. For your convenience we provide a single JAR suitable
+ for running Weld in any servlet container (including Jetty), <literal>weld-servlet.jar</literal>.
+ </para>
+
+ <tip>
+ <para>
+ You must also include the JARs for JSF, EL, and the common annotations
+ (<literal>jsr250-api.jar</literal>), all of which are provided by the Java EE platform (a Java EE
+ application server). Are you starting to appreciate why a Java EE platform is worth using?
+ </para>
+ </tip>
+
+ <para>
+ Second, we need to explicitly specify the servlet listener in <literal>web.xml</literal>, again because the
+ container isn't doing this stuff for you. The servlet listener boots Weld and controls it's interaction with
+ requests.
+ </para>
+
+ <programlisting role="XML"><![CDATA[<listener>
+ <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
+</listener>]]></programlisting>
+
+ <para>
+ When Weld boots, it places the <literal>javax.enterprise.inject.spi.BeanManager</literal>, the portable SPI
+ for obtaining bean instances, in the ServletContext under a variable name equal to the fully-qualified
+ interface name. You generally don't need to access this interface, but Weld makes use of it.
+ </para>
+
+ </section>
+
+ <section id="numberguess-wicket">
+ <title>The numberguess example for Apache Wicket</title>
+ <para>
+ Weld includes a number of portable extensions for JSR-299, including an extension for Wicket, which allows
+ you to inject beans into Wicket components and leverage the conversation context. In this section, we'll
+ walk you through the Wicket version of the numberguess example.
+ </para>
+
+ <tip>
+ <para>
+ You may want to review the Wicket documentation at <ulink
+ url="http://wicket.apache.org/">http://wicket.apache.org/</ulink> before reading this section, if you
+ aren't already familiar with the framework.
+ </para>
+ </tip>
+
+ <para>
+ Wicket is another environment that relies on the Weld servlet extension. The use of <ulink
+ url="http://jetty.mortbay.org">Jetty</ulink> is common in the Wicket community, and is thus chosen here as
+ the runtime container. You've seen already that Jetty is perfectly capable of running CDI applications with
+ Weld add-ons, and this environment is no different.
+ </para>
+
+ <note>
+ <para>
+ We'll also be using the Eclipse IDE in these examples. Instructions are provided later for running the
+ example from the command line, but since you'll likely need to do more than just deploy examples, we'll get
+ setup in this full development environment.
+ </para>
+ </note>
+
+ <section>
+ <title>Creating the Eclipse project</title>
+
+ <para>
+ To use the Wicket example in Eclipse, you have one of two choices. You can either use a Maven plugin to
+ generate a regular Eclipse Web project, or you can open the example natively using the <ulink
+ src="http://m2eclipse.sonatype.org/">m2eclipse plugin</ulink>. Since the Weld source code relies so
+ heavily on Maven, we encourage you to bite the bullet and adopt the m2eclipse plugin. Both approaches are
+ described here for your convenience..
+ </para>
+
+ <para>
+ If you have m2eclipse installed, you can open any Maven project directly. From within Eclipse, select
+ <emphasis>File -> Import... -> Maven Projects</emphasis>. Then, browse to the location of the Wicket
+ numberguess example. You should see that Eclipse recognizes the existence of a Maven project.
+ </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/m2eclipse-wicket-numberguess-import.png" format="PNG"/>
+ </imageobject>
+ </mediaobject>
+
+ <para>
+ This will create a project in your workspace called <literal>weld-wicket-numberguess</literal>.
+ </para>
+
+ <para>
+ You'll notice after importing, the project has a build error. That's because we need to enable a Maven
+ profile. Right-click on the project and select <emphasis>Properties</emphasis>, then select the
+ <emphasis>Maven</emphasis> tab in the window that appears. In the form field labeled "Active Maven
+ Profiles (comma separated):", type <literal>jetty</literal>. That will enable some extra dependencies
+ that allow the project to compile. You're now ready to develop!
+ </para>
+
+ <para>
+ If you are not using the m2eclipse plugin, you have to follow different steps to import the project.
+ First, switch into the Wicket numberguess example, then execute the Maven Eclipse plugin with the jetty
+ profile activated, as follows:
+ </para>
+
+ <programlisting><![CDATA[$> cd examples/wicket/numberguess
+mvn -Pjetty eclipse:eclipse]]></programlisting>
+
+ <para>
+ Then, from Eclipse, choose <emphasis>File -> Import... -> General -> Existing Projects into
+ Workspace</emphasis>, select the root directory of the numberguess example, and click Finish. This will
+ create a project in your workspace called <literal>weld-wicket-numberguess</literal>.
+ </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/wicket-numberguess-project.png" format="PNG"/>
+ </imageobject>
+ </mediaobject>
+
+ <para>
+ It's time to get the example running!
+ </para>
+
+ </section>
+
+ <section>
+ <title>Running the example from Eclipse</title>
+
+ <para>
+ This project follows the <literal>wicket-quickstart</literal> approach of creating an instance of Jetty
+ in the <literal>Start</literal> class. So running the example is as simple as right-clicking on that
+ Start class in <literal>src/test/java</literal> in the <emphasis>Package Explorer</emphasis> and choosing
+ <emphasis>Run as Java Application</emphasis>. You should see console output related to Jetty starting up;
+ then visit able <literal>http://localhost:8080</literal> to view the app. To debug choose <emphasis>Debug
+ as Java Application</emphasis> instead.
+ </para>
+ </section>
+
+ <section>
+ <title>Running the example from the command line in JBoss AS or Tomcat</title>
+
+ <para>
+ This example can also be deployed from the command line in a (similar to the other examples). Assuming
+ you have set up the <literal>local.build.properties</literal> file in the <literal>examples</literal>
+ directory to specify the location of JBoss AS or Tomcat, as previously described, you can run:
+ </para>
+
+ <programlisting><![CDATA[$> ant deploy]]></programlisting>
+
+ <para>to deploy the example to JBoss AS, and:</para>
+
+ <programlisting><![CDATA[$> ant tomcat.deploy]]></programlisting>
+
+ <para>
+ to deploy the example to Tomcat. You can then access application at
+ <literal>http://localhost:8080/weld-numberguess-wicket</literal>.
+ </para>
+
+ <para>
+ Alternatively, you can run the application in place on an embedded Jetty container using the following
+ Maven command:
+ </para>
+
+ <programlisting><![CDATA[$> mvn jetty:run -Pjetty]]></programlisting>
+
+ <para>
+ Enough toying with deployment, let's dive into the code.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Understanding the code</title>
+
+ <para>
+ The code in the wicket numberguess example is very similar to the JSF-based numberguess example. The
+ business layer is identical! Where things differ is in view binding. JSF uses Unified EL expressions to
+ bind XML-based view layer components in JSF views to beans. In contrast, Wicket defines its components in
+ Java. These Java-based view components have a one-to-one mapping with HTML elements in an adjacent (pure)
+ HTML file. All view logic, including binding of components to models and controlling the response of view
+ actions, is handled in Java.
+ </para>
+
+ <para>
+ The integration of Weld with Wicket takes advantage of the same qualifier annotations used in your
+ business layer to provide injection into your <literal>WebPage</literal> subclass (or into other custom
+ Wicket component subclasses).
+ </para>
+
+ <para>
+ Here's where things differ from the JSF numberguess example:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Each wicket application must have a <literal>WeldApplication</literal> subclass. In our case, our
+ application class is <literal>NumberGuessApplication</literal>:
+ </para>
+ <programlisting role="JAVA"><![CDATA[public class NumberGuessApplication extends WeldApplication {
+ @Override public Class getHomePage() {
+ return HomePage.class;
+ }
+}]]></programlisting>
+ <para>
+ This class specifies which page Wicket should treat as our home page, in our case,
+ <literal>HomePage.class</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ In <literal>HomePage</literal>, we see typical Wicket code to set up page elements. The bit that is
+ interesting is the injection of the <literal>Game</literal> bean:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Inject Game game;]]></programlisting>
+
+ <para>
+ The <literal>Game</literal> bean is can then be used, for example, by the code for submitting a
+ guess:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[final Component guessButton = new AjaxButton("GuessButton") {
+ protected void onSubmit(AjaxRequestTarget target, Form form) {
+ if (game.check()) {
+ info("Correct!");
+ setVisible(false);
+ prompt.setVisible(false);
+ guessLabel.setVisible(false);
+ inputGuess.setVisible(false);
+ }
+ else if (game.getRemainingGuesses() == 0) {
+ info("Sorry, the answer was " + game.getNumber());
+ setVisible(false);
+ guessLabel.setVisible(false);
+ inputGuess.setVisible(false);
+ }
+ else if (game.getNumber() > game.getGuess()) {
+ info("Higher!");
+ }
+ else if (game.getNumber() < game.getGuess()) {
+ info("Lower");
+ }
+ target.addComponent(form);
+ }
+}; ]]></programlisting>
+
+ <note>
+ <para>
+ All injections may be serialized; actual storage of the bean is managed by JSR-299. Note that
+ Wicket components, like the <literal>HomePage</literal> and it subcomponents, are
+ <emphasis>not</emphasis> JSR-299 beans.
+ </para>
+ <para>
+ Wicket components allow injection, but they <emphasis>cannot</emphasis> use interceptors,
+ decorators or lifecycle callbacks such as <literal>@PostConstruct</literal> or methods. The
+ components would need to delegate to actual beans to leverage these features.
+ </para>
+ </note>
+ </listitem>
+ <listitem>
+ <para>
+ The example uses AJAX for processing of button events, and dynamically hides buttons that are no
+ longer relevant, for example when the user has won the game.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ In order to activate Wicket for this webapp, the Wicket filter is added to <literal>web.xml</literal>,
+ and our application class is specified in <literal>web.xml</literal>:
+ </para>
+
+ <programlisting role="XML"><![CDATA[<filter>
+ <filter-name>Wicket Filter</filter-name>
+ <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
+ <init-param>
+ <param-name>applicationClassName</param-name>
+ <param-value>org.jboss.weld.examples.wicket.NumberGuessApplication</param-value>
+ </init-param>
+</filter>
+
+<filter-mapping>
+ <filter-name>Wicket Filter</filter-name>
+ <url-pattern>/*</url-pattern>
+</filter-mapping>]]></programlisting>
+
+ <para>
+ The servlet listener is still required, as in the Tomcat example, to bootstrap CDI when Jetty
+ starts and to hook CDI into the Jetty servlet request and session lifecycles. However, rather than
+ putting it into the web.xml, it is placed into an override file,
+ <literal>src/main/webapp/WEB-INF/jetty-additions-to-web.xml</literal>, that is passed to Jetty as
+ an extra descriptor to be appended to the <literal>web.xml</literal> configuration.
+ </para>
+
+ <programlisting role="XML"><![CDATA[<web-app version="2.4" ...>
+ <listener>
+ <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
+ </listener>
+</web-app>]]></programlisting>
+
+ </listitem>
+
+ </itemizedlist>
+ </section>
+ </section>
+
+ <section id="numberguess-se">
+ <title>The numberguess example for Java SE with Swing</title>
+
+ <para>
+ This example shows how to use the Weld SE extension to in a
+ Java SE based Swing application with no EJB or servlet dependencies.
+ This example can be found in the <literal>examples/se/numberguess</literal>
+ folder of the Weld distribution.
+ </para>
+
+ <para>
+ To run the example:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Ensure that Maven 2 (version 2.0.10+) is installed and in your PATH
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Ensure that the <literal>JAVA_HOME</literal> environment
+ variable is pointing to your JDK installation
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Open a command line or terminal window in the
+ <literal>examples/se/numberguess</literal> directory
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Execute the following command
+ </para>
+ <programlisting>mvn -Drun</programlisting>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Let's have a look at the significant code and configuration
+ files that make up this example.
+ </para>
+
+ <para>
+ As usual, there is an empty <literal>beans.xml</literal> file in the root
+ package (<literal>src/main/resources/beans.xml</literal>), which
+ marks this application as a CDI application.
+ </para>
+
+ <para>
+ The game's main logic is located in <literal>Game.java</literal>.
+ Here is the code for that class, highlighting the ways in which this
+ differs from the web application version:
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="scope" coords="1" />
+ <area id="name" coords="2" />
+ <area id="messages1" coords="26" />
+ <area id="validation" coords="41" />
+ <area id="reset" coords="73" />
+ </areaspec>
+ <programlisting role="JAVA"><![CDATA[@ApplicationScoped
+public class Game implements Serializable
+{
+
+ public static final int MAX_NUM_GUESSES = 10;
+
+ private Integer number;
+ private int guess = 0;
+ private int smallest = 0;
+
+ @Inject
+ @MaxNumber
+ private int maxNumber;
+
+ private int biggest;
+ private int remainingGuesses = MAX_NUM_GUESSES;
+ private boolean validNumberRange = true;
+
+ @Inject
+ Generator rndGenerator;
+
+ public Game()
+ {
+ }
+
+ ...
+
+ public boolean isValidNumberRange()
+ {
+ return validNumberRange;
+ }
+
+ public boolean isGameWon()
+ {
+ return guess == number;
+ }
+
+ public boolean isGameLost()
+ {
+ return guess != number && remainingGuesses <= 0;
+ }
+
+ public boolean check()
+ {
+ boolean result = false;
+
+ if (checkNewNumberRangeIsValid())
+ {
+ if (guess > number)
+ {
+ biggest = guess - 1;
+ }
+
+ if (guess < number)
+ {
+ smallest = guess + 1;
+ }
+
+ if (guess == number)
+ {
+ result = true;
+ }
+
+ remainingGuesses--;
+ }
+
+ return result;
+ }
+
+ private boolean checkNewNumberRangeIsValid()
+ {
+ return validNumberRange = ((guess >= smallest) && (guess <= biggest));
+ }
+
+ @PostConstruct
+ public void reset()
+ {
+ this.smallest = 0;
+ this.guess = 0;
+ this.remainingGuesses = 10;
+ this.biggest = maxNumber;
+ this.number = rndGenerator.next();
+ }
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="scope">
+ <para>
+ The bean is application scoped rather than session scoped,
+ since an instance of a Swing application typically represents
+ a single 'session'.
+ </para>
+ </callout>
+ <callout arearefs="name">
+ <para>
+ Notice that the bean is not named, since it doesn't need to
+ be accessed via EL.
+ </para>
+ </callout>
+ <callout arearefs="messages1">
+ <para>
+ In Java SE there is no JSF <literal>FacesContext</literal>
+ to which messages can be added. Instead the <literal>Game</literal>
+ class provides additional information about the state of the
+ current game including:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ If the game has been won or lost
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the most recent guess was invalid
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ This allows the Swing UI to query the state of the game,
+ which it does indirectly via a class called
+ <literal>MessageGenerator</literal>, in order to determine
+ the appropriate messages to display to the user during the
+ game.
+ </para>
+ </callout>
+ <callout arearefs="validation">
+ <para>
+ Since there is no dedicated validation phase, validation of
+ user input is performed during the <literal>check()</literal> method.
+ </para>
+ </callout>
+ <callout arearefs="reset">
+ <para>
+ The <literal>reset()</literal> method makes a call to the
+ injected <literal>rndGenerator</literal> in order to get
+ the random number at the start of each game. Note that it
+ cannot use <literal>manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random>(){})</literal>
+ as the JSF example does because there will not be any active
+ contexts like there is during a JSF request.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ The <literal>MessageGenerator</literal> class depends on the
+ current instance of <literal>Game</literal> and queries its
+ state in order to determine the appropriate messages to provide
+ as the prompt for the user's next guess and the response to the
+ previous guess. The code for <literal>MessageGenerator</literal>
+ is as follows:
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="game" coords="3" />
+ <area id="challenge" coords="6" />
+ <area id="result" coords="17" />
+ </areaspec>
+ <programlisting role="JAVA"><![CDATA[public class MessageGenerator
+{
+ @Inject
+ private Game game;
+
+ public String getChallengeMessage()
+ {
+ StringBuilder challengeMsg = new StringBuilder("I'm thinking of a number between ");
+ challengeMsg.append(game.getSmallest());
+ challengeMsg.append(" and ");
+ challengeMsg.append(game.getBiggest());
+ challengeMsg.append(". Can you guess what it is?");
+
+ return challengeMsg.toString();
+ }
+
+ public String getResultMessage()
+ {
+ if (game.isGameWon())
+ {
+ return "You guessed it! The number was " + game.getNumber();
+ }
+ else if (game.isGameLost())
+ {
+ return "You are fail! The number was " + game.getNumber();
+ }
+ else if (!game.isValidNumberRange())
+ {
+ return "Invalid number range!";
+ }
+ else if (game.getRemainingGuesses() == Game.MAX_NUM_GUESSES)
+ {
+ return "What is your first guess?";
+ }
+ else
+ {
+ String direction = null;
+
+ if (game.getGuess() < game.getNumber())
+ {
+ direction = "Higher";
+ }
+ else
+ {
+ direction = "Lower";
+ }
+
+ return direction + "! You have " + game.getRemainingGuesses() + " guesses left.";
+ }
+ }
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="game">
+ <para>
+ The instance of <literal>Game</literal> for the application
+ is injected here.
+ </para>
+ </callout>
+ <callout arearefs="challenge">
+ <para>
+ The <literal>Game</literal>'s state is interrogated to
+ determine the appropriate challenge message ...
+ </para>
+ </callout>
+ <callout arearefs="result">
+ <para>
+ ... and again to determine whether to congratulate, console or
+ encourage the user to continue.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Finally we come to the <literal>NumberGuessFrame</literal> class
+ which provides the Swing front end to our guessing game.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="gameIn" coords="3" />
+ <area id="messagesIn" coords="6" />
+ <area id="start" coords="9" />
+ <area id="init" coords="21" />
+ <area id="guess1" coords="38" />
+ <area id="replay" coords="48" />
+ </areaspec>
+ <programlisting role="JAVA"><![CDATA[public class NumberGuessFrame extends javax.swing.JFrame
+{
+ @Inject
+ private Game game;
+
+ @Inject
+ private MessageGenerator msgGenerator;
+
+ public void start(@Observes ContainerInitialized event)
+ {
+ java.awt.EventQueue.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ initComponents();
+ setVisible(true);
+ }
+ });
+ }
+
+ private void initComponents()
+ {
+
+ buttonPanel = new javax.swing.JPanel();
+ mainMsgPanel = new javax.swing.JPanel();
+ mainLabel = new javax.swing.JLabel();
+ messageLabel = new javax.swing.JLabel();
+ guessText = new javax.swing.JTextField();
+ ...
+ mainLabel.setText(msgGenerator.getChallengeMessage());
+ mainMsgPanel.add(mainLabel);
+
+ messageLabel.setText(msgGenerator.getResultMessage());
+ mainMsgPanel.add(messageLabel);
+ ...
+ }
+
+ private void guessButtonActionPerformed( java.awt.event.ActionEvent evt )
+ {
+ int guess = Integer.parseInt(guessText.getText());
+ game.setGuess( guess );
+ game.check();
+ refreshUI();
+ }
+
+ private void replayBtnActionPerformed(java.awt.event.ActionEvent evt)
+ {
+ game.reset();
+ refreshUI();
+ }
+
+ private void refreshUI() {
+ mainLabel.setText( msgGenerator.getChallengeMessage() );
+ messageLabel.setText( msgGenerator.getResultMessage() );
+ guessText.setText( "" );
+ guessesLeftBar.setValue( game.getRemainingGuesses() );
+ guessText.requestFocus();
+ }
+
+ // swing components
+ private javax.swing.JPanel borderPanel;
+ ...
+ private javax.swing.JButton replayBtn;
+
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="gameIn">
+ <para>
+ The injected instance of the game (logic and state).
+ </para>
+ </callout>
+ <callout arearefs="messagesIn">
+ <para>
+ The injected message generator for UI messages.
+ </para>
+ </callout>
+ <callout arearefs="start">
+ <para>
+ This application is started in the prescribed Weld SE way,
+ by observing the <literal>ContainerInitialized</literal> event.
+ </para>
+ </callout>
+ <callout arearefs="init">
+ <para>
+ This method initializes all of the Swing components. Note
+ the use of the <literal>msgGenerator</literal> here.
+ </para>
+ </callout>
+ <callout arearefs="guess1">
+ <para>
+ <literal>guessButtonActionPerformed</literal> is called
+ when the 'Guess' button is clicked, and it does the
+ following:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Gets the guess entered by the user and sets it as the
+ current guess in the <literal>Game</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Calls <literal>game.check()</literal> to validate and
+ perform one 'turn' of the game
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Calls <literal>refreshUI</literal>. If there were
+ validation errors with the input, this will have been
+ captured during <literal>game.check()</literal> and
+ as such will be reflected in the messages returned by
+ <literal>MessageGenerator</literal> and subsequently
+ presented to the user. If there are no validation
+ errors then the user will be told to guess again
+ (higher or lower) or that the game has ended either
+ in a win (correct guess) or a loss (ran out of
+ guesses).
+ </para>
+ </listitem>
+ </itemizedlist>
+ </callout>
+ <callout arearefs="replay">
+ <para>
+ <literal>replayBtnActionPerformed</literal> simply calls
+ <literal>game.reset()</literal> to start a new game and
+ refreshes the messages in the UI.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ </section>
+ </section>
+
+ <section id="translator">
+ <title>The translator example in depth</title>
+
+ <para>
+ The translator example will take any sentences you enter, and translate them to Latin. (Well, not really, but
+ the stub is there for you to implement, at least. Good luck!)
+ </para>
+
+ <para>
+ The translator example is built as an EAR and contains EJBs. As a result, it's structure is more complex than
+ the numberguess example.
+ </para>
+
+ <note>
+ <para>
+ Java EE 6, which bundles EJB 3.1, allows you to package EJBs in a WAR, which will make this structure much
+ simpler! Still, there are other advantages of using an EAR.
+ </para>
+ </note>
+
+ <para>
+ First, let's take a look at the EAR aggregator, which is located in the example's <literal>ear</literal> directory. Maven
+ automatically generates the <literal>application.xml</literal> for us from this plugin configuration:
+ </para>
+
+ <programlisting role="XML"><![CDATA[<plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-ear-plugin</artifactId>
+ <configuration>
+ <modules>
+ <webModule>
+ <groupId>org.jboss.weld.examples.jsf.translator</groupId>
+ <artifactId>weld-jsf-translator-war</artifactId>
+ <contextRoot>/weld-translator</contextRoot>
+ </webModule>
+ </modules>
+ </configuration>
+</plugin>]]></programlisting>
+
+ <para>
+ This configuration overrides the web context path, resulting in this application URL: <ulink
+ url="http://localhost:8080/weld-translator">http://localhost:8080/weld-translator</ulink>.
+ </para>
+
+ <tip>
+ <para>
+ If you weren't using Maven to generate these files, you would need
+ <literal>META-INF/application.xml</literal>:
+ </para>
+
+ <programlisting role="XML"><![CDATA[<application version="5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/application_5.xsd">
+
+ <display-name>weld-jsf-translator-ear</display-name>
+ <description>The Weld JSF translator example (EAR)</description>
+
+ <module>
+ <web>
+ <web-uri>weld-translator.war</web-uri>
+ <context-root>/weld-translator</context-root>
+ </web>
+ </module>
+ <module>
+ <ejb>weld-translator.jar</ejb>
+ </module>
+</application>]]></programlisting>
+ </tip>
+
+ <para>
+ Next, lets look at the WAR, which is located in the example's <literal>war</literal> directory. Just as in the
+ numberguess example, we have a <literal>faces-config.xml</literal> for JSF 2.0 and a <literal>web.xml</literal>
+ (to activate JSF) under WEB-INF, both sourced from <literal>src/main/webapp/WEB-INF</literal>.
+ </para>
+
+ <para>
+ More interesting is the JSF view used to translate text. Just as in the numberguess example we have a template,
+ which surrounds the form (ommitted here for brevity):
+ </para>
+
+ <programlisting role="XML"><![CDATA[<h:form id="translator">
+
+ <table>
+ <tr align="center" style="font-weight: bold">
+ <td>
+ Your text
+ </td>
+ <td>
+ Translation
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80"/>
+ </td>
+ <td>
+ <h:outputText value="#{translator.translatedText}"/>
+ </td>
+ </tr>
+ </table>
+ <div>
+ <h:commandButton id="button" value="Translate" action="#{translator.translate}"/>
+ </div>
+
+</h:form>]]></programlisting>
+
+ <para>
+ The user can enter some text in the left-hand textarea, and hit the translate button to see the result to the
+ right.
+ </para>
+
+ <para>
+ Finally, let's look at the EJB module, which is located in the example's <literal>ejb</literal> directory. In
+ <literal>src/main/resources/META-INF</literal> there is just an empty <literal>beans.xml</literal>, used to
+ mark the archive as containing beans.
+ </para>
+
+ <para>
+ We've saved the most interesting bit to last, the code! The project has two simple beans,
+ <literal>SentenceParser</literal> and <literal>TextTranslator</literal> and two session beans,
+ <literal>TranslatorControllerBean</literal> and <literal>SentenceTranslator</literal>. You should be getting
+ quite familiar with what a bean looks like by now, so we'll just highlight the most interesting bits here.
+ </para>
+
+ <para>
+ Both <literal>SentenceParser</literal> and <literal>TextTranslator</literal> are dependent beans, and
+ <literal>TextTranslator</literal> uses constructor injection:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public class TextTranslator implements Serializable {
+
+ private SentenceParser sentenceParser;
+
+ @EJB private Translator translator;
+
+ @Inject public TextTranslator(SentenceParser sentenceParser) {
+ this.sentenceParser = sentenceParser;
+ }
+
+ public String translate(String text) {
+ StringBuilder sb = new StringBuilder();
+ for (String sentence: sentenceParser.parse(text)) {
+ sb.append(translator.translate(sentence)).append(". ");
+ }
+ return sb.toString().trim();
+ }
+
+}]]></programlisting>
+
+ <para>
+ <literal>TextTranslator</literal> uses the simple bean (really just a plain Java class!)
+ <literal>SentenceParser</literal> to parse the sentence and then calls on the stateless bean with the local
+ business interface <literal>Translator</literal> to perform the translation. That's where the magic happens.
+ Of course, we couldn't develop a full translator, but it's convincing enough to anyone who doesn't understand
+ Latin!
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Stateless
+public class SentenceTranslator implements Translator {
+
+ public String translate(String sentence) {
+ return "Lorem ipsum dolor sit amet";
+ }
+
+}]]></programlisting>
+
+ <para>
+ Finally, there is UI orientated controller. This is a request scoped, named, stateful session bean, which
+ injects the translator. It collects the text from the user and dispatches it to the translator. The bean also
+ has getters and setters for all the fields on the page.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Stateful
+@RequestScoped
+@Named("translator")
+public class TranslatorControllerBean implements TranslatorController {
+
+ @Inject private TextTranslator translator;
+
+ private String inputText;
+
+ private String translatedText;
+
+ public void translate() {
+ translatedText = translator.translate(inputText);
+ }
+
+ public String getText() {
+ return inputText;
+ }
+
+ public void setText(String text) {
+ this.inputText = text;
+ }
+
+ public String getTranslatedText() {
+ return translatedText;
+ }
+
+ @Remove public void remove() {}
+
+}]]></programlisting>
+
+ </section>
+
+ <para>
+ That concludes our short tour of the Weld starter examples. For more information on Weld, or to help out with
+ development, please visit <ulink
+ url="http://www.seamframework.org/Weld/Development">http://www.seamframework.org/Weld/Development</ulink>.
+ </para>
+
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
+</chapter>
14 years, 7 months
Weld SVN: r4942 - doc/trunk/reference/en-US.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-11-10 00:13:46 -0500 (Tue, 10 Nov 2009)
New Revision: 4942
Modified:
doc/trunk/reference/en-US/intro.xml
Log:
fix code bug
Modified: doc/trunk/reference/en-US/intro.xml
===================================================================
--- doc/trunk/reference/en-US/intro.xml 2009-11-10 05:08:55 UTC (rev 4941)
+++ doc/trunk/reference/en-US/intro.xml 2009-11-10 05:13:46 UTC (rev 4942)
@@ -189,7 +189,7 @@
<programlisting role="JAVA"><![CDATA[@Inject Instance<TextTranslator> textTranslatorInstance;
...
public void translate() {
- textTranslatorInstance().translate(inputText);
+ textTranslatorInstance.get().translate(inputText);
}]]></programlisting>
<para>
14 years, 7 months
Weld SVN: r4941 - doc/trunk/reference/en-US.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-11-10 00:08:55 -0500 (Tue, 10 Nov 2009)
New Revision: 4941
Modified:
doc/trunk/reference/en-US/intro.xml
Log:
title
Modified: doc/trunk/reference/en-US/intro.xml
===================================================================
--- doc/trunk/reference/en-US/intro.xml 2009-11-10 05:05:27 UTC (rev 4940)
+++ doc/trunk/reference/en-US/intro.xml 2009-11-10 05:08:55 UTC (rev 4941)
@@ -59,7 +59,7 @@
</section>
<section id="first-bean">
- <title>Your first bean (or is it?)</title>
+ <title>Getting our feet wet</title>
<para>
Suppose that we have two existing Java classes that we've been using for years in various applications. The
14 years, 7 months
Weld SVN: r4940 - doc/trunk/reference/en-US.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-11-10 00:05:27 -0500 (Tue, 10 Nov 2009)
New Revision: 4940
Modified:
doc/trunk/reference/en-US/part1.xml
Log:
minor
Modified: doc/trunk/reference/en-US/part1.xml
===================================================================
--- doc/trunk/reference/en-US/part1.xml 2009-11-10 05:03:26 UTC (rev 4939)
+++ doc/trunk/reference/en-US/part1.xml 2009-11-10 05:05:27 UTC (rev 4940)
@@ -143,7 +143,7 @@
A bean specifies only the type and semantics of other beans it depends upon. It need not be aware of the actual
lifecycle, concrete implementation, threading model or other clients of any bean it interacts with. Even better,
the concrete implementation, lifecycle and threading model of a bean may vary according to the deployment scenario,
- without affecting any client. This loose-coupling is what makes the architecture so simple, yet powerful.
+ without affecting any client. This loose-coupling makes your code easier to maintain.
</para>
<para>
14 years, 7 months
Weld SVN: r4939 - doc/trunk/reference/en-US.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-11-10 00:03:26 -0500 (Tue, 10 Nov 2009)
New Revision: 4939
Modified:
doc/trunk/reference/en-US/part1.xml
Log:
fix
Modified: doc/trunk/reference/en-US/part1.xml
===================================================================
--- doc/trunk/reference/en-US/part1.xml 2009-11-10 05:02:06 UTC (rev 4938)
+++ doc/trunk/reference/en-US/part1.xml 2009-11-10 05:03:26 UTC (rev 4939)
@@ -142,9 +142,8 @@
<para>
A bean specifies only the type and semantics of other beans it depends upon. It need not be aware of the actual
lifecycle, concrete implementation, threading model or other clients of any bean it interacts with. Even better,
- the concrete implementation, lifecycle and threading model of a bean it depends upon may vary according to the
- deployment scenario, without affecting any client. This loose-coupling is what makes the architecture so simple,
- yet powerful.
+ the concrete implementation, lifecycle and threading model of a bean may vary according to the deployment scenario,
+ without affecting any client. This loose-coupling is what makes the architecture so simple, yet powerful.
</para>
<para>
14 years, 7 months