0

I am using jboss 5.1.0.GA (build: SVNTag=JBoss_5_1_0_GA date=200905221634). And need to get business interface of the bean. That is necessary for transaction management. So I have:

@Local
public interface MyBeanInterface {
    void transactionalMethod();
}

@Stateless
public class MyBean implements MyBeanInterface {
    @Resource
    private SessionContext context;

    private int aState;

    public void someMethod() {
        aState = 42;
        context.getBusinessObject(MyBeanInterface.class).transactionalMethod();
    }

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void transactionalMethod() {
        System.out.println(aState); // 0!!!!!
    }
}

For some reason I do not get the same bean, but new bean is created. That is disastrous as transactionalMethod needs the state variable value to execute correctly.

What am I doing wrong, or that is a bug of jboss? By the way there is a bug which affects ability to get business object via bean's class: https://issues.jboss.org/browse/EJBTHREE-2126. Not sure however if it relates to my issue.

michael nesterenko
  • 14,222
  • 25
  • 114
  • 182
  • This is just how it *should* behave as you work with a *stateless* session bean. You might have to use stateful session beans (or singletons, etc.). – home Jan 27 '13 at 22:08
  • @home , Are you sure? From documentation: http://docs.oracle.com/javaee/5/api/javax/ejb/SessionContext.html#getBusinessObject%28java.lang.Class%29 `Obtain an object that can be used to invoke the current bean through the given business interface.` – michael nesterenko Jan 27 '13 at 22:14
  • Hm, your correct, at least the documentation states it should be called on the same bean. But I'd guess this is not necessarily the same instance of the given bean. It would make sense to return another instance as otherwise you would cross transaction boundaries... luckily I never used that feature :-) – home Jan 28 '13 at 06:58

2 Answers2

1

The best solution is this:

@Stateless
public class MyBean implements MyBeanInterface {

    @Resource private TransactionManager tm;

    private int aState;

    public void someMethod() {
        aState = 42;

        Transaction transaction = tm.suspend();

        transactionalMethod();

        tm.resume(transaction);
    }

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void transactionalMethod() {
        System.out.println(aState); // 0!!!!!
    }
}

When you call a published interface method from the same istance, passing by ejb context, the resource is:

  • If it is @Stateless, a new instance is created.
  • If it is @Stateful, a new session is created for the first call, then other call are same as @Singleton.
  • If it is @Singleton, the caller waits for the resource to be freed, in case it calls itself, a deadlock is created. If the method is annotated with @Read, calling yourself does not create any deadlocks.
0

I don't have time to see if the syntax is perfect but you could try:

InitialContext jndiContext = new InitialContext();
Object ref = jndiContext.lookup("projname/MyBeanInterface/local");
MyBeanInterfaceLocal m = (MyBeanInterfaceLocal) ref;

However I saw that you have a SessionContext field, so maybe for you the code should be a little bit different. Maybe it would be:

Object ref = SessionContext.lookup("projname/MyBeanInterface/local");
MyBeanInterfaceLocal m = (MyBeanInterfaceLocal) ref;

Let me know if this helps!