The Java Transaction API (JTA) allows applications to perform distributed transactions —to access and update systems having multiple transactional resources: databases, message queues, custom resource, or resources accessed from multiple processes, perhaps on multiple hosts, as participants in a single transaction.
The purpose of this article is to provide a high-level overview of Bitronix JTA Transaction Manager with mySQL XA datasource.
Steps involve creating a very basic JTA application using Bitronixs Transaction Manager (BTM) are as follows:
- Step 1 – System Setup: You need to perform predefine set of operations before writing code.
- Make sure you have the latest version of Java installed on your system.
- Install MySQL 5.1 or higher version if you can download MySQL from their web site.
- Download list of JAR files mentioned below:
- btm-2.1.0.jar (essential library for BTM)
- slf4j-api-1.5.10.jar
- slf4j-jdk14-1.5.10.jar
- geronimo-jta_1.1_spec-1.1.1.jar
- mysql-connector-java-5.1.10-bin.jar
- Step 2 – MySQL Setup: The following steps need to be performed in order to run your application:
- Create a database using the given command:
CREATE DATABASE javatest;
- Create a user using the following command:
CREATE USER 'javauser'@'%' IDENTIFIED BY 'javadude';
- Create a
student
table in javatest
database like mentioned below:
CREATE TABLE student
(
roll_number INT,
name VARCHAR(20),
class VARCHAR(5),
section VARCHAR(5)
);
- Step 3 – Setup project: The example I have shown here is developed in Eclipse IDE. Steps required to setup project in Eclipse are pretty straightforward:
- Create a new Java project.
- Add all the downloaded JAR files mentioned above in its classpath.
- Step 4 – Write code: Now as you are done with all these steps, finally you are ready to write code and test the application:
- Create a Java class
BTMWithMySQL
:
package jtatest;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import bitronix.tm.BitronixTransactionManager;
import bitronix.tm.TransactionManagerServices;
import bitronix.tm.resource.jdbc.PoolingDataSource;
public class BTMWithMySQL {
private static final String DATABASE = "javatest";
private static final String USER_NAME = "javauser";
private static final String PASSWORD = "javadude";
private static final String INSERT_QUERY = _
"insert into student(roll_number,name,class,section) _
values (?,?,?,?)";
private static final String SELECT_QUERY = "select * from student";
public static void main(String[] args) {
PoolingDataSource mySQLDS = new PoolingDataSource();
mySQLDS.setClassName_
("com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
mySQLDS.setUniqueName("mySqlBtm");
mySQLDS.setMaxPoolSize(3);
mySQLDS.getDriverProperties().setProperty_
("databaseName", DATABASE);
mySQLDS.init();
BitronixTransactionManager btm = _
TransactionManagerServices.getTransactionManager();
try {
btm.begin();
Connection connection = _
mySQLDS.getConnection(USER_NAME, PASSWORD);
PreparedStatement pstmt = _
connection.prepareStatement(INSERT_QUERY);
for(int index = 1; index <= 5; index++) {
pstmt.setInt(1,index);
pstmt.setString(2, "student_" + index);
pstmt.setString(3, "" + (4 + index));
pstmt.setString(4, "A");
pstmt.executeUpdate();
}
pstmt.close();
connection.close();
btm.commit();
} catch (Exception ex) {
ex.printStackTrace();
try {
btm.rollback();
} catch (Exception e) {
e.printStackTrace();
}
}
try {
btm.begin();
Connection connection = _
mySQLDS.getConnection(USER_NAME, PASSWORD);
PreparedStatement pstmt = _
connection.prepareStatement(SELECT_QUERY);
ResultSet rs = pstmt.executeQuery();
while(rs.next()){
System.out.println("Student: " + _
rs.getInt("roll_number") + " " +_
rs.getString("name") + " " + _
rs.getString("class")
+ " " + rs.getString("section"));
}
rs.close();
pstmt.close();
connection.close();
btm.commit();
}
catch (Exception ex) {
ex.printStackTrace();
try {
btm.rollback();
} catch (Exception e) {
e.printStackTrace();
}
}
mySQLDS.close();
btm.shutdown();
}
}
Here you can see I have used com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
for datasource. But this example is limited to a single database and a single table. By using BitronixTransactionManager
, you can perform similar operations on multiple databases.
Before each insert
or select
operation, you need to begin transaction by invoking btm.begin()
and at the end of it, you commit your transaction by invoking btm.commit()
.
Once you perform all your work, you have to shutdown Bitronix Transaction Manager by calling btm.shutdown()
as cited in the example above.
- Run your code to see how it works.
However, it is a very basic example to Bitronix JTA Transaction, now you are free to explore your own. For more information, you can visit the official Bitronix site at http://www.bitronix.be.
CodeProject