Which Types of EJBs Can Use BMT?

An EJB with BMT must be either a session bean or a message-driven bean. Entity beans use only container-managed transaction demarcation. Because the EJB architecture does not support nested transactions, your EJB instance that starts a transaction must complete that transaction before it starts a new transaction. Your transaction is completed when it is either committed or rolled back. The EJB container manages client invocations to an EJB with BMT. When writing code for a client, you invoke a business method via the EJB's home or component interface; the EJB container suspends any transaction that might be associated with the client request. If a transaction is associated with the instance, the container associates the method execution with this transaction. As you learned from Day 16, the EJB container propagates transactions implicitly. That means you don't have to explicitly pass the transaction context as a parameter because the EJB container handles this task for you transparently.

Note

You should keep in mind that clients such as JavaServer Pages (JSPs) and servlets are not designed to be transactional components. Use EJBs to perform transactional work, and then you can invoke such EJBs from either a servlet or a JSP.


In the following sections, you'll learn about the transaction semantics for methods specific to each type of bean using BMT. You'll also learn the restrictions that are imposed when an EJB of a certain type uses bean-managed transactions.

Understanding Transaction Semantics in BMTs

As you learned on Day 17, transaction semantics govern the behavior of transaction processing, which are based on the EJB type and the transaction type. These semantics describe the transaction context at the time a method is invoked, and define whether the EJB can access methods in the UserTransaction interface. EJB applications must be designed with these semantics in mind. For BMT, the transaction semantics differ between stateful session, stateless session, and message-driven beans. For entity beans, transactions are never bean-managed. Entity beans may choose to manage their own persistence mechanism (CMP or BMP), but must leave transaction demarcation to the EJB container.

Session Beans with BMT

Both stateful and stateless session beans can use bean-managed transaction demarcation. In a session bean with BMT, it is a common practice to use either JDBC or JTA transactions. As mentioned earlier, JTA transactions are recommended wherever possible.

You learned in the previous section that you must obtain the transaction context from the EJBContext, which in turn is obtained by the setSessionContext() method of the EJB.

The EJB code starts a transaction using the begin() method of the UserTransaction object. All operations in an EJB execute within the scope of a transaction. The commit() method causes the EJB container to call the transaction manager to complete the transaction. In case of failure, exceptions can be caught and the transaction can be rolled back using the rollback() method of the UserTransaction object.

Stateless Session Bean with BMT

In a stateless session bean with BMT, a business method must commit or roll back a transaction before returning. The EJB container detects the case in which a transaction was started but not completed, rolls back the transaction, and then throws the java.rmi.RemoteException to the client if the client is a remote client, or throws the javax.ejb.EJBException if the client is a local client.

In developing a stateless session bean with BMT, the EJB's deployment descriptor must be specified through a bean-managed demarcation, as follows:

<ejb-jar>
   <enterprise-beans>
      <session>
         ...
         <session-type>Stateless</session-type>
         <transaction-type>Bean</transaction-type>
         ...
      </session>
   </enterprise-beans>
</ejb-jar>

Table 18.3. Transaction Semantics for Stateless Session Beans
MethodCan the Method Access UserTransaction?
create()No
setSessionContext()Yes
ejbCreate()Yes
ejbRemove()Yes
Business methodYes

Only the constructor create() of the stateless session bean is not allowed to access methods on the UserTransaction interface.

Stateful Session Bean with BMT

In a stateful session bean with a JTA transaction, the association between the bean instance and the transaction is retained across multiple client calls. Even if each business method called by the client opens and closes the database connection, the association is retained until the instance completes the transaction. There is no restriction that a business method must commit or roll back a transaction before returning, as in the case of a stateless session bean.

In a stateful session bean with a JDBC transaction, the JDBC connection retains the association between the bean instance and the transaction across multiple calls. If the connection is closed, the association is not retained. A stateful session bean instance may, but is not required to, commit a started transaction before a business method returns. If a transaction has not been completed by the end of a business method, the container retains the association between the transaction and the instance across multiple client calls until the instance eventually completes the transaction.

Caution

Stateful session beans that implement the SessionSynchronization interface cannot use bean-managed transaction demarcation. The reason for such a restriction is that they are in full control of committing the transaction, and thus would create a conflict between the container and the EJB.


In developing a stateful session bean with BMT, the EJB's deployment descriptor must be specified with a bean-managed demarcation, as follows:

<ejb-jar>
   <enterprise-beans>
      <session>
         ...
         <session-type>Stateful</session-type>
         <transaction-type>Bean</transaction-type>
         ...
      </session>
   </enterprise-beans>
</ejb-jar>

In the case of a stateful session bean, it is possible that the business method that started a transaction can complete without committing or rolling back the transaction. In such a case, the container must retain the association between the transaction and the instance across multiple client calls until the instance commits or rolls back the transaction. When the client invokes the next business method, the EJB container must invoke the business method in this transaction context.

The following example illustrates a stateful session bean that retains the transaction context across two data sources, using three client calls, invoked in the order methodA, methodB, and methodC:

public class MySessionEJB implements SessionBean {
   EJBContext ctx;
   DataSource ds1;
   DataSource ds2;
   Connection con1;
   Connection con2;
   methodA(...) {
      Statement stmt;
      InitialContext initCtx = new InitialContext();
      // obtain distributed transaction context
      ut = ctx.getUserTransaction();
      // start transaction explicitly
      ut.begin();
      // do some work using con1 here
      ds1 = (javax.sql.DataSource)
                  initCtx.lookup("java:comp/env/jdbc/myDB1");
      con1 = ds1.getConnection();
      stmt = con1.createStatement();
      stmt.executeUpdate(...);
      // The container retains the transaction associated with the
      // instance to the next client call [which is methodB(...)]
   }
   methodB(...) {
      Statement stmt;
      InitialContext initCtx = new InitialContext();
      // make some work using con2 here...
      ds2 = (javax.sql.DataSource)
             initCtx.lookup("java:comp/env/jdbc/myDB2");
      con2 = ds2.getConnection();
      stmt = con2.createStatement();
      stmt.executeUpdate(...);
      // The container retains the transaction associated with the
      // instance to the next client call [which is methodC(...)].
   }
   methodC(...) {
      Statement stmt;
      // obtain again the same transaction contex
      ut = ctx.getUserTransaction();
      // make some more work using con1 and con2
      stmt = con1.createStatement();
      stmt.executeUpdate(...);
      stmt = con2.createStatement();
      stmt.executeUpdate(...);
      // commit the transaction
      ut.commit();
      // release connections
      con1.close();
      con2.close();
   }
...
}

In this example, the transaction begin() in methodA and the container maintain the transaction context after the EJB returns from the method. The EJB calls commit() to commit the transaction in methodC, where it restores the “same” transaction context from the EJBContext.

Transactions are expensive and use critical resources; therefore, it is recommended that an EJB open and close a database connection in each business method rather than hold the Connection open until the end of the transaction. The following is an example of a stateful session bean that starts a transaction in methodA and commits in methodC:

public class MySessionEJB implements SessionBean {
    EJBContext ctx;
    InitialContext initCtx;
    methodA(...) {
        Statement stmt;
        // obtain distributed transaction context
        ut = ctx.getUserTransaction();
        // start a transaction
        ut.begin();
    }
     methodB(...) {
        DataSource ds;
        Connection con;
        Statement stmt;
        // open connection
        ds = (javax.sql.DataSource)
               initCtx.lookup("java:comp/env/jdbc/myDB");
        con = ds.getConnection();
        // make some updates on con
        stmt = con.createStatement();
        stmt.executeUpdate(...);
        // close the connection
        stmt.close();
        con.close();
    }
    methodC(...) {
        // obtain same distributed transaction context
        ut = ctx.getUserTransaction();
        // commit the transaction
        ut.commit();
    }
...
}

In the preceding example, if the sequence of execution were methodA, methodB, methodB, and methodC, and all the database updates were done by the multiple invocations of methodB, these methods would be performed in the scope of the same transaction with optimum resource usage.

Table 18.4 summarizes the transaction semantics of stateful session beans with bean-managed transactions.

Table 18.4. Transaction Semantics for Stateful Session Beans
MethodCan Access UserTransaction Methods?
create(...)No
setSessionContext()Yes
ejbCreate()Yes
ejbRemove()Yes
ejbActivate()Yes
ejbPassivate()Yes
Business methodYes
afterBegin()N/A
beforeCompletion()N/A
afterCompletion()N/A

Because a stateful session bean with bean-managed transaction cannot implement the SessionSynchronization interface, the methods afterBegin(), beforeBegin(), and afterCompletion() of the SessionSynchronization are not applicable.

Message-Driven Beans with BMT

As you learned on Day 14, “Developing Message-Driven Beans,” there is no direct communication between a client and a message-driven bean, except through a JMS message. Therefore, no client transaction context is available when a message-driven bean is invoked because a distributed transaction context does not flow with a JMS message. When a message-driven bean with BMT uses the UserTransaction interface to specify transactions, the message receipt that causes the onMessage() method of the bean to be invoked is not part of the transaction. A container-managed transaction with the Required transaction attribute must be used if receipt of a message is to be part of a transaction. A message-driven bean instance must commit a transaction before the onMessage() method returns. The EJB container detects the case in which a transaction was started, but not completed, in the onMessage() method, and rolls back the transaction.

Caution

The EJB developer must not send a JMS message followed by synchronous receipt of a reply to that message within a single transaction. Because a JMS message is not delivered to its final destination until the transaction commits, the receipt of the reply within the same transaction will never take place.


The container makes the UserTransaction interface available to the EJB's business method or the onMessage() method via the EJBContext interface and under the environment entry "java:comp/UserTransaction". When an instance uses the UserTransaction interface to demarcate a transaction, the container must enlist all the resource managers used by the instance between the begin() and commit() or rollback() methods with the transaction. When the instance attempts to commit the transaction, the container is responsible for global coordination of committing the transaction.

Caution

In MDB with BMT, the acknowledge() method should not be used within a transaction.


In developing a message-driven bean with BMT, the EJB's deployment descriptor must be specified with a bean-managed demarcation, as follows:

<ejb-jar>
  <enterprise-beans>
    ...
    <message-driven>
      ...
      <transaction-type>Bean</transaction-type>
      ...
    </message-driven>
    ...
  </enterprise-beans>
</ejb-jar>

Table 18.5 describes the transaction semantics for message-driven beans in bean-managed transactions.

Table 18.5. Transaction Semantics for Message-Driven Beans
MethodCan Access UserTransaction Methods?
create()No
setMessageDrivenContext()Yes
ejbCreate()Yes
ejbRemove()Yes
onMessage()Yes
Business methodYes

Handling Exceptions in BMT

EJB must catch and handle specific exceptions thrown during transactions. EJBs can throw either application or system-level exceptions, or both, whenever they encounter errors while handling transactions. Application-level exceptions arise from errors in the business logic. The calling application must handle them. System-level exceptions, such as runtime errors, transcend the application itself and can be handled by the application, the enterprise bean, or the EJB container. An EJB must declare application-level exceptions and system-level exceptions in the throws clauses of its remote interface. You must test for checked exceptions in your client application's try-catch block before calling the bean's methods.

When an instance attempts to start a transaction using the begin() method of the UserTransaction interface while the instance has not committed the previous transaction, the container must throw the javax.transaction.NotSupportedException in the begin() method.

The container must throw the java.lang.IllegalStateException if an instance of a bean with BMT attempts to invoke the setRollbackOnly() or getRollbackOnly() method of the EJBContext interface.

System-Level Exceptions

An EJB throws a system-level exception to indicate an unexpected system-level failure. For example, it throws an exception if it can't open a database connection. System-level exceptions are usually a java.ejb.EJBException if the method is local and a java.rmi.RemoteException is the method is remote.

Note

java.ejb.EJBException is a runtime exception and it isn't required to be listed in the throws clause of the bean's business methods.


System-level exceptions usually require the transaction to be rolled back. Often the container managing the EJB does the rollback. Sometimes the client must roll back the transaction, especially if the transactions are bean-managed.

Application-Level Exceptions

The bean's business methods use application exceptions to report abnormal application conditions, such as unacceptable input values or amounts beyond acceptable limits. These are business logic errors, not system problems. Application-level exceptions are exceptions other than java.ejb.EJBException. For example, a bean method that debits an account balance might throw an application exception to report that the account balance isn't sufficient to permit a particular debit operation. When an application-level exception occurs, the enterprise bean instance doesn't automatically roll back the client's transaction. The client then has the knowledge and the opportunity to evaluate the error message, take the necessary steps to correct the situation, and recover the transaction.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.176.228