JTA/JDBC coordination using WebSphere MQ base Java

WebSphere MQ base Java supports the MQQueueManager.begin() method, which allows WebSphere(R) MQ to act as a coordinator for a database which provides a JDBC type 2 compliant driver. Currently this support is available on AIX, HP-UX, Solaris, and Windows with DB2(R) or Oracle databases.

Configuring JTA/JDBC coordination

In order to use the XA-JTA support, you must use the special JTA switch library. The method for using this library varies depending on whether you are using Windows or one of the other platforms.

Configuring on Windows

On Windows systems, the new XA library is supplied as a complete DLL. The name of this DLL is jdbcxxx.dll where xxx indicates the database for which the switch library has been compiled. This library is in the Java\lib\jdbc directory of your WebSphere MQ base Java installation.

Configuring on the other platforms

For each database management system, WebSphere MQ provides two object files. You must link one object file to create a 32-bit switch library, and link the other object file to create a 64-bit switch library. For DB2, the name of each object file is jdbcdb2.o and, for Oracle, the name of each object file is jdbcora.o.

You must link each object file using the appropriate makefile supplied with WebSphere MQ. A switch library requires other libraries, which might be stored in different locations on different systems. However, a switch library cannot use the library path environment variable to locate these libraries because the switch library is loaded by the queue manager, which runs in a setuid environment. The supplied makefile therefore ensures that a switch library contains the fully qualified path names of these libraries.

To create a switch library, enter a make command with the following format. To create a 32-bit switch library, enter the command in the /java/lib/jdbc directory of your WebSphere MQ installation. To create a 64-bit switch library, enter the command in the /java/lib64/jdbc directory.

make JAVA_HOME=JDK_path DBMS

The meanings of the parameters on the make command are as follows:

JAVA_HOME=JDK_path
The fully qualified path name of the directory where you have installed your JDK.

To create a 32-bit switch library on AIX, the JDK must be a 32-bit JDK. On HP-UX or Solaris, you can use a 64-bit JDK because a 64-bit JDK contains the 32-bit libraries.

To create a 64-bit switch library on AIX, HP_UX, or Solaris, the JDK must be a 64-bit JDK.

DBMS
The database management system for which you are creating the switch library. The valid values are db2 for DB2 and oracle for Oracle.

Here is an example of a make command:

make JAVA_HOME=/usr/my_jdk142 db2

Note the following points:

After you have created the switch libraries for DB2, Oracle, or both, you must declare them to your queue manager. If the queue manager configuration file (qm.ini) already contains XAResourceManger stanzas for DB2 or Oracle databases, you must replace the SwitchFile entry in each stanza by one of the following:

For a DB2 database
SwitchFile=jdbcdb2
For an Oracle database
SwitchFile=jdbcora

Do not specify the fully qualified path name of either the 32-bit or 64-bit switch library. Specify only the name of the library.

If the queue manager configuration file does not already contain XAResourceManager stanzas for DB2 or Oracle databases, or if you want to add additional XAResourceManager stanzas, see the WebSphere MQ System Administration Guide for information about how to construct an XAResourceManager stanza. However, each SwitchFile entry in a new XAResourceManger stanza must be exactly as described previously for a DB2 or Oracle database.

After you have updated the queue manager configuration file, and made sure that all appropriate database environment variables have been set, you can restart the queue manager.

Using JTA/JDBC coordination

The basic sequence of API calls for a user application is:

  qMgr = new MQQueueManager("QM1")
  Connection con = qMgr.getJDBCConnection( xads );
  qMgr.begin()

 < Perform MQ and DB operations to be grouped in a unit of work >

  qMgr.commit() or qMgr.backout();
  con.close()
  qMgr.disconnect()

xads in the getJDBCConnection call is a database-specific implementation of the XADataSource interface, which defines the details of the database to connect to. See the documentation for your database to determine how to create an appropriate XADataSource object to pass into getJDBCConnection.

You also need to update your CLASSPATH with the appropriate database-specific jar files for performing JDBC work.

If you need to connect to multiple databases, you might have to call getJDBCConnection several times to perform the transaction across several different connections.

There are two forms of the getJDBCConnection, reflecting the two forms of XADataSource.getXAConnection:

  public java.sql.Connection getJDBCConnection(javax.sql.XADataSource xads)
    throws MQException, SQLException, Exception

  public java.sql.Connection getJDBCConnection(XADataSource dataSource,
                                            String userid, String password)
    throws MQException, SQLException, Exception

These methods declare Exception in their throws clauses to avoid problems with the JVM verifier for customers who are not using the JTA functionality. The actual exception thrown is javax.transaction.xa.XAException. which requires the jta.jar file to be added to the classpath for programs that did not previously require it.

To use the JTA/JDBC support, you must include the following statement in your application:

MQEnvironment.properties.put(MQC.THREAD_AFFINITY, new Boolean(true)); 

Known problems and limitations

Because this support makes calls to JDBC drivers, the implementation of those JDBC drivers can have significant impact on the system behavior. In particular, tested JDBC drivers behave differently when the database is shut down while an application is running. Always avoid abruptly shutting down a database while there are applications holding open connections to it.

DB2
Sometimes DB2 returns a SQL0805N error. This problem can be resolved with the following CLP command:
  DB2 bind @db2cli.lst blocking all grant public
Refer to the DB2 documentation for more information.
Oracle 8.1.7
Calling the JDBC Connection.close() method after MQQueueManager.disconnect() generates an SQLException. Either call Connection.close() before MQQueueManager.disconnect(), or omit the call to Connection.close().
HP-UX and JDK 1.4.2
On HP-UX, you can use only the HP-UX SDK for the Java 2 Platform, Version 1.3.1 to develop and run applications that use the JTA/JDBC support. Version 1.4.2 is not supported.
HP-UX, Solaris, and multiple XAResourceManager stanzas
On HP-UX or Solaris, more than one XAResourceManager stanza in a queue manager configuration file (qm.ini) is not supported.
Solaris and JDK 1.3
When running on Solaris with JDK 1.3, attempting to start the queue manager from a user ID other than root or mqm is likely to fail to load the jdbcora switch file with the following message being put to the error log:
AMQ6175: The system could not dynamically load the library /opt/mqm/java/lib/jdbcora.
The error message was ld.so.1: amqzxma0: fatal: libverify.so: open failed:
No such file or directory. The Queue Manager will continue without this module.

The problem arises because of a dependency between two libraries in JDK 1.3 that cannot be resolved by the dynamic linker when the invoking program has the setuid bit set (as strmqm does).

Under these circumstances, start the queue manager from the mqm user ID; if this is not practical, make a symbolic link for libverify into /usr/lib. For example:

  ln -s /usr/j2se/jre/lib/sparc/libverify.so /usr/lib/libverify.so
Windows systems

The JDBC libraries supplied with WebSphere MQ Java (jdbcdb2.dll and jdbcora.dll) have a dependency on jvm.dll, which is supplied with the JVM. However, depending on the JVM used, this DLL might be in a subdirectory that is not on the path; for example, jre/bin/classic/jvm.dll.

If jvm.dll cannot be found when the queue manager starts, the queue manager produces a message like the following (this example is for DB2):

AMQ6174: The library C:\Program Files\IBM\MQSeries\Java\lib\jdbc\jdbcdb2.dll
was not found. The queue manager will continue without this module.

In fact, the file not found is jvm.dll. The solution is to update the path to include the location of jvm.dll.