6 What’s Left to Discover?

CDI contains a number of other features that are not required for our application. These are described in brief in the following sections. If you want to learn more about any of the topics, we recommend you take a look at Weld, the CDI Reference Implementation.

6.1 ApplicationScope and ConversationScope

CDI has other interesting scopes in addition to the ones we have already described, with ApplicationScope and ConversationScope being particularly worthy of mention.

With ConversationScope, the bean is able to control its lifecycle independently via a third object – the so-called Conversation. This scope is recommended for situations in which user data must be stored across multiple views, such as in the case of a Wizard. When a Wizard is started, the Conversation is started also – and with it, the lifecycle of the bean. When the Wizard is ended, so is the Conversation, which in turn ends the lifecycle of the bean. The Conversation is started and ended using the methods begin and end.

ApplicationScope is the easiest scope to explain: beans with this scope exist only once for all users across an application. This means that beans with this scope can exchange data between all users; in our application, it could be used to cache the sum of all donations made.

Corresponding annotations are @ConversationScoped and @ApplicationScoped – both are located in the package javax.enterprise.context.

6.2 The FlowScope

The introduction of Faces Flows in JSF 2.2 represented a new concept in JSF – one that required beans with a higher lifespan than the ViewScope was able to offer.

If a developer defines a Faces Flow, they need their stored data to be preserved for its entire duration. A reason for this can be that the views involved in the Faces Flow are required to exchange data.

A Faces Flow does not have a set duration; instead, its duration is defined by the times at which it is started and ended. With this in mind, JSF 2.2 introduced a new scope for CDI – the so-called FlowScope. Beans with this scope exist for the duration of a Faces Flow.

To make a bean FlowScoped, we must use the annotation @FlowScoped from the package javax.faces.flow.

6.3 Interceptors and Decorators

Interceptors and decorators both modify methods of beans using methods of other independent classes.

When a method is invoked, an interceptor enables to invoke another method before or after the invocation of the original method. In CDI, an annotation is applied to the method to be modified to specify which interceptor should be used.

Decorators must implement the same interface as the bean to be modified. However, a decorator contains an additional delegation object that also implements an interface and corresponds to the runtime of the relevant bean. If a decorator is invoked using the CDI configuration file beans.xml, the decorator will respond to the invoking of a bean method by invoking the same method in the decorator. This method can then execute code and, where needed, can invoke methods of the bean to be modified using the delegation object. We have no need to explore decorators further within the scope of this workshop.

Interceptors are usually used for the decoupling of technical aspects like logging and transaction handling. Decorators are used for the decoupling of domain aspects, such as the storage of business rules.

Java EE 7 saw the introduction of a new functionality for decorators and interceptors: if multiple decorators or interceptors were defined within an application, the developer was now able to determine in which order these should be used.

6.4 Stereotypes

Stereotypes condense multiple annotations into one. This enables a bean to be used with a single annotation, rather than many. This is not only simpler – it also means the annotations can be changed at a central location, in the file in which the new annotation is defined.

Let’s say that the new annotation, @Action, combines the annotations @RequestScoped, @Transactional and @Named. It is much easier to annotate a bean simply with

@Action

than to annotate it with

@RequestScoped
@Transactional
@Named

every time. It is worth mentioning that @Transactional is an annotation for the execution of a transaction; however, this will be discussed in this tutorial.

6.5 The BeanManager

Using the BeanManager, a method can be instructed in the code to request a reference to a CDI bean from the CDI container. This means that the bean is not injected with the annotation @Inject as it usually is.

The simple example below shows how a reference to our CampaignListProducer can be obtained using the BeanManager:

BeanManager bm = CDI.current().getBeanManager();
Bean<CampaignListProducer> bean = (Bean<CampaignListProducer>) bm.getBeans(CampaignListProducer.class).iterator().next();
CreationalContext<CampaignListProducer> ctx = bm.createCreationalContext(bean);
CampaignListProducer producer = (CampaignListProducer) bm.getReference(bean, CampaignListProducer.class, ctx);

A new addition in Java EE 7 was that the expression CDI.current().getBeanManager() could be used to return a reference to the BeanManager. Before Java EE 7, such a reference could only be obtained by injecting the BeanManager object or by using a JNDI lookup at java:comp/BeanManager.

6.6 Extensions

CDI enables certain so-called extensions that extend the container in a variety of ways. The Apache project Deltaspike is a handy collection of such extensions. If you want to learn more, we recommend you take a look at the Deltaspike website. There, you’ll find a number of modules for extending CDI beans with functionalities that are typically associated with EJBs and are lacking in CDIs.

6.7 Disposer Methods

Producer methods were introduced in section 3.4. Since these methods create a CDI bean, we might wonder how the developer is informed when the container wishes to remove the bean. This issue is of particular interest for dependent resources that must be explicitly cleaned up, such as database connections.

Take a look at the following simplified example, which creates a new database connection of type Connection for every request:

@Produces
@RequestScoped
public Connection connect() {
...
}

Before the request is ended, the database connection must be closed by invoking the method close. This is accomplished by the following disposer method:

void close(@Disposes Connection connection) {
    connection.close();
}

What we still don’t know is how the container finds the right disposer method for a particular producer method. In fact, the answer is very simple. Firstly, both methods must be defined in the same class. Secondly, the return value of the producer method must correspond with the disposer method’s input parameter type (the parameter is also annotated with @Disposes).

Discussion

Use the message board below to give the authors your feedback or to discuss this page’s topic with other readers (in English please!). Please don’t expect the authors to answer directly, but they might update the content of this site according to your feedback.