A new synapse mediator (Transaction Mediator) has been added to support the distributed transactions using Java transaction API(JTA). JTA allows applications to perform a distributed transaction, that is, transactions that access and update data on two or more networked computer resources (an example would be to have two databases or a database and a message queue such as JMS). This mediator can be used to perform a distributed transaction. The synapse configuration has been extended to add explicit transaction markers. This means that you can use the synapse configuration language to define the start, end etc. of your transaction. It is the responsibility of the user to define when to start, commit or rollback the transaction. For example, you can mark the start of a transaction at the start of a database commit, end of the transaction at the end of the database commit and you can mark rollback transaction if a failure occurs.
...
...
style | border:1 |
---|
location | top |
---|
type | flat |
---|
separator | pipe |
---|
|
...
Transaction Mediator Configuration
Code Block |
---|
|
<transaction action="new|use-existing-or-new|fault-if-no-tx|commit|rollback|suspend|resume"/>
|
...
Since the Transaction Mediator is implemented using JTA, you need to have a JTA provider. Here we used JBoss J2EE application server (Application Server (JBoss AS), which implements the transaction support through Arjuna TS) , as the JTA provider, so it is necessary to deploy the WSO2 ESB in JBoss Application server ( AS). Use Apache Derby as the database server.
...
4. We use here a sample similar to #361 sample 361, and the full Synapse configuration is shown below. (you You can directly paste the following configuration into synapse configuration in $ESB_HOME/repository/conf/synapse-config/synapse.xml
). In the "In" sequence, we will send a message to the service and in the "Out" sequence we will delete an entry from the first database and update the second database with that entry. If we try to add an entry, which is already there in the second database, the whole transaction will rollback.
Code Block |
---|
|
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="myFaultHandler">
<log level="custom">
<property name="text" value="** Rollback Transaction**"/>
</log>
<transaction action="rollback"/>
<send/>
</sequence>
<sequence name="main" onError="myFaultHandler">
<in>
<send>
<endpoint>
<address uri="http://localhost:9000/services/SimpleStockQuoteService"/>
</endpoint>
</send>
</in>
<out>
<transaction action="new"/>
<log level="custom">
<property name="text" value="** Reporting to the Database esbdb**"/>
</log>
<dbreport useTransaction="true" xmlns="http://ws.apache.org/ns/synapse">
<connection>
<pool>
<dsName>java:jdbc/XADerbyDS</dsName>
<icClass>org.jnp.interfaces.NamingContextFactory</icClass>
<url>localhost:1099</url>
<user>esb</user>
<password>esb</password>
</pool>
</connection>
<statement>
<sql>delete from company where name =?</sql>
<parameter expression="//m0:return/m1:symbol/child::text()"
xmlns:m0="http://services.samples" xmlns:m1="http://services.samples/xsd"
type="VARCHAR"/>
</statement>
</dbreport>
<log level="custom">
<property name="text" value="** Reporting to the Database esbdb1**"/>
</log>
<dbreport useTransaction="true" xmlns="http://ws.apache.org/ns/synapse">
<connection>
<pool>
<dsName>java:jdbc/XADerbyDS1</dsName>
<icClass>org.jnp.interfaces.NamingContextFactory</icClass>
<url>localhost:1099</url>
<user>esb</user>
<password>esb</password>
</pool>
</connection>
<statement>
<sql>INSERT into company values (?,'c4',?)</sql>
<parameter expression="//m0:return/m1:symbol/child::text()"
xmlns:m1="http://services.samples/xsd" xmlns:m0="http://services.samples"
type="VARCHAR"/>
<parameter expression="//m0:return/m1:last/child::text()"
xmlns:m1="http://services.samples/xsd" xmlns:m0="http://services.samples"
type="DOUBLE"/>
</statement>
</dbreport>
<transaction action="commit"/>
<send/>
</out>
</sequence>
</definitions>
|
...
Info |
---|
|
In the table schema we cannot have the same entry twice. |
Code Block |
---|
|
CREATE table company(name varchar(10) primary key, id varchar(10), price double);
|
...
Database1:
Code Block |
---|
|
INSERT into company values ('IBM','c1',0.0);
INSERT into company values ('SUN','c2',0.0);
|
Database2:
Code Block |
---|
|
INSERT into company values ('SUN','c2',0.0);
INSERT into company values ('MSFT','c3',0.0);
|
...
Datasource1:esb-derby-xa-ds.xml
Code Block |
---|
|
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<xa-datasource>
<jndi-name>jdbc/XADerbyDS</jndi-name>
<isSameRM-override-value>false</isSameRM-override-value>
<xa-datasource-class>org.apache.derby.jdbc.ClientXADataSource</xa-datasource-class>
<xa-datasource-property name="portNumber">1527</xa-datasource-property>
<xa-datasource-property name="DatabaseName">esbdb</xa-datasource-property>
<xa-datasource-property name="User">esb</xa-datasource-property>
<xa-datasource-property name="Password">esb</xa-datasource-property>
<metadata>
<type-mapping>Derby</type-mapping>
</metadata>
</xa-datasource>
</datasources>
|
Datasource2:esb-derby1-xa-ds.xml
Code Block |
---|
|
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<xa-datasource>
<jndi-name>jdbc/XADerbyDS1</jndi-name>
<isSameRM-override-value>false</isSameRM-override-value>
<xa-datasource-class>org.apache.derby.jdbc.ClientXADataSource</xa-datasource-class>
<xa-datasource-property name="portNumber">1527</xa-datasource-property>
<xa-datasource-property name="DatabaseName">esbdb1</xa-datasource-property>
<xa-datasource-property name="User">esb</xa-datasource-property>
<xa-datasource-property name="Password">esb</xa-datasource-property>
<metadata>
<type-mapping>Derby</type-mapping>
</metadata>
</xa-datasource>
</datasources>
|
...
Drop the two datasource declarations above into $JBOSS_HOME/server/default/deploy folder
. Map the above jndi
names: drop the following jboss-web.xml
configuration into $JBOSS_HOME/serer/default/deploy/esb.war/WEB-INF/
.
Code Block |
---|
|
<!DOCTYPE jboss-web PUBLIC
"-//JBoss//DTD Web Application 5.0//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd">
<jboss-web>
<resource-ref>
<res-ref-name>jdbc/XADerbyDS</res-ref-name>
<jndi-name>java:/XADerbyDS</jndi-name>
</resource-ref>
<resource-ref>
<res-ref-name>jdbc/XADerbyDS1</res-ref-name>
<jndi-name>java:/XADerbyDS1</jndi-name>
</resource-ref>
</jboss-web>
|
...
1. To remove the IBM record from the first database and add it to the second database, run the sample with the following options.
Code Block |
---|
ant stockquote -Daddurl=http://localhost:9000/services/SimpleStockQuoteService
-Dtrpurl=http://localhost:8280/ -Dsymbol=IBM
|
...
1. Try to add an entry which is already there in the second database. This time use Symbol SUN
.
Code Block |
---|
ant stockquote -Daddurl=http://localhost:9000/services/SimpleStockQuoteService
-Dtrpurl=http://localhost:8280/ -Dsymbol=SUN
|
2. You will see how the fault sequence is executed and the whole transaction rollback. Check both databases again; there is no record deleted from the first database and no record added into the second database.
Excerpt |
---|
|
Description of transaction mediator in example in WSO2 ESB. |