Enterprise Java Development@TOPIC@
Interpose on contructor, EJB business and lifecycle methods
Interceptor lifecycle is same as the bean it interposes on (i.e., Stateless/Stateful)
EJB Interceptors may define AroundInvoke
callbacks for
business methods
MDB onMessage()
May throw runtime and application exceptions declared by business method
Interceptors may rollback the current transaction by
throwing a RuntimeException
calling setRollbackOnly()
on the EJBContext
Figure 115.1. Sample Business Method being Intercepted
@Stateless
public class ContactsEJB implements ContactsRemote {
@PersistenceContext(unitName="ejbinterceptor-contacts")
private EntityManager em;
@Override
public Contact createContact(Contact contact) throws InvalidParam {
logger.debug("createContact({})", contact);
em.persist(contact);
return contact;
}
Figure 115.2. Sample Business Method Interceptor
import javax.interceptor.AroundConstruct;
public class LifecycleInterceptor {
@Resource
private EJBContext ejbCtx;
@AroundInvoke
public Object invoke(InvocationContext ctx) throws Exception {
logger.debug("*** Business Method: {}, caller={}", ctx.getMethod(), ejbCtx.getCallerPrincipal().getName());
Object response = ctx.proceed();
logger.debug("*** Response Object: {}", response);
return response;
}
Figure 115.3. Sample Output
LifecycleInterceptor] (EJB default - 4) *** Business Method: public info.ejava.examples.ejb.interceptor.bo.Contact info.ejava.examples.ejb.interceptor.ejb.ContactsEJB.createContact(info.ejava.examples.ejb.interceptor.bo.Contact) throws info.ejava.examples.ejb.interceptor.ejb.InvalidParam, caller=anonymous ContactsEJB] (EJB default - 4) createContact(Contact [id=0, name=John Doe, normalizedName=null]) LifecycleInterceptor] (EJB default - 4) *** Response Object: Contact [id=1, name=John Doe, normalizedName=john doe]
Information about the call intercepted
Methods to control behavior of invocation chain
Figure 115.4. InvocationContext Interface
public interface javax.interceptor.InvocationContext {
public abstract java.lang.Object getTarget();
public abstract java.lang.Object getTimer();
public abstract java.lang.reflect.Method getMethod();
public abstract java.lang.reflect.Constructor<?> getConstructor();
public abstract java.lang.Object[] getParameters();
public abstract void setParameters(java.lang.Object[]);
public abstract java.util.Map<java.lang.String, java.lang.Object> getContextData();
public abstract java.lang.Object proceed() throws java.lang.Exception;
}
All EJB Interceptors may define standard lifecycle callbacks
AroundConstruct
PostConstruct
PreDestory
Stateful EJB Interceptors
may define state callbacks
PrePassivate
PostActivate
may use an extended persistence context
Figure 115.5. Lifecycle Callbacks
public class LifecycleInterceptor {
@AroundConstruct
public void ctor(InvocationContext ctx) {
...
}
@PostConstruct
public void init(InvocationContext ctx) {
...
}
@PreDestroy
public void destory(InvocationContext ctx) {
...
}
EJB Interceptors may define AroundTimeout
for timer methods
May call InvocationContext.getTimer()
to get timed out timer
May not throw application exceptions
Figure 115.6.
public class LifecycleInterceptor {
@AroundTimeout
public Object timeout(InvocationContext ctx) throws Exception {
logger.debug("*** Timeout: {}", ctx.getTimer());
Object response = ctx.proceed();
return response;
}
EJB Deployment descriptor (ejb-jar.xml)
@Interceptors annotation
CDI Deployment descriptor (beans.xml)
Figure 115.7. EJB Descriptor (ejb-jar.xml) Activation
<?xml version="1.0"?>
<ejb-jar ...
<assembly-descriptor>
<interceptor-binding>
<ejb-name>ContactsEJB</ejb-name>
<interceptor-class>info.ejava.examples.ejb.interceptor.interceptors.LifecycleInterceptor</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
</ejb-jar>
Decouples EJB and Interceptor classes
Assign to specific EJBs or globally
Assign to specific EJB methods or global to class
Can control order applied
Figure 115.8. @Interceptor(s) Annotation Activation
//way 1 - class level
@Stateless
@Interceptors({ //global to EJB class
PreNormizedInterceptor.class,
ContactsNormalizerInterceptor.class,
PostNormizedInterceptor.class,
})
public class ContactsEJB implements ContactsRemote {
//way 2 - method level
@Stateless
public class ContactsEJB implements ContactsRemote {
@Override
@Interceptors({ //specific to individual EJB method
PreNormizedInterceptor.class,
ContactsNormalizerInterceptor.class,
PostNormizedInterceptor.class,
})
public Contact createContact(Contact contact) throws InvalidParam {
@Annotation near-equivalent to EJB deployment descriptor
Couples EJB class to Interceptor class
Cannot assign globally to all EJBs
Can assign to specific EJB methods or global to class
Can control order applied