EJB Interceptors can be added much the same way at two different levels:
- At EJB Container level
- At Application level
If you want to learn more Application level EJB interceptors you can have a look at: How to code EJB interceptors like a pro
Finally, if you want to learn how to monitor EJB deployments using the CLI have a look at: Monitoring the EJB container using the CLI
In this article we will show how to apply EJB Interceptors at EJB Container level, which allows tracing calls to all EJBs running as well as individual EJBs.
Configuring Container Interceptors
Firstly, to configure EJB Container interceptors you can use the file jboss-ejb3.xml . You need to place this file in the the META-INF folder of the EJB deployment. Let’s see one example:
<jboss xmlns="http://www.jboss.com/xml/ns/javaee" xmlns:jee="http://java.sun.com/xml/ns/javaee" xmlns:ci ="urn:container-interceptors:1.0"> <jee:assembly-descriptor> <ci:container-interceptors> <!-- Default interceptor --> <jee:interceptor-binding> <ejb-name>*</ejb-name> <interceptor-class>com.mastertheboss.interceptor.GenericContainerInterceptor</interceptor-class> </jee:interceptor-binding> <!-- Class level container-interceptor --> <jee:interceptor-binding> <ejb-name>ClassLevelContainerInterceptor</ejb-name> <interceptor-class>com.mastertheboss.interceptor.ClassLevelContainerInterceptor</interceptor-class> </jee:interceptor-binding> <!-- Method specific container-interceptor --> <jee:interceptor-binding> <ejb-name>MethodSpecificContainerInterceptor</ejb-name> <interceptor-class>com.mastertheboss.interceptor.MethodSpecificContainerInterceptor</interceptor-class> <method> <method-name>mymethod</method-name> </method> </jee:interceptor-binding> </ci:container-interceptors> </jee:assembly-descriptor> </jboss>
This file declares three interceptors:
- GenericContainerInterceptor: This Interceptor applies to all (*) EJB Running in the Container
- ClassLevelContainerInterceptor: This Interceptor applies only to the EJB whose name is ClassLevelContainerInterceptor
- MethodSpecificContainerInterceptor: This interceptor applies to the method mymethod() of the Class MethodSpecificContainerInterceptor
As an example, here is the com.mastertheboss.interceptor.GenericContainerInterceptor which includes the javax.interceptor.AroundInvoke annotation in one of its methods:
package com.mastertheboss.interceptor; import org.jboss.logging.Logger; import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext; public class GenericContainerInterceptor { private static Logger log = Logger.getLogger(GenericContainerInterceptor.class); @AroundInvoke private Object intercept(final InvocationContext invocationContext) throws Exception { log.info("Going to call " +invocationContext.getMethod()); // Invoke the EJB method Object result = this.getClass().getName() + " " + invocationContext.proceed(); return result; } }
When executed, this Interceptor will display the EJB being called and its method:
15:02:13,198 INFO' [com.mastertheboss.interceptor.GenericContainerInterceptor] (http-/127.0.0.1:8080-1) Going to call public void com.mastertheboss.ejb.ServiceBean.put(com.mastertheboss.model.SimpleProperty)
Configuring the Order of Interceptors
To configure the Order of Interceptors you can use the interceptor-order element. Within it, add the list of interceptors in the order you want them to be invoked:
<jee:interceptor-binding> <ejb-name>AnotherFlowTrackingBean</ejb-name> <interceptor-order> <interceptor-class>com.mastertheboss.interceptor.ClassLevelContainerInterceptor</interceptor-class> <interceptor-class>com.mastertheboss.interceptor.MethodSpecificContainerInterceptor</interceptor-class> <interceptor-class>com,nastertheboss.interceptor.ContainerInterceptorOne</interceptor-class> </interceptor-order> <method> <method-name>echoInSpecificOrderOfContainerInterceptors</method-name> </method> </jee:interceptor-binding>
JBoss AS 5 – 6
EJB 3 Interceptors are defined in the file server/<your server>/deploy/ejb3-interceptors.xml.
<domain name="Stateless Bean" extends="Intercepted Bean" inheritBindings="true"> . . . . <bind pointcut="execution(public * *->*(..))"> <interceptor-ref name="org.jboss.aspects.tx.TxPropagationInterceptor"/> <interceptor-ref name="org.jboss.ejb3.tx.CMTTxInterceptorFactory"/> <interceptor-ref name="org.jboss.ejb3.stateless.StatelessInstanceInterceptor"/> <interceptor-ref name="org.jboss.ejb3.tx.BMTTxInterceptorFactory"/> <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/> <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/> <!-- interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/ --> <stack-ref name="EJBInterceptors"/> </bind> <annotation expr="!class(@org.jboss.ejb3.annotation.Pool)"> @org.jboss.ejb3.annotation.Pool (value="ThreadlocalPool", maxSize=30, timeout=10000) </annotation> </domain>
<!--------- OUR INTERCEPTOR ----------> <interceptor class="com.sample.PoolInterceptor" scope="PER_VM"/> ........ <domain name="Stateless Bean" extends="Intercepted Bean" inheritBindings="true"> <interceptor-ref name="org.jboss.aspects.tx.TxPropagationInterceptor"/> <interceptor-ref name="org.jboss.ejb3.tx.CMTTxInterceptorFactory"/> <interceptor-ref name="org.jboss.ejb3.stateless.StatelessInstanceInterceptor"/> <interceptor-ref name="org.jboss.ejb3.tx.BMTTxInterceptorFactory"/> <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/> <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/> <!--------- OUR INTERCEPTOR ----------> <interceptor-ref name="com.sample.PoolInterceptor"/> <stack-ref name="EJBInterceptors"/> </bind> <annotation expr="!class(@org.jboss.ejb3.annotation.Pool)"> @org.jboss.ejb3.annotation.Pool (value="StrictMaxPool", maxSize=1000, timeout=100000) </annotation> </domain>
Compile’ the interceptor and add the class to the jboss-ejb3-core.jar
‘ That’s all! restart the server and verify that your SLSB now debugs information about the current/max size of instances.