SeamFramework.orgCommunity Documentation
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
.
Sfortunatamente ci sono parecchie trappole in cui è facile cadere:
the higher-priority Web Bean may not implement all the API types of the Web Bean that it attempts to override,
the higher-priority Web Bean may not declare all the binding types of the Web Bean that it attempts to override,
the higher-priority Web Bean might not have the same name as the Web Bean that it attempts to override, or
the Web Bean that it attempts to override might declare a producer method, disposal method or observer method.
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.
Specialization is a feature that is specific to simple and enterprise Web Beans. To make use of specialization, the higher-priority Web Bean must:
essere un diretta sottoclasse del Web Bean di cui fa l'override, e
essere un semplice Web Bean se il Web Bean di cui fare override è un semplice Web Bean o un Web Bean Enterprise se il Web Bean di cui fa override è un Web Bean Enterprise, e
essere annotato con @Specializes
.
@Stateless @Staging @Specializes
public class StagingCreditCardPaymentProcessor
extends CreditCardPaymentProcessor {
...
}
We say that the higher-priority Web Bean specializes its superclass.
Quando viene usata la specializzazione:
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.