In a Bean Managed Transaction, the code in the EJB or Message Driven Bean explicitly marks the boundaries of the transaction. Although beans with container-managed transactions require less coding, they have one limitation: When a method is executing, it can be associated with either a single transaction or no transaction at all. If this limitation will make coding your bean difficult, you should consider using bean-managed transactions. How do you code an EJB 3 using bean managed transactions ? 

Here is an example:

package com.mastertheboss.ejb;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.PersistenceContext;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;


@Stateless
@TransactionManagement(TransactionManagementType.BEAN)

public class ManagedComponent {
    /**
     * Ask the container to inject an Entity Manager (EM). As a consequence the EM will be automatically enlisted into any new
     * transactions started by the managed component.
     *
     */
    @PersistenceContext
    private EntityManager entityManager;

    // Inject a UserTransaction for manual transaction demarcation.
    @Inject
    private UserTransaction userTransaction;

    public String executeTransaction() {

        try {
            userTransaction.begin();

            // Execute Transaction here

            userTransaction.commit();

            return result;
        } catch (Exception e) {
            return e.getMessage();
        } finally {
            /*
             * Clean up
             */
            try {
                if (userTransaction.getStatus() == Status.STATUS_ACTIVE)
                    userTransaction.rollback();
            } catch (Throwable e) {
                // ignore
            }
        }
    }
}

As you can see, we specify that an EJB uses BMT by using the @TransactionManagement annotation and setting its TransactionManagementType element to BEAN. Next, the transaction operations are enclosed in a code sequence starting with the UserTransaction 's begin method and ending with the commit method. Please note that the above example @Inject the UserTransaction therefore you need to include also CDI dependencies in your project.

On the other hand, if you are not using CDI in your project, you can use the legacy @Resource annotation to inject the UserTransaction in your project:

@Resource
private UserTransaction utx;

A Message Driven Bean BMT

Much the same way, we can code a Message Driven Bean using BMT. Here is an example:

import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import javax.transaction.UserTransaction;

import org.jboss.ejb3.annotation.ResourceAdapter;

@MessageDriven(name = "MDB_BMTExample", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
                                                            @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"),
                                                            @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Dups-ok-acknowledge") })
@TransactionManagement(value = TransactionManagementType.BEAN)
@ResourceAdapter("hornetq-ra.rar")
public class MDB_BMTExample implements MessageListener
{
   @Resource
   MessageDrivenContext ctx;

   public void onMessage(final Message message)
   {
      try
      {
         
         TextMessage textMessage = (TextMessage)message;
         String text = textMessage.getText();
         System.out.println("message " + text + " received");

         // lets look at the user transaction to make sure there isn't one.
         UserTransaction tx = ctx.getUserTransaction();

         if (tx != null)
         {
            tx.begin();
            System.out.println("we're in the middle of a transaction: " + tx);
            tx.commit();
         }
         else
         {
            System.out.println("something is wrong, I was expecting a transaction");
         }
      }
      catch (Exception e)
      {
         e.printStackTrace();
      }
   }
}

Rolling back an EJB BMT Transaction

In a BMT EJB, either the UserTransaction 's rollback() or setRollbackOnly() methods are used to explicitly rollback the transaction. In the above example, we have used the rollback() method of the UserTransaction class, however it is also possible to invoke setRollBackOnly as in this example:

try {
// Starts the transaction
userTransaction.begin;
...
// Commits the transaction
userTransaction.commit();
} catch (FirstException fe ) {
userTransaction.setRollbackOnly();
} catch (SecondException se ) {
userTransaction.setRollbackOnly();
}

So what is the difference between UserTransaction 's rollback() or setRollbackOnly() ? The use of the rollback() method results in the immediate rollback of the transaction. On the other hand, using the setRollbackOnly method only marks the transaction for rollback. It will not be rolled back until the transaction actually ends. Delaying the rollback can be advantageous since it permits other activities to be performed, such as logging the error conditions.

Interview question

Q: And now a nice interview question: what happens if a BMT EJB calls a CMT EJB in its transaction ? and viceversa ?

A: Actually, it is possible a BMT will start a transaction and then invoke a method of a CMT. As a result, the CMT will not be aware who started the transaction. In contrast, a BMT can only participate in a transaction that it started. It is not possible to propagate a transaction to another BMT EJB.

0
0
0
s2smodern

Related articles available on mastertheboss.com

EJB 3.0 tutorial : Session Beans

Enterprise JavaBeans (EJB) technology is a J2EE technology for de

JBoss MDB 3.0

Message-driven beans (MDBs) are stateless, server-side, transacti

How do you keep your EJB callbacks separated from biz. methods?

JBoss daily recipe

How to set EJB timeout period ?

JBoss recipe of the day

How to add a Selector with MDB 3.0 ?

Message selectors allow an MDB to be more selective about the mes

How to create a MDB 3.0 singleton ?

  EJB3 uses the resource adapter.  When using the resource adapt