Full parsing of Java transactions (eight)--Introduction to Distributed Transactions (SPRING+JTA+ATOMIKOS+HIBERNATE+JMS)

Source: Internet
Author: User

In previous articles in this series, we focused on JDBC's handling of local transactions, and this article will cover an example of a distributed transaction.

Please download the GitHub source code in the following ways:

git clone https://github.com/davenkin/jta-atomikos-hibernate-activemq.git

The difference between a local transaction and a distributed transaction is that a local transaction is only used to process a single data source transaction (such as a single database), and a distributed transaction can handle a variety of heterogeneous data sources, such as a business operation that contains both JDBC and JMS or an operation that requires access to multiple different databases.

Java through JTA to complete the distributed transaction, JTA itself is only a specification, different application server contains its own implementation (such as JBOSSJTA), but also has a separate application server independent JTA implementation, such as the Atomikos in this article. For the principle of JTA, this article is not detailed here, the reader can learn the relevant knowledge.

In this article, we will implement one of the following scenarios: You shop online, after placing an order, the order data will be stored in the system's database, and in order to arrange the logistics, the order information will be sent to the Logistics department with a message (messages) for delivery.

The above operations are designed to both database operations and JMS message sending, so that we can only select distributed transactions for the entire operation to be an atomic operation. We first design a service layer that defines the OrderService interface:

Package Davenkin;public interface OrderService {public    void Makeorder (Order order);}

For the sake of simplicity, we design a very simple domain object order:

@XmlRootElement (name = "Order") @XmlAccessorType (Xmlaccesstype.field) public class Order {    @XmlElement (name = "Id", Required = true)    private long ID;    @XmlElement (name = "ItemName", required = true)    private String itemname;    @XmlElement (name = "Price", required = true)    private double price;    @XmlElement (name = "Buyername", required = true)    private String buyername;    @XmlElement (name = "MailAddress", required = true)    private String mailaddress;    Public Order () {    }

In order to use JAXB to marshal and unmarshal order objects, we have added JAXB-related annotation to the Order class. We will use Hibernate to complete the data persistence and then send the order to XML using the spring-provided jmstemplate to TextMessage to the Order.queue in the Logistics department.

(i) Preparing the database

For convenience, we will use the spring-provided embedded database, which by default spring uses Hsql as the back-end database, although in this case we will take Hsql's non-XA datasource, However, you can still participate in distributed transactions after Atomikos packaging.

The SQL script is included in the Createdb.sql file:

CREATE TABLE User_order (ID INT not null,item_name VARCHAR (+) not NULL unique,price DOUBLE not null,buyer_name CHAR (32) Not null,mail_address VARCHAR ($) Not null,primary KEY (ID));

In spring, configure the DataSource as follows:

    <jdbc:embedded-database id= "DataSource" >        <jdbc:script location= "Classpath:createDB.sql"/>    </jdbc:embedded-database>

(ii) Launch of ACTIVEMQ

We will use embedded's activemq to start the brokerservice provided by ACTIVEMQ before the test, and then close brokerservice after the test execution is complete.

  @BeforeClass public    static void Startembeddedactivemq () throws Exception {        broker = new Brokerservice ();        Broker.addconnector ("tcp://localhost:61616");        Broker.start ();    }    @AfterClass public    static void Stopembeddedactivemq () throws Exception {        broker.stop ();    }

(iii) Realization of OrderService

Create a Defaultorderservice class that implements the OrderService interface and maintains a jmstemplate and a hibernate sessionfactory instance variable, Used for message sending and database processing, respectively.

Package Davenkin;import Org.hibernate.sessionfactory;import Org.hibernate.classic.session;import Org.springframework.beans.factory.annotation.required;import Org.springframework.jms.core.jmstemplate;import Org.springframework.transaction.annotation.transactional;public class Defaultorderservice  implements orderservice{    private jmstemplate jmstemplate;    Private Sessionfactory sessionfactory;    @Override    @Transactional public    void Makeorder (order order) {        Session session = Sessionfactory.getcurrentsession ();        Session.save (order);        Jmstemplate.convertandsend (order);    }    @Required public    void Setjmstemplate (Jmstemplate jmstemplate) {        this.jmstemplate = jmstemplate;    }    @Required public    void Setsessionfactory (Sessionfactory sessionfactory) {        this.sessionfactory = sessionfactory;}    }

(iv) Create an order mapping configuration file

 <?xml version= "1.0"? ><! DOCTYPE hibernate-mapping Public "-//hibernate/hibernate mapping DTD 3.0//en" "Http://hibernate.sourceforge.net/hib Ernate-mapping-3.0.dtd ">

(v) Configuring Atomikos transactions

In the spring IOC container, we need to configure the usertransaction and TransactionManager provided by Atomikos and then configure Spring's Jtatransactionmanager:

  <bean id= "Usertransactionservice" class= "COM.ATOMIKOS.ICATCH.CONFIG.USERTRANSACTIONSERVICEIMP" init-method= " Init "destroy-method=" Shutdownforce "> <constructor-arg> <props> <prop k ey= "Com.atomikos.icatch.service" >com.atomikos.icatch.standalone.UserTransactionServiceFactory</prop> & lt;/props> </constructor-arg> </bean> <bean id= "Atomikostransactionmanager" class= "Com.atom Ikos.icatch.jta.UserTransactionManager "init-method=" Init "destroy-method=" Close "depends-on=" Usertransactionservice "> <property name=" Forceshutdown "value=" false "/> </bean> <bean id=" Atomikosusertransaction "class=" com.atomikos.icatch.jta.UserTransactionImp "depends-on=" Usertransactionservice " > <property name= "transactiontimeout" value= "/> </bean> <bean id=" Jtatransactionmanage R "class=" Org.springframework.transaction.jta.JtaTransactionManager "depends-on= "Usertransactionservice" > <property name= "TransactionManager" ref= "Atomikostransactionmanager"/> <property name= "usertransaction" ref= "atomikosusertransaction"/> </bean> <tx:annotation-driv En transaction-manager= "Jtatransactionmanager"/>

(vi) Configuring JMS

For JMS, in order to enable ACTIVEMQ to join the distributed transaction, we need to configure activemqxaconnectionfactory instead of activemqconnectionfactory, and then configure Jmstemplate, It is also necessary to configure Messageconvertor to cross between the order object and the XML.

    <bean id= "Jmsxaconnectionfactory" class= "org.apache.activemq.ActiveMQXAConnectionFactory" > <property n Ame= "Brokerurl" value= "tcp://localhost:61616"/> </bean> <bean id= "amqconnectionfactory" class= "Com.atom Ikos.jms.AtomikosConnectionFactoryBean "init-method=" init "> <property name=" uniqueresourcename "value=" xaact Ivemq "/> <property name=" xaconnectionfactory "ref=" jmsxaconnectionfactory "/> <property name=" p Oolsize "value=" 5 "/> </bean> <bean id=" jmstemplate "class=" Org.springframework.jms.core.JmsTemplate "        ; <property name= "ConnectionFactory" ref= "amqconnectionfactory"/> <property name= "receiveTimeout" value= "200 0 "/> <property name=" defaultdestination "ref=" Orderqueue "/> <property name=" sessionTransacted "  Value= "true"/> <property name= "Messageconverter" ref= "Oxmmessageconverter"/> </bean> <bean Id= "Orderqueue"class= "Org.apache.activemq.command.ActiveMQQueue" > <constructor-arg value= "ORDER. QUEUE "/> </bean> <bean id=" Oxmmessageconverter "class=" Org.springframework.jms.support.converte R.marshallingmessageconverter "> <property name=" marshaller "ref=" Marshaller "/> <property name=" u Nmarshaller "ref=" Marshaller "/> </bean> <oxm:jaxb2-marshaller id=" Marshaller "> <oxm:class-t O-be-bound name= "Davenkin. Order "/> </oxm:jaxb2-marshaller>

(vii) Testing

In the test, we first start activemq by using the method in (b), then call Defaultorderservice, and finally verify the database and queue:

   @Test public    void Makeorder () {        orderservice.makeorder (Createorder ());        JdbcTemplate jdbctemplate = new JdbcTemplate (dataSource);        Assertequals (1, Jdbctemplate.queryforint ("Select COUNT (*) from User_order"));        String dbitemname = Jdbctemplate.queryforobject ("Select Item_name from User_order", string.class);        String messageitemname = (Order) Jmstemplate.receiveandconvert ()). Getitemname ();        Assertequals (Dbitemname, messageitemname);    }    @Test (expected = illegalargumentexception.class) public    void Failtomakeorder ()    {        Orderservice.makeorder (null);        JdbcTemplate jdbctemplate = new JdbcTemplate (dataSource);        Assertequals (0, Jdbctemplate.queryforint ("Select COUNT (*) from User_order"));        Assertnull (Jmstemplate.receiveandconvert ());    }

Full parsing of Java transactions (eight)--Introduction to Distributed Transactions (SPRING+JTA+ATOMIKOS+HIBERNATE+JMS)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.