We're going to explore the different kinds of beans that Weld supports without any work on our part.
As mentioned earlier, the Managed Beans specification was introduced in Java EE 6 to provide a common definition of a Managed Bean. All that's required to create a Managed Bean is to annotate it with @ManagedBean
, though CDI doesn't require us to do so.
Note
JSF also has a @ManagedBean
annotation to define their beans, and it's important to not confuse the two as they are separate annotations. Future releases of the JSF specification will endeavor to close this gap by utilizing the annotation from the Managed Beans specification.
Earlier in this chapter, we covered the requirements for constructors of a Java class to be a Managed Bean, but the CDI specification states that it must also meet the following conditions:
It is not a non-static inner class
It is a concrete class or is annotated
@Decorator
It is not annotated with an EJB component-defining annotation or declared as an EJB bean class in
ejb-jar.xml
It does not implement
javax.enterprise.inject.spi.Extension
According to the preceding conditions, Java Persistence API (JPA) entities are also Managed Beans! Trying to use entities as Managed Beans will cause runtime issues when attempting to persist Managed Beans that have been proxied by CDI.
Session Beans can take advantage of CDI just like any other bean, though there are a few restrictions due to Session Beans having their lifecycle managed separate to CDI.
Message-driven and entity beans are not contextual objects in the CDI sense, so they are not able to be injected into other beans. It is possible to inject beans into a message-driven bean, and use interceptors and decorators to utilize some of the CDI functionalities that are available.
As the EJB container controls the lifecycle of a stateless Session Bean and a singleton Session Bean, there is no need to specify any CDI scope for these, but a stateful Session Bean may use any scope it requires.
In these final two sections, we will introduce producers, both method and field, which can be used to provide a CDI bean that isn't a Java class, per se. Producers are often useful in a situation where it is not known during development which particular qualified bean instance needs to be used, and producers allow us to create a bean that depends on runtime information for its creation.
Producers provide a source for new bean instances. A producer will be invoked by Weld when there is no instance of that bean in the required context.
We will cover producers in detail in Chapter 5, Producers.
To create a producer on a method, all that's required is to annotate the method with @Produces
, along with any other qualifiers that we want the bean being produced to fulfill.
Note
Though producer methods can be called by our application, just as any other method, the returned bean will be completely outside the control of CDI. If the method has parameters, they will not be injected with beans at all; they would need to be passed just like any method call.
We'll define a producer method for UserAccount
from an earlier example:
public class AccountManager { @Produces @User Account getUserAccount() { ... } }
The bean created from this producer can then be injected by using:
@Inject @User Account userAccount;
We can also add @Named
to allow the bean to be accessed via EL, which for this example would be userAccount
.
Producer methods can also declare parameters, and the container will retrieve a bean that matches the bean type and qualifiers that can be passed into the method.
Producer fields are a simpler alternative to producer methods, as they remove the need to create a method and thus reduce boilerplate code. If we converted the producer method from the previous example, it would be as follows:
public class AccountManager { @Produces @User Account userAccount = ...; }
In situations where you have a bean with a field that you want to make available to other beans, using a producer field is often the best way to achieve this as it only involves one or more annotations being added to the existing field definition.
We can also add @Named
to the producer field and access the bean with the same EL name from the previous example.