ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

J2EE Transaction Frameworks: Distributed Transaction Primer
Pages: 1, 2, 3, 4

Transactions in clients: Case I

This is the case where the J2EE configuration is {Stand-alone Client <-> EJB Container <-> RDBMS/EIS Resources}. Transaction support in applets and application clients is not required by the J2EE platform. However, a J2EE product might choose to implement and provide this capability for added value. So the ability of applets and fat standalone application clients to directly access a UserTransaction object depends entirely on the capabilities provided by the container. To ensure portability, applets and application clients should delegate transactional work to the lower tier of enterprise beans.



Transactions in web components: Case II

This is the case where the J2EE configuration is {Browser <-> Web Container <-> RDBMS/EIS Resources}. It is possible for a servlet or a JSP page to use JNDI lookup to get hold of a UserTransaction object and use the underlying interface to programmatically specify transactions. In a two-tier application configuration where a web component needs to access enterprise information systems under the scope of a JTA transaction, this is quite common. The code snippet below illustrates the use of the JTA interface to specify transactions within a web component:

Context myCntxt = new InitialContext();
UserTransaction ut =
(UserTransaction) myCntxt.lookup("java:comp/UserTransaction");
ut.begin();
// perform transactional work here
ut.commit();

It is important to keep in mind that a web component like a servlet may only start a transaction in its service method. Moreover, a transaction started by a servlet or a JSP page must be completed before the service method returns. Transactions cannot span across web requests. The following guidelines are recommended for handling interactions in web components between JTA transactions, threads, and JDBC connections.

  • JTA transactions should start and complete only from the thread in which the service method is called. Additional threads created in the servlet should not attempt to start any JTA transaction.
  • JDBC connections may be acquired and released by a thread other than the service method thread, but should not be shared between threads.
  • JDBC Connection objects should not be stored in static fields.
  • For web components implementing the SingleThreadModel, JDBC Connection objects may be stored in class instance fields.
  • For web components (servlets) not implementing the SingleThreadModel, JDBC Connection objects should not be stored in class instance fields and should be acquired and released within the same invocation of the service method.

Transactions in application servers: Case III

This is the case where the J2EE configuration is {Browser <-> Web Container <-> EJB Container <-> RDBMS/EIS Resources}. The following scenarios are illustrated to motivate discussions on use of transactions in application servers with EJB container and a built in transaction monitor.

Scenario A : Messages sent/received over JMS and multiple databases access:

It's possible for an application using EJB servers to send messages to or receive messages from one or more JMS destinations or update data in one or more databases in a single transaction. In the following figure, a client invokes a method on the remote interface of enterprise Bean A. which in turn sends a message to a JMS queue and updates data in a database A. After that, EJB A calls a method of another enterprise Bean B that updates data in database B. The application server with its EJB container and built in transaction manager ensures that the operations on A, B, and C are either all committed or rolled back.

Diagram of message sent to JMS queue and updates to multiple databases.
Figure 5. Message sent to JMS queue and updates to multiple databases

The application programmer does not have to do anything to ensure transactional semantics. The EJBs A and B perform the sending of the message and database updates using the standard JMS and JDBC APIs. Behind the scenes, the application server enlists the session on the connection to the JMS provider and the database connections as part of the transaction. When the transaction commits, the application server and the messaging and database systems perform a two-phase commit protocol to ensure atomic updates across all the three resources.

Scenario B: Multiple database access via multiple application servers:

The J2EE architecture allows updates of data at multiple sites to be performed in a single transaction. In the following figure, a client invokes a method on enterprise Bean A. which in turn sends a message to a message queue, updates data in database A. After that, EJB A calls a method in another EJB B deployed in another application server which updates data in database B. The EJB architecture makes it possible to perform the updates to databases A and B in a single transaction.

Diagram of updates to multiple databases in same transaction.
Figure 6. Updates to multiple databases in same transaction

When EJB A invokes EJB B, the two application servers cooperate to propagate the transaction context from A to B. This transaction context propagation is transparent to the application. At commit time, the two application servers use distributed two phase commit protocol (if the capability exists) to ensure the atomicity of the database updates and the transaction.

The two types of transaction demarcation in enterprise beans, namely, bean managed and container managed, are discussed in detail next.

Bean managed transaction

As mentioned before, in a bean-managed transaction, an enterprise bean uses the javax.transaction.UserTransaction interface to explicitly specify transaction boundaries in the application code. Only session beans and message driven beans can choose to use bean-managed demarcation. An entity bean must always use container managed transaction demarcation. The following code illustrates the use of JTA interface to specify transactions in an enterprise bean with bean-managed transaction demarcation.

UserTransaction ut = ejbContext.getUserTransaction();
ut.begin();
// Transactional work is done here
ut.commit();

The following example illustrates a business method of a typical session bean that performs a bean managed transaction involving both a database connection and a JMS connection.

public class MySessionEJB implements SessionBean {
EJBContext ejbContext;
public void someMethod(...) {
javax.transaction.UserTransaction ut;
javax.sql.DataSource ds;
java.sql.Connection dcon;
java.sql.Statement stmt;
javax.jms.QueueConnectionFactory qcf;
javax.jms.QueueConnection qcon;
javax.jms.Queue q;
javax.jms.QueueSession qsession;
javax.jms.QueueSender qsender;
javax.jms.Message message;
InitialContext initCtx = new InitialContext();
// obtain db conn object and set it up for transactions
ds = (javax.sql.DataSource)
initCtx.lookup("java:comp/env/jdbc/Database");
dcon = ds.getConnection();
stmt = dcon.createStatement();
// obtain jms conn object and set up session for transactions
qcf = (javax.jms.QueueConnectionFactory)
initCtx.lookup("java:comp/env/jms/qConnFactory");
qcon = qcf.createQueueConnection();
qsession = qcon.createQueueSession(true,0);
q = (javax.jms.Queue)
initCtx.lookup("java:comp/env/jms/jmsQueue");
qsender = qsession.createSender(q);
message = qsession.createTextMessage();
message.setText("some message");
//
// Now do a transaction that involves the two connections.
//
ut = ejbContext.getUserTransaction();
// start the transaction
ut.begin();
// Do database updates and send message. The Container
// automatically enlists dcon and qsession with the
// transaction.
stmt.executeQuery(...);
stmt.executeUpdate(...);
stmt.executeUpdate(...);
qsender.send(message);
// commit the transaction
ut.commit();

// release connections
stmt.close();
qsender.close();
qsession.close();
dcon.close();
qcon.close();
}
...
}

Pages: 1, 2, 3, 4

Next Pagearrow