The words written in the front

Recently finally busy finished from the examination of the matter, can have more time to sum up.

I miss the national examination for a long time, listening to the information about the examination on the radio, and feeling the tense atmosphere in the examination room.

Chances like that are getting rarer and rarer.

What is the JTA

Before introducing Atomikos, let’s talk about JTA.

First, JTA is a specification.

The Java Transaction API (JTA: Java Transaction API) and its cousin Java Transaction Service (JTS: Java Transaction Service, which provides the J2EE platform with distributed Transaction capabilities.

In a way, the JTA specification can be thought of as the Java version of the XA specification, abstracting the DTP model interaction interfaces specified in the XA specification into methods in the Java interface and specifying what functions each method should implement.

This connects XA to JTA.

JTA interface specification

The JTA transaction model specifies which components are in a distributed transaction, while the JTA interface specification specifies how these components interact with each other.

It is important to note that these interfaces defined by the JTA specification are not implemented by application developers, but by vendors, depending on the roles they play in the DTP model.

We developers just need to learn how to use it.

The JTA specification is a Java extension package that requires additional JAR package dependencies to be introduced into the application

<dependency> <groupId>javax.transaction</groupId> <artifactId> jTA </artifactId> <version>1.1</version> </dependency>Copy the code

There is very little source code in JTA specification 1.1, as follows:

As you can see, all of these are exceptions except for the interface definitions contained in the red box. Here we only discuss the functions of interfaces defined in the JTA specification:

Javax.transaction.Status: Transaction Status. This interface defines constants that represent transaction Status

Javax.mail. Transaction. Synchronization, Synchronization

Javax.mail. Transaction. The transaction: the transaction

Javax.mail. Transaction. TransactionManager: transaction manager

Javax.mail. Transaction. UserTransaction: used to declare a distributed transaction

Registered javax.mail. Transaction. TransactionSynchronizationRegistry: transaction synchronization

Javax.mail. Transaction. Xa. XAResource: define the RM for TM operation interface

Javax.transaction.xa. Xid: indicates the transaction ID

TM suppliers

Realize the UserTransaction, TransactionManager, Transaction, TransactionSynchronizationRegistry, Synchronization, Xid interfaces, Distributed transactions are implemented by interacting with the XAResource interface.

In addition, TM vendors implement interfaces defined by the JTS specification if they want to support distributed transactions across applications.

Common TM providers include the application Server mentioned earlier, including JBoss, EJB Server, WebLogic, etc., as well as some joTM and Atomikos that provide transaction manager functionality in the form of third-party libraries.

The RM supplier

The XAResource interface needs to be implemented by the resource manager. The XAResource interface defines methods that will be called by TM, such as:

Start method: starts transaction branch

End method: ends the transaction branch

Prepare method: Prepare to submit

Commit method: Commit

Rollback Method: Rollback

Recover method: Lists all transaction branches in PREPARED

Some RM providers may also provide their own implementations of the Xid interface.

A particular interface

In addition, different resource managers have their own specific interfaces to implement:

For example, THE JDBC driver that supports distributed transactions defined in the JDBC2.0 specification needs to be implemented as javax.sql.XAConnection and Javax.sql. XADataSource interfaces

According to the JMS1.0 specification, JMS vendors that support distributed transactions need to implement javax.jms.xaconnection and javax.jms.xasession interfaces

As Application developers in the DTP model, we don’t need to implement any of the interfaces defined in the JTA specification. We just need to use the UserTransaction implementation provided by TM to declare, commit, and roll back a distributed transaction.

The following example illustrates the basic use of the UserTransaction interface: Build a distributed transaction to manipulate data in two different databases, assuming there is a user table in both libraries.

UserTransaction userTransaction= new UserTransaction() { @Override public void begin() throws NotSupportedException, SystemException { } @Override public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException { } @Override public void rollback() throws IllegalStateException, SecurityException, SystemException { } @Override public void setRollbackOnly() throws IllegalStateException, SystemException { } @Override public int getStatus() throws SystemException { return 0; } @Override public void setTransactionTimeout(int i) throws SystemException { } }; Try {// Start a distributed transaction try{userTransaction.begin(); } catch (NotSupportedException e1) { e1.printStackTrace(); } catch (SystemException e1) { e1.printStackTrace(); } // execute transaction branch 1 conn1 = db1.getConnection(); ps1= conn1.prepareStatement("INSERT into user(name,age) VALUES ('tianshouzhi',23)"); ps1.executeUpdate(); // execute transaction branch 2 conn2 = db2.getConnection(); ps2 = conn2.prepareStatement("INSERT into user(name,age) VALUES ('tianshouzhi',23)"); ps2.executeUpdate(); // Commit, a two-phase commit takes place inside this method userTransaction.com MIT (); }catch (Exception e){ try { userTransaction.rollback(); } catch (SystemException ignore) {}}Copy the code

Note that when committing or rolling back a transaction in a distributed transaction, the Commit and rollback methods provided by the Connection interface should no longer be used.

Instead, use the COMMIT and ROLLBACK interfaces of the UserTransaction interface.

In addition, this example is intended only to illustrate how to use the UserTransaction class; in fact, in real development, it is not that complicated.

Some open source distributed transaction solutions work with Spring’s declarative transaction management capabilities, so you can implement distributed transactions with a simple @Transactional annotation.

Atomikos, for example, which we’ll cover below, supports transaction integration with Spring.

Atomikos is introduced

Atomikos is an open source class transaction manager that provides value-added services for the Java platform.

Atomikos TransactionsEssentials is a value-added and open source transaction manager for the Java platform. Here are some features included in this open source release: 1. Full crash/restart recovery

2. Compatible with standard SUN JTA API

3. Nested transactions

4. Provide built-in JDBC adapters for XA and non-XA

Atomikos company

Atomikos’ official website is www.atomikos.com/. Its most famous product is…

TransactionEssentials: Open source, free product

ExtremeTransactions: Business edition, for a fee.

Open source edition Atomikos – TransactionEssentials

TransactionEssentials:

JTA/XA implements Transaction Manager interfaces, such as

UserTransaction implementation is com. Atomikos. Icatch. Jta. UserTransactionImp, users only need to operate this class directly

// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.atomikos.icatch.jta; import com.atomikos.icatch.config.UserTransactionService; import com.atomikos.icatch.config.UserTransactionServiceImp; import com.atomikos.util.SerializableObjectFactory; import java.io.Serializable; import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.Referenceable; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.SystemException; import javax.transaction.TransactionManager; import javax.transaction.UserTransaction; public class UserTransactionImp implements UserTransaction, Serializable, Referenceable { private static final long serialVersionUID = -865418426269785202L; private transient TransactionManager txmgr_; public UserTransactionImp() { } private void checkSetup() { Class var1 = TransactionManagerImp.class; synchronized(TransactionManagerImp.class) { this.txmgr_ = TransactionManagerImp.getTransactionManager(); if (this.txmgr_ == null) { UserTransactionService uts = new UserTransactionServiceImp(); uts.init(); this.txmgr_ = TransactionManagerImp.getTransactionManager(); } } } public void begin() throws NotSupportedException, SystemException { this.checkSetup(); this.txmgr_.begin(); } public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SystemException, IllegalStateException, SecurityException { this.checkSetup(); this.txmgr_.commit(); } public void rollback() throws IllegalStateException, SystemException, SecurityException { this.checkSetup(); this.txmgr_.rollback(); } public void setRollbackOnly() throws IllegalStateException, SystemException { this.checkSetup(); this.txmgr_.setRollbackOnly(); } public int getStatus() throws SystemException { this.checkSetup(); return this.txmgr_.getStatus(); } public void setTransactionTimeout(int seconds) throws SystemException { this.checkSetup(); this.txmgr_.setTransactionTimeout(seconds); } public Reference getReference() throws NamingException { return SerializableObjectFactory.createReference(this); }}Copy the code

TransactionManager implementation is com. Atomikos. Icatch. Jta. UserTransactionManager

// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.atomikos.icatch.jta; import com.atomikos.icatch.config.Configuration; import com.atomikos.util.SerializableObjectFactory; import java.io.Serializable; import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.Referenceable; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.InvalidTransactionException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import javax.transaction.UserTransaction; public class UserTransactionManager implements TransactionManager, Serializable, Referenceable, UserTransaction { private static final long serialVersionUID = -655789038710288096L; private transient TransactionManagerImp tm; private boolean forceShutdown; private boolean startupTransactionService = true; private boolean closed = false; private boolean coreStartedHere; private void checkSetup() throws SystemException { if (! this.closed) { this.initializeTransactionManagerSingleton(); } } private void initializeTransactionManagerSingleton() throws SystemException { this.tm = (TransactionManagerImp)TransactionManagerImp.getTransactionManager(); if (this.tm == null) { if (! this.getStartupTransactionService()) { throw new SystemException("Transaction service not running"); } this.startupTransactionService(); this.tm = (TransactionManagerImp)TransactionManagerImp.getTransactionManager(); } } private void startupTransactionService() { this.coreStartedHere = Configuration.init(); } private void shutdownTransactionService() { if (this.coreStartedHere) { Configuration.shutdown(this.forceShutdown); this.coreStartedHere = false; } } public UserTransactionManager() { } public void setStartupTransactionService(boolean startup) { this.startupTransactionService = startup; } public boolean getStartupTransactionService() { return this.startupTransactionService; } public void init() throws SystemException { this.closed = false; this.checkSetup(); } public void begin() throws NotSupportedException, SystemException { if (this.closed) { throw new SystemException("This UserTransactionManager instance was closed already.  Call init() to reuse if desired."); } else { this.checkSetup(); this.tm.begin(); } } public boolean getForceShutdown() { return this.forceShutdown; } public void setForceShutdown(boolean value) { this.forceShutdown = value; } public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException { if (this.closed) { throw new SystemException("This UserTransactionManager instance was closed already - commit no longer allowed or possible."); } else { this.checkSetup(); this.tm.commit(); } } public int getStatus() throws SystemException { this.checkSetup(); return this.tm.getStatus(); } public Transaction getTransaction() throws SystemException { this.checkSetup(); return this.tm.getTransaction(); } public void resume(Transaction tx) throws InvalidTransactionException, IllegalStateException, SystemException { this.checkSetup(); this.tm.resume(tx); } public void rollback() throws IllegalStateException, SecurityException, SystemException { this.tm.rollback(); } public void setRollbackOnly() throws IllegalStateException, SystemException { this.tm.setRollbackOnly(); } public void setTransactionTimeout(int secs) throws SystemException { this.checkSetup(); this.tm.setTransactionTimeout(secs); } public Transaction suspend() throws SystemException { this.checkSetup(); return this.tm.suspend(); } public Reference getReference() throws NamingException { return SerializableObjectFactory.createReference(this); } public void close() { this.shutdownTransactionService(); this.closed = true; }}Copy the code

The Transaction implementation is com. Atomikos. Icatch. Jta. TransactionImpl

2. Provide a layer of encapsulation for database connection pools that implement the XADataSource interface as specified in the JDBC specification and MQ clients that implement the JMS specification.

In the JTA specification, interfaces such as XADataSource and XAConnection should be implemented by resource manager RM,

Atomikos functions as a transaction manager (TM) and does not need to provide an implementation.

Atomikos wraps XADataSource just to facilitate integration with the transaction manager.

The implementation class that encapsulates XADataSource is AtomikosDataSourceBean. Typical XADataSource implementations include:

1, mysql official com. Mysql. JDBC. Jdbc2. Optional. The MysqlXADataSource 2, alibaba open-source druid connection pool, The corresponding implementation classes for the com. Alibaba. Druid. Pool. Xa. DruidXADataSource 3, tomcat - org provided by the JDBC connection pool.. Apache tomcat. JDBC. Pool. An XADataSource Other common database connection pools, such as DBCP, DBCP2, or C3P0, do not currently appear to provide an implementation of the XADataSource interface. If AtomikosDataSourceBean is provided with a data source that does not implement the XADataSource interface, such as c3P0's ComboPooledDataSource, it will throw an exception like the following:Copy the code
com.atomikos.jdbc.AtomikosSQLException: The class 'com.mchange.v2.c3p0.ComboPooledDataSource'
 specified by property 'xaDataSourceClassName' does not implement the required interface  
 javax.jdbc.XADataSource.  
 Please make sure the spelling is correct, and check your JDBC driver vendor's documentation.
Copy the code

ExtremeTransactions provides the following additional features on top of TransactionEssentials:

TCC support: This is a flexible transaction

Supports transaction propagation through RMI, IIOP, SOAP and other remote procedure call technologies.

This article focuses on TransactionEssentials, the open source version of Atomikos’s transaction manager implementation, including:

1. Use TransactionEssentials’ API directly

2. TransactionEssentials integration with Spring and MyBatis

3, Atomikos configuration details

Use TransactionEssentials’ API directly

Introduce the following dependencies in the MAVEN project poM file:

< the dependency > < groupId > com. Atomikos < / groupId > < artifactId > the transactions - JDBC < / artifactId > < version > 4.0.6 < / version > </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> The < version > 5.1.39 < / version > < / dependency >Copy the code

Create a mysql database table

Note that XA transactions are only supported by the InnoDB engine in mysql, where the database engine is explicitly specified as InnoDB.

Create database db_user; create database db_user; Create table db_user.user(id int AUTO_INCREMENT PRIMARY KEY,name varchar(50)) engine=innodb; Create database db_account; create database db_account; Create table db_account. Account (user_id int,money double) engine=innodb; Also, in this case, the db_User and db_Account libraries are in the same mysql instance.Copy the code

1. Case code

After using the transaction manager, we provided by atomikos UserTransaction interface implementation class com. Atomikos. Icatch. Jta. UserTransactionImp to turn on, commit and rollback transaction.

Instead of using setAutoCommit(false) in java.sql.Connection to start transactions. Other interfaces defined in the JTA specification do not need to be used directly by developers.

import com.atomikos.icatch.jta.UserTransactionImp; import com.atomikos.jdbc.AtomikosDataSourceBean; import javax.transaction.SystemException; import javax.transaction.UserTransaction; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.Properties; public class AtomikosExample { private static AtomikosDataSourceBean createAtomikosDataSourceBean(String dbName) { // Properties p = new Properties(); p.setProperty("url", "jdbc:mysql://localhost:3306/" + dbName); p.setProperty("user", "root"); p.setProperty("password", "your password"); / / use AtomikosDataSourceBean encapsulation com. Mysql. JDBC. Jdbc2. Optional. The MysqlXADataSource AtomikosDataSourceBean ds = new AtomikosDataSourceBean(); // Atomikos requires the name of each AtomikosDataSourceBean, which is set to the same as dbName for easy memorization. ds.setXaDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"); ds.setXaProperties(p); return ds; } public static void main(String[] args) { AtomikosDataSourceBean ds1 = createAtomikosDataSourceBean("db_user"); AtomikosDataSourceBean ds2 = createAtomikosDataSourceBean("db_account"); Connection conn1 = null; Connection conn2 = null; PreparedStatement ps1 = null; PreparedStatement ps2 = null; UserTransaction userTransaction = new UserTransactionImp(); Try {// start the transaction userTransaction.begin(); SQL conn1 = ds1.getConnection(); ps1 = conn1.prepareStatement("INSERT into user(name) VALUES (?) ", Statement.RETURN_GENERATED_KEYS); ps1.setString(1, "tianshouzhi"); ps1.executeUpdate(); ResultSet generatedKeys = ps1.getGeneratedKeys(); int userId = -1; while (generatedKeys.next()) { userId = generatedKeys.getInt(1); // int I =1/0; // int I =1/0; // execute SQL conn2 = ds2.getConnection() on DB2; ps2 = conn2.prepareStatement("INSERT into account(user_id,money) VALUES (? ,?) "); ps2.setInt(1, userId); ps2.setDouble(2, 10000000); ps2.executeUpdate(); // Two-stage submission userTransaction.com MIT (); } catch (Exception e) { try { e.printStackTrace(); userTransaction.rollback(); } catch (SystemException e1) { e1.printStackTrace(); } } finally { try { ps1.close(); ps2.close(); conn1.close(); conn2.close(); ds1.close(); ds2.close(); } catch (Exception ignore) { } } } }Copy the code

2.TransactionEssentials integration with Spring and Mybatis

1. Add the following dependencies to the POM

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> < version > 4.3.7. RELEASE < / version > < / dependency > < the dependency > < groupId > org. Springframework < / groupId > < artifactId > spring - the context < / artifactId > < version > 4.3.7. RELEASE < / version > < / dependency > < the dependency > Mybatis </groupId> <artifactId>mybatis</artifactId> <version>3.4.1</version> </dependency> <dependency> < the groupId > org. Mybatis < / groupId > < artifactId > mybatis - spring < / artifactId > < version > 1.3.1 < / version > < / dependency >Copy the code

2. Create a User entity

package com.tianshouzhi.atomikos;
public class User {
   private int id;
   private String name;
   // setters and getters
}
Copy the code

3. Create an Account instance

package com.tianshouzhi.atomikos;
public class Account {
   private int userId;
   private double money;
   // setters and getters
}
Copy the code

4. Create a UserMapper interface

For convenience, myBatis annotation method is used here, no mapping file is written, the function is the same

package com.tianshouzhi.atomikos.mappers.db_user;
import org.apache.ibatis.annotations.Insert;
import com.tianshouzhi.atomikos.User;
import org.apache.ibatis.annotations.Options;
public interface UserMapper {
   @Insert("INSERT INTO user(id,name) VALUES(#{id},#{name})")
   @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
   public void insert(User user);
}
Copy the code

5. Create the AccountMapper interface

package com.tianshouzhi.atomikos.mappers.ds_account;
import com.tianshouzhi.atomikos.Account;
import org.apache.ibatis.annotations.Insert;
public interface AccountMapper {
    @Insert("INSERT INTO account(user_id,money) VALUES(#{userId},#{money})")
    public void insert(Account account);
}
Copy the code

6. Create a bean that uses JTA transactions

Note that you can still use Spring’s declarative transaction management when using JTA transactions

package com.tianshouzhi.atomikos; import com.tianshouzhi.atomikos.mappers.db_user.UserMapper; import com.tianshouzhi.atomikos.mappers.ds_account.AccountMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; public class JTAService { @Autowired private UserMapper userMapper; Db_user library @autowired Private AccountMapper AccountMapper; @transactional public void insert() {User User = new User(); user.setName("wangxiaoxiao"); userMapper.insert(user); // int i = 1 / 0; Db_user = new Account(); account.setUserId(user.getId()); account.setMoney(123456789); accountMapper.insert(account); }}Copy the code

7. Compile the configuration file spring-atomikos.xml

<? The XML version = "1.0" encoding = "utf-8"? > <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <! - = = = = = = = = = = in view of the two libraries, each configuration a AtomikosDataSourceBean, underlying all use MysqlXADataSource = = = = = = = = = = = = = = = = = = = = = -- -- > <! - configuration data source db_user - > < bean id = "db_user" class = "com. Atomikos. JDBC. AtomikosDataSourceBean" init - method = "init" destroy-method="close"> <property name="uniqueResourceName" value="ds1" /> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /> <property name="xaProperties"> <props> <prop key="url">jdbc:mysql://localhost:3306/db_user</prop> <prop key="user">root</prop> <prop key="password">shxx12151022</prop> </props> </property> </bean> <! - configuration data source db_account - > < bean id = "db_account" class = "com. Atomikos. JDBC. AtomikosDataSourceBean" init - method = "init" destroy-method="close"> <property name="uniqueResourceName" value="ds2" /> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /> <property name="xaProperties"> <props> <prop key="url">jdbc:mysql://localhost:3306/db_account</prop> <prop key="user">root</prop> <prop key="password">shxx12151022</prop> </props> </property> </bean> <! --============= For two data sources, Each configuration a SqlSessionFactoryBean = = = = = = = = = = = = -- -- > < bean id = "ssf_user" class = "org. Mybatis. Spring. SqlSessionFactoryBean" > <property name="dataSource" ref="db_user" /> </bean> <bean id="ssf_account" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="db_account" /> </bean> <! --============= For two SQlsessionFactoryBeans, Each configuration a MapperScannerConfigurer = = = = = = = = = = = = -- -- > < bean class = "org. Mybatis. Spring. Mapper. MapperScannerConfigurer" > < property name="sqlSessionFactoryBeanName" value="ssf_user"/> <! - specifies com. Tianshouzhi. Atomikos. Mappers. Db_user UserMapper interface under the package using ssf_user access to the underlying database connections - > < property name = "basePackage" value="com.tianshouzhi.atomikos.mappers.db_user"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="ssf_account"/> <! - specifies com. Tianshouzhi. Atomikos. Mappers. Ds_account AccountMapper interface under the package using ssf_account access to the underlying database connections - > < property name = "basePackage" value="com.tianshouzhi.atomikos.mappers.ds_account"/> </bean> <! - = = = = = = = = = = = = = = = = configuration atomikos transaction manager = = = = = = = = = = = = = = = = = = = = = = = = -- -- > < bean id = "atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <property name="forceShutdown" value="false"/> </bean> <! --============ Configure spring JtaTransactionManager, The underlying delegate atomikos processing = = = = = = = = = = = = = = = -- -- > < bean id = "jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager" ref="atomikosTransactionManager"/> </bean> <! <tx:annotation-driven Transaction-Manager ="jtaTransactionManager"/> <bean id="jtaService" class="com.tianshouzhi.atomikos.JTAService"/> </beans>Copy the code

8. Test code

package com.tianshouzhi.atomikos; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AtomikosSpringMybatisExample { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring-atomikos.xml"); JTAService jtaService = context.getBean("jtaService", JTAService.class); jtaService.insert(); }}Copy the code

Mysql > insert a record into db_user’s account table and db_account’s account table. Mysql > insert a record into db_user’s account table. Mysql > insert a record into db_user’s account table.

When we open the annotation of the exception simulation in JTAService, we will find that there are no new databases inserted in either library after the exception, indicating that the JTA transaction manager we use does guarantee data consistency.

3. Atomikos configuration

After mastering the basic use of Atomikos, we will introduce the configuration of Atomikos briefly.

By default, Atomikos reads configuration files from the following locations after startup. The Atomikos source code is directly posted here for explanation:

Com. Atomikos. Icatch. Provider. Imp. AssemblerImp# initializeProperties method defines the configuration in the loading sequence logic:

@override public ConfigProperties initializeProperties() {// Read the default configuration transactions-defaults.properties under classpath Properties defaults = new Properties(); loadPropertiesFromClasspath(defaults, DEFAULT_PROPERTIES_FILE_NAME); // Read the classpath, transactions.properties configuration, Override the value of the same key in transactions-defaults.properties transactionsProperties = new Properties(defaults); loadPropertiesFromClasspath(transactionsProperties, TRANSACTIONS_PROPERTIES_FILE_NAME); Classpath, jta.properties, Overrides the value of the same key in transactions-defaults.properties and transactions.properties Properties(transactionsProperties); loadPropertiesFromClasspath(jtaProperties, JTA_PROPERTIES_FILE_NAME); / / read through the Java - Dcom. Atomikos. Icatch. The custom configuration file path of the specified file way, CustomProperties = New Properties(jtaProperties); loadPropertiesFromCustomFilePath(customProperties); FinalProperties = new Properties(customProperties); finalProperties = new Properties(customProperties); return new ConfigProperties(finalProperties); }Copy the code

Configuration file priority: transactions.properties< transactions.properties<jta.

Transactions-defaults. properties is the default configuration of Atomikos and is located in transactions-xxx.jar.

Notice The default configuration may be different for different versions. In particular, the differences between 3.x and 4.x versions are obvious.

The configuration in 4.0.6 is as follows: transactions-default.properties

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = the transaction manager (TM) configuration parameter = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # specifies whether the boot disk log, the default is true. Make sure it is true in production, Com or data integrity cannot be guaranteed. Atomikos. Icatch. Enable_logging = true # JTA/XA resource should be registered automatically Com. Atomikos. Icatch. Automatic_resource_registration = true # JTA transaction, the default timeout time, . The default value is 10000 ms com atomikos. Icatch. Default_jta_timeout = 10000 # affairs maximum timeout time, default is 300000 ms. It said the transaction timeout by UserTransaction. SetTransactionTimeout () is a decision. After 4.x, 0 means no timeout com.atomikos.icatch.max_timeout=300000 # Specifies whether to use different threads (meaning parallel) during two-phase commit. The default is false for versions 3.7 and true for earlier versions. If false, the commits are made in the order in which the resources are accessed in the transaction. . Com. Atomikos. Icatch threaded_2pc = false # specify up to the number of transactions can be run at the same time, the default value is 50, negative said there is no limit to the number. When the userTransaction.begin () method is called, a "Max number of active Transactions reached" exception message may be thrown, Com.atomikos.icatch.max_actives =50 . The default is true com. Atomikos. Icatch allow_subtransactions = true # specify where possible, you should join the son affairs (subtransactions), the default value is true. If set to false, for different subtransactions that are associated, Won't call XAResource. Start (TM_JOIN) com. Atomikos. Icatch. Serial_jta_transactions = true # specify whether the JVM closing force (force) to close the transaction manager, . The default is false com. Atomikos. Icatch force_shutdown_on_vm_exit = false # in a normally closed (no force), should wait for transaction execution time to do it, The default is Long. MAX_VALUE com. Atomikos. Icatch. Default_max_wait_time_on_shutdown = 9223372036854775807 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Transaction log (Transaction logs) = = = = = = = record configuration = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # transaction log directory, by default. /. Com.atomikos.icatch.log_base_dir =./ # Transaction log file prefix, default to TMlog. Transaction logs are stored in files with a numeric suffix and log files with a.log extension, such as TMLog1.log. When a checkpoint is reached, a new transaction log file is created and the number increases. Com.atomikos.icatch.log_base_name =tmlog # . Default is 500 com. Atomikos. Icatch checkpoint_interval = 500 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = transaction log Recovery (Recovery) configuration = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # specifies how long it takes to clear your un-recoverable transaction log, The default 86400000 ms com. Atomikos. Icatch. Forget_orphaned_log_entries_delay = 86400000 # specifies the delay time between scan twice. The default value is with com. Atomikos. Icatch. Default_jta_timeout are the same Com. Atomikos. Icatch. Recovery_delay = ${com. Atomikos. Icatch. Default_jta_timeout} # submit failure, before throwing an exception, most can retry several times, The default value is 5. Com.atomikos.icatch.oltp_max_retries =5 The default 10000 s com. Atomikos. Icatch. Oltp_retry_interval = 10000 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = other = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = java.naming.factory.initial=com.sun.jndi.rmi.registry.RegistryContextFactory com.atomikos.icatch.client_demarcation=false java.naming.provider.url=rmi://localhost:1099 com.atomikos.icatch.rmi_export_class=none com.atomikos.icatch.trust_client_tm=falseCopy the code

When we want to change the default configuration, we can create a new jta.properties under classpath and override the same configuration item.

The difference between different versions of configuration, please refer to the official document: www.atomikos.com/Documentati…

4. Print logs

After the 4.x release, slf4J is preferred, log4j if not, and JUL if not.

See also: www.atomikos.com/Documentati…

Transactions log is configured to print the work log. Transactions log is configured to print the work log.

The words in the back

Mountains and rivers far wide, human fireworks.

No one is you, no one is not you.

reference

Moriji Tian JAVA Technology blog