Chapter 7. Decorators

Interceptors are a powerful way to capture and separate concerns which are orthogonal to the type system. Any interceptor is able to intercept invocations of any Java type. This makes them perfect for solving technical concerns such as transaction management and security. However, by nature, interceptors are unaware of the actual semantics of the events they intercept. Thus, interceptors aren't an appropriate tool for separating business-related concerns.

The reverse is true of decorators. A decorator intercepts invocations only for a certain Java interface, and is therefore aware of all the semantics attached to that interface. This makes decorators a perfect tool for modeling some kinds of business concerns. It also means that a decorator doesn't have the generality of an interceptor. Decorators aren't able to solve technical concerns that cut across many disparate types.

Suppose we have an interface that represents accounts:

public interface Account {
    public BigDecimal getBalance();
    public User getOwner();
    public void withdraw(BigDecimal amount);
    public void deposit(BigDecimal amount);

Several different Web Beans in our system implement the Account interface. However, we have a common legal requirement that, for any kind of account, large transactions must be recorded by the system in a special log. This is a perfect job for a decorator.

A decorator is a simple Web Bean that implements the type it decorates and is annotated @Decorator.

public abstract class LargeTransactionDecorator 
        implements Account {
    @Decorates Account account;
    @PersistenceContext EntityManager em;
    public void withdraw(BigDecimal amount) {
        if ( amount.compareTo(LARGE_AMOUNT)>0 ) {
            em.persist( new LoggedWithdrawl(amount) );
    public void deposit(BigDecimal amount);
        if ( amount.compareTo(LARGE_AMOUNT)>0 ) {
            em.persist( new LoggedDeposit(amount) );

Unlike other simple Web Beans, a decorator may be an abstract class. If there's nothing special the decorator needs to do for a particular method of the decorated interface, you don't need to implement that method.

7.1. Delegate attributes

All decorators have a delegate attribute. The type and binding types of the delegate attribute determine which Web Beans the decorator is bound to. The delegate attribute type must implement or extend all interfaces implemented by the decorator.

This delegate attribute specifies that the decorator is bound to all Web Beans that implement Account:

@Decorates Account account;

A delegate attribute may specify a binding annotation. Then the decorator will only be bound to Web Beans with the same binding.

@Decorates @Foreign Account account;

A decorator is bound to any Web Bean which:

  • has the type of the delegate attribute as an API type, and

  • has all binding types that are declared by the delegate attribute.

The decorator may invoke the delegate attribute, which has much the same effect as calling InvocationContext.proceed() from an interceptor.

7.2. Enabling decorators

We need to enable our decorator in web-beans.xml.


This declaration serves the same purpose for decorators that the <Interceptors> declaration serves for interceptors:

  • it enables us to specify a total ordering for all decorators in our system, ensuring deterministic behavior, and

  • it lets us enable or disable decorator classes at deployment time.

Interceptors for a method are called before decorators that apply to that method.