Possible OPENEJB Bug with Interceptors?

View: New views
4 Messages — Rating Filter:   Alert me  

Possible OPENEJB Bug with Interceptors?

by Marrrck :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Apologies in advance if this has been already reported or I have it wrong. I've searched and it seems that no one else has encountered my specific problem....

The issue I'm having in a nutshell is that my interceptor is not being called for public session bean methods that are called from within other methods in the same class. This is a problem for me because I'm trying to do some exception handling in my generic interceptor, and it is getting bypassed when a session bean method is called from another method. Here's an example:

/////// interceptor
public class TestInterceptor {
@AroundInvoke
  public Object interceptor(InvocationContext invocation) throws Exception {
     System.out.println("Interceptor invoked!");
      return invocation.proceed();
  }
}

///////// session bean interface
@Local
public interface mySessionBeanLocal {
   public void method1();
   public void method2();
}

///////// session bean impl
@Stateful
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Interceptors(TestInterceptor .class)
public class mySessionBean implements mySessionBeanLocal {

   @Override
   public void method1() {
     System.out.println("Method 1 invoked!");
    method2();
   }

   @Override
   public void method2() {
    System.out.println("Method 2 invoked!");
   }
}

I have a junit test case that is annotated with @LocalClient and has an injected copy of mySessoinBeanLocal using @EJB. When my unit test calls method1(), it appears that the interceptor is only triggered when method1() is called but not when method2() is invoked by method1(). If I deploy the same code on JBoss, the interceptor is tripped twice as I would expect it to be. (I'm using Openejb 3.1.1)

Any thoughts/advice/workarounds would be greatly appreciated! Is this a bug in openejb or a bug in JBoss? (or a bug in my reasoning... )

Re: Possible OPENEJB Bug with Interceptors?

by David Blevins :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Oct 22, 2009, at 1:05 PM, Marrrck wrote:

> The issue I'm having in a nutshell is that my interceptor is not being
> called for public session bean methods that are called from within  
> other
> methods in the same class.

> ///////// session bean impl
> @Stateful
> @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
> @Interceptors(TestInterceptor .class)
> public class mySessionBean implements mySessionBeanLocal {
>
>   @Override
>   public void method1() {
>     System.out.println("Method 1 invoked!");
>    method2();
>   }
>
>   @Override
>   public void method2() {
>    System.out.println("Method 2 invoked!");
>   }
> }

Per EJB spec if you wanted container managed anything you have to go  
through the business interface.  This is the motivation for these  
methods on javax.ejb.SessionContext:

     javax.ejb.EJBLocalObject getEJBLocalObject();
     javax.ejb.EJBObject getEJBObject();
     java.lang.Object getBusinessObject(java.lang.Class aClass);

You can do what you want portably like so:

   @Override
   public void method1() {
     System.out.println("Method 1 invoked!");

     
sessionContext.getBusinessObject(mySessionBeanLocal.class).method2();
   }

Clearly JBoss is using byte code enhancement to add container managed  
features directly to your bean class.  This is certainly a neat idea  
-- kicked it around myself a few times -- but not a feature of EJB.  I  
don't know if I'd go as far to say that it's illegal or a bug, but it  
is definitely a very container specific feature  (really more like a  
very container specific architecture).


-David



Re: Possible OPENEJB Bug with Interceptors?

by Marrrck :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Ah, thanks for the clarification! Unfortunately this solution won't work for me because the session bean is stateful. When I modify the code like this:

///////// session bean impl
@Stateful
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Interceptors(TestInterceptor .class)
public class mySessionBean implements mySessionBeanLocal {
   @Resource
   private SessionConext context;

   @Override
   public void method1() {
     System.out.println("Method 1 invoked!");
    context.getBusinessObject(mySessionBeanLocal.class).method2();
   }

   @Override
   public void method2() {
    System.out.println("Method 2 invoked!");
   }
}


I get a "Concurrent calls not allowed" exception:

javax.ejb.EJBException: The bean encountered a non-application exception; nested exception is:
        javax.ejb.EJBException: Concurrent calls not allowed
        at org.apache.openejb.core.ivm.BaseEjbProxyHandler.convertException(BaseEjbProxyHandler.java:358)
        at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:286)
        at $Proxy117.method1(Unknown Source)
        //....
Caused by: javax.ejb.EJBException: Concurrent calls not allowed
        at org.apache.openejb.core.ivm.BaseEjbProxyHandler.convertException(BaseEjbProxyHandler.java:358)
        at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:286)
        at $Proxy117.Method2(Unknown Source)
        //...
Caused by: java.rmi.RemoteException: Concurrent calls not allowed
        at org.apache.openejb.core.stateful.StatefulContainer.obtainInstance(StatefulContainer.java:635)
        at org.apache.openejb.core.stateful.StatefulContainer.businessMethod(StatefulContainer.java:484)
        at org.apache.openejb.core.stateful.StatefulContainer.invoke(StatefulContainer.java:274)
        at org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod(EjbObjectProxyHandler.java:217)
        at org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke(EjbObjectProxyHandler.java:77)
        at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:281)
        ... 56 more

Not sure what the right thing to do is here. I guess the easiest thing would be to move method2 into a different stateful session bean and inject that into the first session bean? "A session bean method should never invoke another public method defined by that session bean's business interface" seems like kind of an arbitrary rule though. Or I guess I could just not rely on interceptors....

David Blevins wrote:
On Oct 22, 2009, at 1:05 PM, Marrrck wrote:

> The issue I'm having in a nutshell is that my interceptor is not being
> called for public session bean methods that are called from within  
> other
> methods in the same class.

> ///////// session bean impl
> @Stateful
> @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
> @Interceptors(TestInterceptor .class)
> public class mySessionBean implements mySessionBeanLocal {
>
>   @Override
>   public void method1() {
>     System.out.println("Method 1 invoked!");
>    method2();
>   }
>
>   @Override
>   public void method2() {
>    System.out.println("Method 2 invoked!");
>   }
> }

Per EJB spec if you wanted container managed anything you have to go  
through the business interface.  This is the motivation for these  
methods on javax.ejb.SessionContext:

     javax.ejb.EJBLocalObject getEJBLocalObject();
     javax.ejb.EJBObject getEJBObject();
     java.lang.Object getBusinessObject(java.lang.Class aClass);

You can do what you want portably like so:

   @Override
   public void method1() {
     System.out.println("Method 1 invoked!");

     
sessionContext.getBusinessObject(mySessionBeanLocal.class).method2();
   }

Clearly JBoss is using byte code enhancement to add container managed  
features directly to your bean class.  This is certainly a neat idea  
-- kicked it around myself a few times -- but not a feature of EJB.  I  
don't know if I'd go as far to say that it's illegal or a bug, but it  
is definitely a very container specific feature  (really more like a  
very container specific architecture).


-David


Re: Possible OPENEJB Bug with Interceptors?

by David Blevins :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Oct 23, 2009, at 7:48 AM, Marrrck wrote:

> I get a "Concurrent calls not allowed" exception:

This is a bug.  Filed it here:

  https://issues.apache.org/jira/browse/OPENEJB-1099

> Not sure what the right thing to do is here. I guess the easiest  
> thing would
> be to move method2 into a different stateful session bean and inject  
> that
> into the first session bean?

That would definitely work.

-David