Weld SiteCommunity Documentation
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 stateful and contextual. The lifecycle of a bean is managed by the container.
Let’s back up a second. What does it really mean to be contextual? Since beans may be stateful, it matters which 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.
However, like a stateless or singleton model, but unlike stateful session beans, the client does not control the lifecycle of the instance by explicitly creating and destroying it. Instead, the scope of the bean determines:
For a given thread in a CDI application, there may be an active context 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).
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).
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, nor does it even need to know what that lifecycle is. Beans interact by passing messages, and the bean implementations define the lifecycle of their own state. The beans are loosely coupled because:
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 Section 4.7, “Alternatives”.
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.
Enough hand-waving. More formally, the anatomy of a bean, according to the spec:
Let’s see what all this new terminology means.
public class BookShop
extends Business
implements Shop<Book> {
...
}
@Stateful
public class BookShopBean
extends Business
implements BookShop, Auditable {
...
}
The bean types of a session bean include local interfaces and the bean class local view (if any). EJB remote interfaces are not considered bean types of a session bean. You can’t inject an EJB using its remote interface unless you define a resource, which we’ll meet in Chapter 14, Java EE component environment resources.
Bean types may be restricted to an explicit set by annotating the bean
with the @Typed
annotation and listing the classes that should be bean
types. For instance, the bean types of this bean have been restricted to
Shop<Book>
, together with java.lang.Object
:
@Typed(Shop.class)
public class BookShop
extends Business
implements Shop<Book> {
...
}
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 PaymentProcessor
interface:
CreditCardPaymentProcessor
and DebitPaymentProcessor
. Injecting a
field of type PaymentProcessor
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.
A qualifier is a user-defined annotation that is itself annotated
@Qualifier
. 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:
@Qualifier
@Target({TYPE, METHOD, PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface CreditCard {}
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.
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.
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 PaymentProcessor
and qualifier @CreditCard
:
@Inject @CreditCard PaymentProcessor paymentProcessor
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.
How do we specify that qualifiers of a bean? By annotating the bean
class, of course! The following bean has the qualifier @CreditCard
and
implements the bean type PaymentProcessor
. Therefore, it satisfies our
qualified injection point:
@CreditCard
public class CreditCardPaymentProcessor
implements PaymentProcessor { ... }
If a bean or an injection point does not explicitly specify a qualifier,
it has the default qualifier, @Default
.
That’s not quite the end of the story. CDI also defines a simple resolution rule 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 Chapter 4, Dependency injection and programmatic lookup.
For example, any web application may have session scoped bean:
public @SessionScoped
class ShoppingCart implements Serializable { ... }
We’ll talk more about scopes in Chapter 5, Scopes and contexts.
The EL name is specified using the @Named
annotation, as shown here:
public @SessionScoped @Named("cart")
class ShoppingCart implements Serializable { ... }
Now we can easily use the bean in any JSF or JSP page:
<h:dataTable value="#{cart.lineItems}" var="item">
...
</h:dataTable>
We can let CDI choose a name for us by leaving off the value of the
@Named
annotation:
public @SessionScoped @Named
class ShoppingCart implements Serializable { ... }
The name defaults to the unqualified class name, decapitalized; in this
case, shoppingCart
.
public @Alternative
class MockPaymentProcessor extends PaymentProcessorImpl { ... }
We cover alternatives in more detail in Section 4.7, “Alternatives”.
@InterceptorBinding
@Inherited
@Target( { TYPE, METHOD })
@Retention(RUNTIME)
public @interface Transactional {}
The interceptor that implements transaction management declares this annotation:
public @Transactional @Interceptor
class TransactionInterceptor { ... }
public @SessionScoped @Transactional
class ShoppingCart implements Serializable { ... }
Notice that ShoppingCart
and TransactionInterceptor
don’t know
anything about each other.
We’ll discuss interceptors, and their cousins, decorators, in Chapter 9, Interceptors and Chapter 10, Decorators.
If a managed bean has a public field, it must have the default scope
@Dependent
.
Managed beans support the @PostConstruct
and @PreDestroy
lifecycle
callbacks.
A producer method is declared by annotating a method of a bean class
with the @Produces
annotation.
import javax.enterprise.inject.Produces;
@ApplicationScoped
public class RandomNumberGenerator {
private java.util.Random random = new java.util.Random(System.currentTimeMillis());
@Produces @Named @Random int getRandomNumber() {
return random.nextInt(100);
}
}
@Inject @Random int randomNumber;
Even in a Unified EL expression:
<p>Your raffle number is #{randomNumber}.</p>
The bean types of a producer method depend upon the method return type:
java.lang.Object
.java.lang.Object
.@Produces Set<Roles> getRoles(User user) {
return user.getRoles();
}
We’ll talk much more about producer methods in Chapter 8, Producer methods.
import javax.enterprise.inject.Produces;
public class Shop {
@Produces PaymentProcessor paymentProcessor = ....;
@Produces @Catalog List<Product> products = ....;
}
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 Chapter 14, Java EE component environment resources. Because we can’t wait to get to work on some examples.