Chapter 10. Specialization

We've already seen how the Web Beans dependency injection model lets us override the implementation of an API at deployment time. For example, the following enterprise Web Bean provides an implementation of the API PaymentProcessor in production:

@CreditCard @Stateless
public class CreditCardPaymentProcessor 
        implements PaymentProcessor {
    ...
}

But in our staging environment, we override that implementation of PaymentProcessor with a different Web Bean:

@CreditCard @Stateless @Staging
public class StagingCreditCardPaymentProcessor 
        implements PaymentProcessor {
    ...
}

What we've tried to do with StagingCreditCardPaymentProcessor is to completely replace AsyncPaymentProcessor in a particular deployment of the system. In that deployment, the deployment type @Staging would have a higher priority than the default deployment type @Production, and therefore clients with the following injection point:

@CreditCard PaymentProcessor ccpp

Would receive an instance of StagingCreditCardPaymentProcessor.

Unfortunately, there are several traps we can easily fall into:

In each of these cases, the Web Bean that we tried to override could still be called at runtime. Therefore, overriding is somewhat prone to developer error.

Web Beans provides a special feature, called specialization, that helps the developer avoid these traps. Specialization looks a little esoteric at first, but it's easy to use in practice, and you'll really appreciate the extra security it provides.

10.1. Using specialization

Specialization is a feature that is specific to simple and enterprise Web Beans. To make use of specialization, the higher-priority Web Bean must:

  • be a direct subclass of the Web Bean it overrides, and

  • be a simple Web Bean if the Web Bean it overrides is a simple Web Bean or an enterprise Web Bean if the Web Bean it overrides is an enterprise Web Bean, and

  • be annotated @Specializes.

@Stateless @Staging @Specializes
public class StagingCreditCardPaymentProcessor 
        extends CreditCardPaymentProcessor {
    ...
}

We say that the higher-priority Web Bean specializes its superclass.

10.2. Advantages of specialization

When specialization is used:

  • the binding types of the superclass are automatically inherited by the Web Bean annotated @Specializes, and

  • the Web Bean name of the superclass is automatically inherited by the Web Bean annotated @Specializes, and

  • producer methods, disposal methods and observer methods declared by the superclass are called upon an instance of the Web Bean annotated @Specializes.

In our example, the binding type @CreditCard of CreditCardPaymentProcessor is inherited by StagingCreditCardPaymentProcessor.

Furthermore, the Web Bean manager will validate that:

  • all API types of the superclass are API types of the Web Bean annotated @Specializes (all local interfaces of the superclass enterprise bean are also local interfaces of the subclass),

  • the deployment type of the Web Bean annotated @Specializes has a higher precedence than the deployment type of the superclass, and

  • there is no other enabled Web Bean that also specializes the superclass.

If any of these conditions are violated, the Web Bean manager throws an exception at initialization time.

Therefore, we can be certain that the superclass with never be called in any deployment of the system where the Web Bean annotated @Specializes is deployed and enabled.