The Java EE 7 Tutorial

Previous
Next

25.7 Using Decorators in CDI Applications

A decorator is a Java class that is annotated javax.decorator.Decorator and that has a corresponding decorators element in the beans.xml file.

A decorator bean class must also have a delegate injection point, which is annotated javax.decorator.Delegate. This injection point can be a field, a constructor parameter, or an initializer method parameter of the decorator class.

Decorators are outwardly similar to interceptors. However, they actually perform tasks complementary to those performed by interceptors. Interceptors perform cross-cutting tasks associated with method invocation and with the lifecycles of beans, but cannot perform any business logic. Decorators, on the other hand, do perform business logic by intercepting business methods of beans. This means that instead of being reusable for different kinds of applications, as are interceptors, their logic is specific to a particular application.

For example, instead of using an alternative TestCoderImpl class for the encoder example, you could create a decorator as follows:

@Decorator
public abstract class CoderDecorator implements Coder {
    
    @Inject
    @Delegate
    @Any
    Coder coder;
    
    public String codeString(String s, int tval) {
        int len = s.length();

        return "\"" + s + "\" becomes " + "\"" + coder.codeString(s, tval)
                + "\", " + len + " characters in length";
    }
}

See The decorators Example: Decorating a Bean for an example that uses this decorator.

This simple decorator returns more detailed output than the encoded string returned by the CoderImpl.codeString method. A more complex decorator could store information in a database or perform some other business logic.

A decorator can be declared as an abstract class so that it does not have to implement all the business methods of the interface.

In order for a decorator to be invoked in a CDI application, it must, like an interceptor or an alternative, be specified in the beans.xml file. For example, the CoderDecorator class is specified as follows:

<decorators>
    <class>javaeetutorial.decorators.CoderDecorator</class>
</decorators>

If an application uses more than one decorator, the decorators are invoked in the order in which they are specified in the beans.xml file.

If an application has both interceptors and decorators, the interceptors are invoked first. This means, in effect, that you cannot intercept a decorator.

The decorators that you specify in the beans.xml file apply only to classes in the same archive. Use the @Priority annotation to specify decorators globally for an application that consists of multiple modules, as in the following example:

@Decorator
@Priority(Interceptor.Priority.APPLICATION)
public abstract class CoderDecorator implements Coder { ... }

Decorators with lower priority values are called first. You do not need to specify the decorator in the beans.xml when you use the @Priority annotation.

Previous
Next