JBoss.org Community Documentation

Chapter 15. Introduction to EJB3 Interceptors

The EJB 3.0 spec defines the ability to apply custom made interceptors to the business methods of your session and message driven beans. EJB 3.0 interceptors take the form of methods annotated with the @javax.ejb.AroundInvoke annotation. These methods must have the following signature:

			
@javax.ejb.AroundInvoke
public Object <Arbitrary method name>(javax.ejb.InvocationContext ctx) throws java.lang.Exception

			
		

Note

You can apply interceptors to JBoss specific @Service and @Consumer beans

You can either define an interceptor method in the bean class itself, or in separate classes. There can only be one interceptor method per class.

Interceptor method in bean class :

Take a look at org.jboss.tutorial.interceptor.bean.EmailMDB . It contains this method:

			
@AroundInvoke
public Object mdbInterceptor(InvocationContext ctx) throws Exception
{
   System.out.println("*** Intercepting call to EmailMDB.mdbInterceptor()");
   return ctx.proceed();
}
			
		

This method will wrap the call to EmailMDB.onMessage(). The call to ctx.proceed() causes the next object in the chain of interceptors to get invoked. At the end of the chain of interceptors, the actual bean method gets called.

Similarly org.jboss.tutorial.interceptor.bean.EmailSystemBean has a method annotated with @AroundInvoke

				
@AroundInvoke
public Object myBeanInterceptor(InvocationContext ctx) throws Exception
{
   if (ctx.getMethod().getName().equals("emailLostPassword"))
   {
      System.out.println("*** EmailSystemBean.myBeanInterceptor - username: " + ctx.getParameters()[0]);
   }

   return ctx.proceed();
}

				
			

External interceptors :

The rest of this example will be looking at adding interceptors external to the bean class, more specifically to EmailSystemBean . Interceptors can be bound in three different ways:

  • Default

  • Class level

  • Method level

An external interceptor instance follows the lifecycle of the target bean instance.

Default interceptors :

We will see how class and method-level interceptors can be bound to a bean or a bean's method using annotations or xml. Default interceptors can only be bound via xml. A Default interceptor is an interceptor that is invoked whenever a business method is invoked on any bean within the deployment.

org.jboss.tutorial.interceptor.bean.DefaultInterceptor defines an @AroundInvoke method with the required method signature.

					
@AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception
{
   System.out.println("*** DefaultInterceptor intercepting " + ctx.getMethod().getName());
   try
   {
      return ctx.proceed();
   }
   finally
   {
      System.out.println("*** DefaultInterceptor exiting");
   }
}

					
			

As mentioned, default interceptors can only be applied via xml. In META-INF/ejb-jar.xml we have the following:

					
<assembly-descriptor>
 <!-- Default interceptor that will apply to all methods for all beans in deployment -->
 <interceptor-binding>
      <ejb-name>*</ejb-name>
      <interceptor-class>org.jboss.tutorial.interceptor.bean.DefaultInterceptor</interceptor-class>
   </interceptor-binding>
   ...
</assembly-descriptor>

					
			

Using * for the ejb-name says that DefaultInterceptor is a default interceptor, i.e. it should intercept all calls to all beans within the deployment unit. We could have added more interceptor-class entries to bind more interceptors, as shown here:

				
<assembly-descriptor>
   <!-- Default interceptor that will apply to all methods for all beans in deployment -->
   <interceptor-binding>
      <ejb-name>*</ejb-name>
      <interceptor-class>org.jboss.tutorial.interceptor.bean.DefaultInterceptor</interceptor-class>
      <interceptor-class>org.jboss.tutorial.interceptor.bean.AnotherInterceptor</interceptor-class>
   </interceptor-binding>
   ...
</assembly-descriptor>

				
			

In this case DefaultInterceptor would be invoked before AnotherInterceptor.

Class-level interceptors :

Class-level interceptors can be bound using xml or annotations.

Class-level using annotations :

org.jbos.tutorial.interceptor.EmailSystemBean has been annotated:

					
@Stateless
@Interceptors ({TracingInterceptor.class})
public class EmailSystemBean
{
   ...
}

					
				

This says that the @AroundInvoke annotated method of org.jboss.tutorial.interceptor.bean.TracingInterceptor should wrap all calls to EmailSystemBean's business methods. The @Interceptors annotation can take an array of classes, so you can bind more than one class-level interceptor this way, e.g.

					
@Stateless
@Interceptors ({TracingInterceptor.class, SomeInterceptor.class})
public class EmailSystemBean
{
   ...
}

					
				

Class-level using xml :

In the META-INF/ejb-jar.xml we have the following:

					
<assembly-descriptor>
   ...
	  <!-- Class interceptor that will apply to all methods for EmailSystemBean -->
	   <interceptor-binding>
         <ejb-name>EmailSystemBean</ejb-name>
         <interceptor-class>org.jboss.tutorial.interceptor.bean.OtherInterceptor</interceptor-class>
      </interceptor-binding>
   ...
</assembly-descriptor>

					
				

Note that here we are specifying the ejb-name of the bean we want to apply the interceptor to. Hence, the @AroundInvoke annotated method of org.jboss.tutorial.interceptor.bean.OtherInterceptor will wrap all calls to EmailSystemBean's business methods.

Method-level interceptors :

Just as we can define default and class-level interceptors, we can also bind an interceptor to a particular business method of a bean

Method-level using annotations :

org.jboss.tutorial.interceptor.bean.EmailSystemBean's sendBookingConfirmationMessage() method has been annotated with the @Interceptors annotation specifying interceptors that will intercept when this perticular method is invoked.

				
@Interceptors({AccountsConfirmInterceptor.class})
public void sendBookingConfirmationMessage(long orderId)
{
   ...
}

				
			

Method-level interceptors are in addition to default and class-level interceptors, meaning that when we call EmailSystemBean.sendBookingConfirmationMessage() we get intercepted by

  • DefaultInterceptor (default)

  • TracingInterceptor (class-level)

  • OtherInterceptor (class-level)

  • AccountsConfirmInterceptor (method-level)

An interceptor method can choose to abort an invocation, by not calling InvocationContext.proceed() as is done in AccountConfirmInterceptor's interceptor method when a confirmation already exists.

Method-level using xml :

We can also bind interceptors to a single business method within a bean using xml. But first let's define an interceptor using xml. All the examples we have looked at so far have used the @AroundInvoke annotation to mark the interceptor methods. In META-INF/ejb-jar.xml we have the following:

				
<interceptors>
     <interceptor>
        <interceptor-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</interceptor-class>
        <around-invoke>
           <method-name>sendCancelMessage</method-name>
        </around-invoke>
		...

     </interceptor>
</interceptors>

				
			

This tells us that the sendCancelMessage() method of org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor is the interceptor method of this interceptor class. To bind interceptors to a particular method using xml, is much the same as how this was done for class-level interceptors apart from that we specify the method-name of the method we want to intercept. From our META-INF/ejb-jar.xml:

				
 <assembly-descriptor>
    ...
	   <!-- Method interceptor will apply to sendBookingCancellationMessage for EmailSystemBean -->
	   <interceptor-binding>
         <ejb-name>EmailSystemBean</ejb-name>
         <interceptor-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</interceptor-class>
         <method>
           <method-name>sendBookingCancellationMessage</method-name>
         </method>
      </interceptor-binding>

    ...
 </assembly-descriptor>

				
			

In the case of overloaded methods, we can further narrow down the method by specifying the method parameters, as in this example:

				
<assembly-descriptor>
   	...
	<!-- Method interceptor will apply to sendBookingCancellationMessage for EmailSystemBean -->
	   <interceptor-binding>
         <ejb-name>SomeBean</ejb-name>
         <interceptor-class>SomeInterceptor</interceptor-class>
         <method>
           <method-name>methodWithParam</method-name>
           <method-params>
           		<method-param>int</method-param>
           		<method-param>java.lang.String[]</method-param>
           </method-params>
         </method>
      </interceptor-binding>
</assembly-descriptor>

				
			

SomeInterceptor will only get applied to the method of SomeBean that matches the signature, i.e. methodWithParam(int, java.lang.String[])

Exclusion of default and class interceptors :

For some beans we may want to exclude the default interceptors configured for the deployment, and for some methods within a bean class we may want to exclude the class interceptors for the bean (and/or the default interceptors)

Annotations :

The @javax.ejb.ExcludeDefaultInterceptors annotation can be applied to a bean class or a method. If applied to a bean class, default interceptors will not get invoked for any of that bean class's methods. If applied to a bean business method, default interceptors will not get invoked when calling that method.

The @javax.ejb.ExcludeClassInterceptors annotation can be applied to a bean method. When this annotation is used class-level interceptors will not get invoked when calling that method.

org.jboss.tutorial.interceptor.bean.EmailMDB defines

						
@ExcludeDefaultInterceptors
public class EmailMDB implements MessageListener
{
   ...
}

						
					

so DefaultInterceptor is not invoked when invoking the EmailMDB.onMessage()

org.jboss.tutorial.interceptor.bean.EmailSystemBean's noop method is annotated with both @ExcludeClassInterceptors and @ExcludeDefaultInterceptors and so will not get intercepted by any of these.

						
@ExcludeClassInterceptors
@ExcludeDefaultInterceptors
public void noop()
{
   System.out.println("<In EmailSystemBean.noop business method");
   System.out.println("Exiting EmailSystemBean.noop business method>");
}

						
					

XML :

We can also exclude class and method-level interceptors within an interceptor-binding by specifying the exclude-class-interceptors and exclude-default-interceptors elements.

						
<assembly-descriptor>
      ...

	   <interceptor-binding>
         <ejb-name>EmailSystemBean</ejb-name>
         <exclude-default-interceptors>true</exclude-default-interceptors>
         <exclude-class-interceptors>true</exclude-class-interceptors>
         <method>
           <method-name>noop2</method-name>
         </method>
      </interceptor-binding>
	...
</assembly-descriptor>
						
					

Inheritance Ordering :

If an interceptor (or bean class) inherits from another class which has a method declared to be an interceptor method, the interceptor methods from the super class will be invoked first. However, if the interceptor method in the superclass has been overridden (regardless of if the overriding method is declared to be an interceptor method or not) the superclass method is not invoked.

Both org.jboss.tutorial.interceptor.bean.AccountsConfirmInterceptor and org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor inherit from org.jboss.tutorial.interceptor.bean.AccountsInterceptor.

AccountsInterceptor declares the following interceptor method:

				
@AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception
{
   System.out.println("*** AccountsInterceptor intercepting " + ctx.getMethod().getName());
   try
   {
      return ctx.proceed();
   }
   finally
   {
      System.out.println("*** AccountsInterceptor exiting");
   }
}

				
			

This method is overridden by AccountsConfirmInterceptor, even though it is not AccountsConfirmInterceptor's interceptor method:

				
public class AccountsConfirmInterceptor extends AccountsInterceptor
{
   ...
   public Object intercept(InvocationContext ctx) throws Exception
   {
      //overrides AccountsInterceptor.intercept() so that will not be invoked
      return null;
   }


   @AroundInvoke
   public Object sendConfirmMessage(InvocationContext ctx) throws Exception
   {
      ...
   }
}
				
			

So when invoking AccountsConfirmInterceptor, we simply invoke its sendConfirmMessage() method. AccountsCancelInterceptor, on the other hand, does not override AccountsInterceptor.intercept(), so when invoking AccountsCancelInterceptor, we first get intercepted by AccountsInterceptor.intercept() followed by AccountsCancelInterceptor.sendCancelMessage().

Injection in interceptors:
Using Annotations :

Just like a bean class, an interceptor can be the target of dependency injection (see the "injection" tutorial for details about injection). The format for how this works is the same, and the injection works off the same ENC as the bean to which the interceptor is bound.

org.jboss.tutorial.interceptor.bean.AccountsConfirmInterceptor has dependency injection set up using annotations:

					
public class AccountsConfirmInterceptor extends AccountsInterceptor
{
   @Resource(mappedName="java:ConnectionFactory")
   QueueConnectionFactory cf;

   @Resource(mappedName="queue/tutorial/accounts")
   Queue queue;

   @PersistenceContext
   EntityManager em;

   ...

					
				

Remember that interceptors follow the same lifecycle as the bean they are bound to. The interceptors are created at the same time as the bean instance is created, and dependecy injection occurs before the first business method is called. In the example just shown, the container:
  • Looks up java:ConnectionFactory, binds it in the ENC and injects this into the field cf

  • Looks up queue/tutorial/accounts, binds it in the ENC and injects this into the field queue

  • Obtains the default EntityManager and injects this into the field em

Using XML :

Injection, into interceptors, can also be configured via xml, using the traditional ejb-ref, ejb-local-ref, resource-ref, resource-env-ref etc. which bind the global names. The only difference from beans is that we put this into the {{interceptors}} element defining the interceptor.

					
<interceptors>
     <interceptor>
        <interceptor-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</interceptor-class>
        <around-invoke>
           <method-name>sendCancelMessage</method-name>
        </around-invoke>
        <resource-ref>
        	<res-ref-name>jms/ConnFactory</res-ref-name>
           <res-type>javax.jms.QueueConnectionFactory</res-type>
           <res-auth>Container</res-auth>
           <mapped-name>java:/ConnectionFactory</mapped-name>
           <injection-target>
              <injection-target-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</injection-target-class>
              <injection-target-name>cf</injection-target-name>
           </injection-target>
        </resource-ref>
        <resource-env-ref>
        	<resource-env-ref-name>accountsQueue</resource-env-ref-name>
           <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
           <mapped-name>queue/tutorial/accounts</mapped-name>
           <injection-target>
              <injection-target-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</injection-target-class>
              <injection-target-name>queue</injection-target-name>
           </injection-target>
        </resource-env-ref>
     </interceptor>
</interceptors>

					
				

  • The container looks up java:/ConnectionFactory in JNDI and creates the java:comp/env/jms/ConnFactory entry in the bean's ENC, and following bean creation it injects the connection factory into AccountsCancelInterceptor's cf field.

  • The container looks up queue/tutorial/accounts in JNDI and creates the java:comp/env/accountsQueue entry in the bean's ENC, and following bean creation it injects the queue into AccountsCancelInterceptor's queue field.

Interceptor Ordering :

By default the ordering of interceptors when invoking a method are

  • External interceptors

  • Default interceptors, if present

  • Class interceptors, if present

  • Method interceptors, if present

  • Interceptor method on the bean class (using @AroundInvoke)

Within each group (default, class, method) the order of the interceptors are from left to right as defined in the @Interceptors annotation, and then the xml interceptors.

Overriding interceptor ordering :

You can override the default sort order of the external interceptors by specifiying an interceptor-binding with an interceptor-order specifying the order of the interceptors

					
<assembly-descriptor>
      <interceptor-binding>
         <ejb-name>EmailSystemBean</ejb-name>
         <interceptor-order>
            <interceptor-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</interceptor-class>
            <interceptor-class>org.jboss.tutorial.interceptor.bean.DefaultInterceptor</interceptor-class>
            <interceptor-class>org.jboss.tutorial.interceptor.bean.OtherInterceptor</interceptor-class>
            <interceptor-class>org.jboss.tutorial.interceptor.bean.TracingInterceptor</interceptor-class>
         </interceptor-order>
         <method>
           <method-name>sendBookingCancellationMessage</method-name>
         </method>
      </interceptor-binding>
      ...
</assembly-descriptor>

					
				

So when invoking EmailSystemBean.sendBookingCancellationMessage we will get the following interception order, quite different from the default sort order
  • AccountsCancelInterceptor (method-level)

  • DefaultInterceptor (default interceptor)

  • OtherInterceptor (2nd class-level interceptor)

  • TracingInterceptor (1st class-level interceptor)

InvocationContext :

As you have seen the @AroundInvoke annotated interceptor methods all take a parameter of type javax.ejb.InvocationContext. The definition of InvocationContext is:

				

package javax.interceptor;

public interface InvocationContext {

	public java.lang.Object getTarget();

    public java.lang.reflect.Method getMethod();

	public java.lang.Object[] getParameters();

  	public void setParameters(java.lang.Object[] arg0);

	public java.util.Map getContextData();

	public java.lang.Object proceed() throws java.lang.Exception;
}
				

			

getBean() - returns the bean instance on which we are calling a method

getMethod() - returns the method we are calling on the bean instance

getParameters() - returns the parameters for the method call

setParameters() - allows you to modify the parameters for the method call

getContextData - The EJB interceptions are stateless, but the same InvocationContext instance is used for each interceptor method in a chain. If you want to pass values between interceptor methods in the business method invocation you can store them in the Map retured by getContextData().

proceed - As discussed, invokes the next interceptor, or if we are in the last interceptor invokes the target bean method.

In some case we might want access to the EJBContext, this can be injected into the interceptor instance using the @Resource annotation. The AroundInvoke methods share the JNDI name space of the bean for whose methods they are invoked and execute within the same transaction and security context as the business methods for which they are invoked.

Building and Running

Note

To build and run the example, make sure you have installed JBoss 5.x. See the Section 1.1, “JBoss Application Server 5.x” for details.

From the command prompt, move to the "interceptor" folder under the Section 1.3, “Set the EJB3_TUTORIAL_HOME”

Ant Users:

Make sure your JBossAS-5.x is running

			
$ ant
$ ant run

run:
     [java] Starting
     [java]
     [java] Calling emailLostPassword
     [java] Waiting 2 seconds
     [java]
     [java] Calling sendBookingConfirmationMessage
     [java] Waiting 2 seconds
     [java]
     [java] Calling sendBookingConfirmationMessage
     [java] Waiting 2 seconds
     [java]
     [java] Calling sendBookingCancellationMessage
     [java] Waiting 2 seconds
     [java]
     [java] Calling noop
     [java] Waiting 2 seconds
     [java]
     [java] Calling noop2
     [java] Waiting 2 seconds
     [java] Done

		     
			

Maven Users: Make sure the AS is not running.

$ mvn clean install -PRunSingleTutorial
			

					
21:49:01,888 INFO  [STDOUT] *** DefaultInterceptor intercepting emailLostPassword
21:49:01,889 INFO  [STDOUT] *** TracingInterceptor intercepting emailLostPassword
21:49:01,889 INFO  [STDOUT] *** OtherInterceptor intercepting emailLostPassword
21:49:01,889 INFO  [STDOUT] *** EmailSystemBean.myBeanInterceptor - username: whatever
21:49:01,889 INFO  [STDOUT] <In EmailSystemBean.emailLostPassword business method
21:49:02,083 INFO  [STDOUT] Message sent successfully to remote queue.
21:49:02,130 INFO  [STDOUT] Exiting EmailSystemBean.emailLostPassword business method>
21:49:02,130 INFO  [STDOUT] *** OtherInterceptor exiting
21:49:02,130 INFO  [STDOUT] *** TracingInterceptor invocation of org.jboss.tutorial.interceptor.bean.EmailSystemBean.emailLostPassword() took 241ms
21:49:02,130 INFO  [STDOUT] *** DefaultInterceptor exiting
21:49:02,179 WARN  [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
21:49:02,180 WARN  [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
21:49:02,185 INFO  [STDOUT] *** EmailMDB.mdbInterceptor intercepting
21:49:02,185 INFO  [STDOUT]
----------------
EMailMDB - Got message, sending email
----------------
21:49:04,251 INFO  [STDOUT] *** DefaultInterceptor intercepting sendBookingConfirmationMessage
21:49:04,251 INFO  [STDOUT] *** TracingInterceptor intercepting sendBookingConfirmationMessage
21:49:04,251 INFO  [STDOUT] *** OtherInterceptor intercepting sendBookingConfirmationMessage
21:49:04,251 INFO  [STDOUT] *** AccountsConfirmInterceptor intercepting
21:49:04,395 INFO  [STDOUT] *** AccountsConfirmInterceptor - recording confirmation
21:49:04,431 INFO  [STDOUT] *** AccountsConfirmInterceptor - notifying accounts dept sendBookingConfirmationMessage
21:49:04,440 INFO  [STDOUT] <In EmailSystemBean.sendBookingConfirmationMessage business method
21:49:04,455 WARN  [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
21:49:04,455 WARN  [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
21:49:04,458 INFO  [STDOUT] *** DefaultInterceptor intercepting onMessage
21:49:04,459 INFO  [STDOUT]
----------------
AccountsMDB - Got message Confirming order 100
----------------
21:49:04,459 INFO  [STDOUT] *** DefaultInterceptor exiting
21:49:04,466 INFO  [STDOUT] Message sent successfully to remote queue.
21:49:04,467 INFO  [STDOUT] Exiting EmailSystemBean.sendBookingConfirmationMessage business method>
21:49:04,467 INFO  [STDOUT] *** AccountsConfirmInterceptor exiting
21:49:04,467 INFO  [STDOUT] *** OtherInterceptor exiting
21:49:04,467 INFO  [STDOUT] *** TracingInterceptor invocation of org.jboss.tutorial.interceptor.bean.EmailSystemBean.sendBookingConfirmationMessage() took 216ms
21:49:04,467 INFO  [STDOUT] *** DefaultInterceptor exiting
21:49:04,478 INFO  [STDOUT] *** EmailMDB.mdbInterceptor intercepting
21:49:04,478 INFO  [STDOUT]
----------------
EMailMDB - Got message, sending email
----------------
21:49:06,533 INFO  [STDOUT] *** DefaultInterceptor intercepting sendBookingConfirmationMessage
21:49:06,533 INFO  [STDOUT] *** TracingInterceptor intercepting sendBookingConfirmationMessage
21:49:06,533 INFO  [STDOUT] *** OtherInterceptor intercepting sendBookingConfirmationMessage
21:49:06,533 INFO  [STDOUT] *** AccountsConfirmInterceptor intercepting
21:49:06,547 INFO  [STDOUT] *** AccountsConfirmInterceptor - order has already been confirmed aborting
21:49:06,548 INFO  [STDOUT] *** AccountsConfirmInterceptor exiting
21:49:06,548 INFO  [STDOUT] *** OtherInterceptor exiting
21:49:06,548 INFO  [STDOUT] *** TracingInterceptor invocation of org.jboss.tutorial.interceptor.bean.EmailSystemBean.sendBookingConfirmationMessage() took 15ms
21:49:06,548 INFO  [STDOUT] *** DefaultInterceptor exiting
21:49:08,577 INFO  [STDOUT] *** AccountsInterceptor intercepting sendBookingCancellationMessage
21:49:08,577 INFO  [STDOUT] *** AccountsCancelInterceptor intercepting sendBookingCancellationMessage
21:49:08,577 INFO  [STDOUT] *** AccountsConfirmInterceptor - notifying accounts dept
21:49:08,593 INFO  [STDOUT] *** DefaultInterceptor intercepting sendBookingCancellationMessage
21:49:08,593 INFO  [STDOUT] *** OtherInterceptor intercepting sendBookingCancellationMessage
21:49:08,593 INFO  [STDOUT] *** TracingInterceptor intercepting sendBookingCancellationMessage
21:49:08,593 INFO  [STDOUT] <In EmailSystemBean.sendBookingCancellationMessage business method
21:49:08,605 INFO  [STDOUT] Message sent successfully to remote queue.
21:49:08,606 INFO  [STDOUT] Exiting EmailSystemBean.sendBookingCancellationMessage business method>
21:49:08,606 INFO  [STDOUT] *** TracingInterceptor invocation of org.jboss.tutorial.interceptor.bean.EmailSystemBean.sendBookingCancellationMessage() took 13ms
21:49:08,606 INFO  [STDOUT] *** OtherInterceptor exiting
21:49:08,606 INFO  [STDOUT] *** DefaultInterceptor exiting
21:49:08,606 INFO  [STDOUT] *** AccountsCancelInterceptor exiting
21:49:08,606 INFO  [STDOUT] *** AccountsInterceptor exiting
21:49:08,617 INFO  [STDOUT] *** EmailMDB.mdbInterceptor intercepting
21:49:08,617 INFO  [STDOUT]
----------------
EMailMDB - Got message, sending email
----------------
21:49:08,620 INFO  [STDOUT] *** DefaultInterceptor intercepting onMessage
21:49:08,620 INFO  [STDOUT]
----------------
AccountsMDB - Got message Cancelling order 100
----------------
21:49:08,620 INFO  [STDOUT] *** DefaultInterceptor exiting
21:49:10,628 INFO  [STDOUT] <In EmailSystemBean.noop business method
21:49:10,628 INFO  [STDOUT] Exiting EmailSystemBean.noop business method>
21:49:12,648 INFO  [STDOUT] <In EmailSystemBean.noop2 business method
21:49:12,648 INFO  [STDOUT] Exiting EmailSystemBean.noop2 business method>

						
					

Note

Look at the JBoss console window to see the output of the interceptions taking place, the EmailMDB and AccountsMDB might occur in slightly different places since they execute asynchronously.

You can ignore the [WARN] messages:

21:49:02,179 WARN  [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
21:49:02,180 WARN  [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container