Author: Alexander Brown
In CICS TS V5.2 the Liberty JVM server was enhanced to support the Java Transaction API (JTA). JTA enables Java EE Web applications that are running in CICS Liberty to coordinate transactional updates between CICS resources and XA resources. In a typical scenario the CICS resource could be a VSAM file while the XA resource might be a remote DB2 database using JDBC type 4 connectivity. This article shows you how to develop a simple web application using JTA.
For the example in this tutorial, the following minimum prerequisites apply:
- CICS TS V5.2
- A configured Liberty JVM server
The Java Transaction API (JTA) is a high-level interface for
coordinating global transactions using the Java programming language.
This API is implemented by different runtimes, including WebSphere
Liberty. JTA is exposed to application developers through a
UserTransaction; a Java class which provides methods for controlling
transactions.
A Java transaction can be thought of as the Java version of a CICS unit-of-work (UOW); both are controlled by transaction managers and coordinate updates to recoverable resources. However, because the Java runtime environment is not natively transactional, there has to be a beginning and an end to the logical unit of work. Beginning a Java transaction can be thought of as performing a syncpoint. The end of a Java transaction can either be another syncpoint or a rollback, depending on the scenario. CICS is inherently transactional and a UOW is always started at CICS task attach time. The CICS UOW exists whether there is a JTA transaction or not.
In a CICS Liberty JVM server with JTA configured, beginning a Java transaction will create a new subordinate CICS UOW. This UOW is used to control the transactional behaviour of CICS resources such as VSAM files and recoverable TSQs. It also controls updates to CICS RMI resources such as a local DB2 or MQ instance. However, recoverable updates to a remote data source using JDBC type 4 connectivity will be controlled by the Java transaction and the Liberty transaction manager, allowing transactional coordination of both the CICS UOW and the remote data source in the same global transaction, as shown below.
In this example we will look at a Java servlet which writes to a
recoverable CICS temporary storage queue (TSQ) and also accesses a
remote DB2 database using JDBC type 4 connectivity. The TSQ should be
defined as recoverable by using a CICS
TSMODEL
definition that specifies the attributes RECOVERY(YES). A DataSource
must be defined in the Liberty
server
configuration file and support XA by specifying the
java.sql.XADataSource property on the dataSource element. For example:
<dataSource id="db2xa" jndiName="jdbc/db2xa" type="javax.sql.XADataSource">
<jdbcDriver libraryRef="DB2JCC4Lib"/>
<properties.db2.jcc databaseName="SAMPLEDB" serverName="localhost" portNumber="50000"/>
</dataSource>Our sample Java servlet is shown below and illustrates how the UserTransaction interface can be used to coordinate updates to both CICS and a remote DB2 database.
@WebServlet("/JTAServlet")
public class JTAServlet extends HttpServlet
{
@Resource
private UserTransaction transaction;
@Resource("jdbc/mydb")
private DataSource dataSource;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Connection conn = null;
Statement stmt = null;
try
{
transaction.begin();
TSQ tsq = new TSQ();
tsq.setName("RECOVERABLEQ");
tsq.writeString("My data");
conn = dataSource.getConnection();
stmt = conn.createStatement();
stmt.executeUpdate("INSERT INTO schema.tablename(column) DATA('My data')");
transaction.commit();
}
catch(Exception e)
{
try
{
transaction.rollback();
}
catch(Exception tE)
{
// Syncpoint failure, so wrap this exception and throw servlet exception
throw new ServletException(tE);
}
}
finally
{
try
{
stmt.close
}
catch(SQLException e)
{
e.printStackTrace();
}
try
{
conn.close();
}
catch(SQLException e)
{
e.printStackTrace();
}
}
}
}The key steps in the example source code are as follows:
- The
UserTransactionandDataSourceinterfaces are injected as instance variables using the@Resourceannotation to avoid a JNDI lookup of these resources on every request. This works because the transaction context is scoped to the current thread and not the UserTransaction object; so it can be safely used as an instance variable across multiple requests and separate methods. - The JTA transaction scope is started using the
UserTransactioninterface with thetransaction.begin()method, this causes the Liberty transaction manager to create an XA transaction, which is defined by a unique XID, at the same time CICS creates a new UOW, which is mapped to the XA transaction using a UOWLINK. - When a recoverable CICS resource such as a TSQ is updated using the
tsq.writeString()method, then then the updates will be coordinated using the subordinate CICS UOW. - When modifying an external XA capable resource (in this case an SQL call to a remote database using
stmt.executeUpdate()the XID is passed to the resource manager of that resource to identify the transaction. - If the transaction should complete successfully, the Liberty transaction manager drives a commit. In this example the transaction manager must drive a two-phase commit. The Liberty server sends a 'prepare to commit' flow to both CICS and the remote database. Both of these then return a response as to whether they are ready to commit back to Liberty. If both are ready, the Liberty server then tells them to commit and waits for both of them to acknowledge that they have committed before it counts the transaction as complete.
- If a Java exception is thrown then we catch the failure and
invoke the
rollbackmethod on theUserTransaction. This causes the Liberty transaction manager to back-out any changes made within the Java transaction. Liberty sends a rollback command to both CICS and the remote database, which will then undo all their changes and acknowledge that the rollback has occurred. Note: it is generally bad practice to catch the generic Exception type but we do it here for simplicity of the sample.
Note: JDBC 4.1 allows the use of the try-with-resources syntax introduced in Java SE 7 on
ConnectionandStatementand is supported in CICS TS V5.3 via using Java EE 7 via APAR PI63877.
Java EE web applications can be packaged as part of a basic web-based
project (deployed as a WAR file), or as part of an OSGi application
project (deployed as an EBA file). Both WARs and EBAs can be included in
a CICS bundle. In a Liberty JVM server the JTA capability is provided by
default as part of the cicsts:core-1.0 feature.
The Liberty transaction log directory, the tranlog, is used to store
the state of all Java transactions within the Liberty server, the
location of this log defaults to the working directory of the Liberty
JVM server, typically
&USSHOME;/<applid>/<jvmserver>/wlp/usr/serverName/, but can be
configured in the Liberty server configuration file using the XML
element:
<transaction transactionLogDirectory="/var/cics/tranlog/${com.ibm.cics.jvmserver.applid}/${com.ibm.cics.jvmserver.name}"/>Once a Java transaction is active the subordinate CICS UOW and its CICS task can be viewed by inquiring on the UOWLINK, UOW and Task resources using CEMT or CICS Explorer. Beneath the covers, JTA creates an XA transaction which is used to co-ordinate the recoverable work between the different parties. The XA transaction is referenced using a unique XID which is then used by the transaction manager to coordinate updates across all the resource managers in the global transaction. The CICS UOWLINK is used to map the reference between the CICS UOW and the XID and stores a reference to the XID using the Branch Qualifier and Global Transaction Identifier components as shown.
There is an interesting difference between JDBC type 2 connectivity and JDBC type 4 connectivity when using a DB2 database in a CICS system. With JDBC type 2 connectivity connections are handled by CICS using a DB2CONN resource. With JDBC type 4 connectivity there is an independent Java transaction manager. This means when using a JTA transaction which updates both CICS resources and a database, it will depend on the connection type as to whether a one-phase or two-phase commit is issued. If using type 2 connectivity, the JTA transaction only connects to the CICS UOW, therefore only a one-phase commit is necessary. However, with type 4 connectivity, there are two transaction managers involved, so a two-phase commit is required to ensure transactional behavior.
When failures occur within transactions, it is important to know how the application server handles the failures. These failures can take a number of forms -- unchecked exceptions from Java, ABENDs from CICS or even system failure.
In error scenarios, rollback will be performed on all in-flight transactions on that task. Transactions that are in-doubt and controlled by Liberty (through a JTA transaction) have their details written to the transaction log, allowing the transaction to be recovered or backed out as necessary by the recovery manager. In CICS, UOW recovery is treated in the same way as if the UOW was subordinate to another CICS region, in the event of Liberty server failure, they will not recover until the Liberty JVM server has been re-enabled.
In the case of a CICS failure, a CICS emergency restart will recover all non-Liberty related UOWs and re-enable the Liberty JVM server. When this happens, Liberty will read its tranlog and invoke the recovery method for each resource (the XAResource) which was active at the time of failure, sending an XA recovery flow to any remote data source that was used and to the CICS recovery manager. This retrieves all XIDs associated with unfinished transactions and returns them to the Liberty transaction manager, which then manages the commit, forget or rollback using the XA resources as appropriate.
In CICS TS V5.3, there are scenarios where you might want the CICS UOW and JTA transactions to operate independently. An example of this is when using the REQUIRES_NEW EJB transaction attribute to create nested transactions. If the JTA transaction and CICS UOW are integrated at this point, the application will fail because CICS does not support nested UOWs.
To prevent the integration of JTA and CICS UOWs across a particular
Liberty JVM server, add the following element to the Liberty
server.xml configuration file:
<cicsts_jta integration="false"/>This article has shown how JTA can be used and set up on a CICS Liberty JVM server. The following links provide more information on JTA and Java transactions in CICS.
