1

Does new transaction starts when method b() is called from method a()? Or this is just a method call from the object and annotation does not work? If so, how to do that transaction started?

@Stateless
public class TestBean {
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void a() {
        b();
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void b() {
    }
}
shurik2533
  • 1,770
  • 4
  • 22
  • 41
  • It is depend on what library/framework you use. In plane java of course not. – talex Oct 16 '14 at 10:16
  • possible duplicate of [EJB Transactions in local method-calls](http://stackoverflow.com/questions/427452/ejb-transactions-in-local-method-calls) – Gas Oct 16 '14 at 13:44

2 Answers2

4

You can easily check that by querying the current transaction status using the TransactionSynchronizationRegistry resource. Here is an example i tried on Wildfly 8.1:

1 - Inject the TransactionSynchronizationRegistry as resource:

@Resource
TransactionSynchronizationRegistry txReg;

2 - a small helper to query the current tranaaction status and return a human readable String:

private String getTXStatus()
{
    int txStatus = this.txReg.getTransactionStatus();
    switch (txStatus)
    {
        case Status.STATUS_ACTIVE:
            return "STATUS_ACTIVE";
        case Status.STATUS_COMMITTED:
            return "STATUS_COMMITTED";

        case Status.STATUS_COMMITTING:
            return "STATUS_COMMITTING";
        case Status.STATUS_MARKED_ROLLBACK:
            return "STATUS_MARKED_ROLLBACK";
        case Status.STATUS_NO_TRANSACTION:
            return "STATUS_NO_TRANSACTION";
        case Status.STATUS_PREPARED:
            return "STATUS_PREPARED";
        case Status.STATUS_PREPARING:
            return "STATUS_PREPARING";
        case Status.STATUS_ROLLEDBACK:
            return "STATUS_ROLLEDBACK";
        case Status.STATUS_ROLLING_BACK:
            return "STATUS_ROLLING_BACK";
        case Status.STATUS_UNKNOWN:
            return "STATUS_UNKNOWN";
        default:
            return "Unknown(" + txStatus + ")";
    }

3 - now you may instrument your business methods with some quick and dirty logging (and NEVER put System.out.println() in productive EJB code!

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void a()
{
    System.out.println("+++ a()");
    System.out.println("TX status is " + getTXStatus());
    b();
    System.out.println("TX status is " + getTXStatus());
    System.out.println("--- a()");
}

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void b()
{
    System.out.println("+++ b()");
    System.out.println("TX status is " + getTXStatus());
    System.out.println("--- b()");
}

4 - now we may invoke a() and then b() from some client:

String beanName = "ejb:EJB3/MOD3//SagMalWas!de.treufuss.ejb3project.client.HelloWorldRemote";
HelloWorldBIF bif = HelloWorldBIF.class.cast(jndiContext.lookup(beanName));
bif.a();
bif.b();

which yields the following output in servers console:

12:58:33,123 INFO  [stdout] (EJB default - 3) +++ a()
12:58:33,123 INFO  [stdout] (EJB default - 3) TX status is STATUS_NO_TRANSACTION
12:58:33,123 INFO  [stdout] (EJB default - 3) +++ b()
12:58:33,123 INFO  [stdout] (EJB default - 3) TX status is STATUS_NO_TRANSACTION
12:58:33,123 INFO  [stdout] (EJB default - 3) --- b()
12:58:33,124 INFO  [stdout] (EJB default - 3) TX status is STATUS_NO_TRANSACTION
12:58:33,124 INFO  [stdout] (EJB default - 3) --- a()

12:58:33,127 INFO  [stdout] (EJB default - 4) +++ b()
12:58:33,128 INFO  [stdout] (EJB default - 4) TX status is STATUS_ACTIVE
12:58:33,128 INFO  [stdout] (EJB default - 4) --- b()

Which proves that no transaction is started for invocation of b() from a

Addendum

You may force creation of a new transaction by invoking the b() method via beans business interface from EJB context. To do that...

1 - Inject EJB context as resource

@Resource
private SessionContext ctx;

2 - Invoke b() method via business interface:

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void a()
{
    System.out.println("+++ a()");
    System.out.println("TX status is " + getTXStatus());
    // Direct invocation is treated as POJMC (plain old java method call 
    b();
    // Indirect invocation via EJB context
    HelloWorldLocal thisBean = ctx.getBusinessObject(HelloWorldLocal.class);
    thisBean.b();
    System.out.println("TX status is " + getTXStatus());
    System.out.println("--- a()");
}
Gyro Gearless
  • 5,131
  • 3
  • 18
  • 14
2

No transaction will be started. This is treated as internal method and is associated with current transaction. Since you a() method declares NOT_SUPPORTED transaction attribute, there will be no transaction created during invocation of methods a() and b(). Transaction attributes are respected, when Client calls the method, so if some component will call testBean.b() then new transaction will be created regardless, whether there already was transaction present or not.

Gas
  • 17,601
  • 4
  • 46
  • 93