A new synapse mediator (Transaction Mediator) has been added to support the The Transaction mediator supports distributed transactionsusing Java transaction API (JTA). JTA allows applications to perform a distributed transaction, that is, transactions that Distributed transactions 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 You can use the synapse Synapse configuration language to define the start , and end etc. of your transaction, pause transactions, and more. It is the responsibility of the user to define when to start, commit, or rollback roll back 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 a transaction for rollback transaction if a failure occurs.
...
Table of Contents | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Transaction Mediator
...
<transaction action="new|use-existing-or-new|fault-if-no-tx|commit|rollback|suspend|resume"/>
The action
attribute has the following meanings:
Value | Meaning |
---|---|
new | Creates a new JTA transaction. Generates an error if a transaction already exist. |
use-existing-or-new | Creates a new JTA transaction. Does nothing if a transaction exist. |
fault-if-no-tx | Generates an error if no transaction exist. Does nothing if a transaction exist. |
commit | Commits transaction. Generates an error if no transaction exist. |
rollback | Rollback transaction. Generates an error if no transaction exist. |
suspend | Suspends transaction. Generates an error if no transaction exist. |
resume | Resumes transaction. Generates an error if no transaction exist. |
Info | ||
---|---|---|
| ||
To use the Transaction Mediator, you need to have a JTA provider in your environment, for example, JBoss. |
Transaction Mediator Scenario
Use the following scenario to show how the Transaction Mediator works. Assume we have a record in one database and we want to delete that record from the first database and add it to the second database (these two databases can be run on the same server or they can be in two remote servers). The database tables are defined in such a way that the same entry cannot be added twice. So, in the successful scenario, the record will be deleted from the first table (of the first database) and will be added to the second table (of the second database). In a failure scenario (the record is already in the second database), no record will be deleted from first table and no record will be added into the second database.
System Requirements
Info | ||
---|---|---|
| ||
This scenario applies to version 3.0. In versions after, there is a Transaction Manager in Carbon itself, so you don't have to put the ESB in an application server to get it working. |
- Windows, Linux or Solaris operating systems.
- WSO2 ESB 3.0.1.
- JBoss Application Server (jboss-5.1.0.GA version used).
- Derby Database (db-derby-10.5.1.1-bin version was used).
- Apache ActiveMQ 5.3.1.
Since the Transaction Mediator is implemented using JTA, you need to have a JTA provider. Here we used JBoss Application Server (JBoss AS), which implements the transaction support through Arjuna TS, as the JTA provider, so it is necessary to deploy WSO2 ESB in JBoss AS. Use Apache Derby as the database server.
Info | ||
---|---|---|
| ||
JBoss server and the Derby database server have the characteristics mentioned above. |
Running the Example
1. Unzip the WSO2 ESB distribution to a place of your choice. And then remove the geronimo-jta_1.1_spec-1.1.0.wso2v1.jar
( This JAR file can be found in $ESB_HOME/repository/components/plugins
).
Info | ||
---|---|---|
| ||
The reason is that the implementation of |
2. Deploy the WSO2 ESB on JBoss AS. The JBoss installation path will be referred to as $JBOSS_HOME
and the WSO2 ESB repo location as $CARBON_HOME
.
3. Drop the derby client JARs (derby.jar
, derbynet.jar
and derbyclient.jar
) into $CARBON_HOME/repository/components/lib
folder and also into $JBOSS_HOME/server/default/lib
(here is used the default JBoss configuration) folder.
4. We use here a sample similar to sample 361, and the full Synapse configuration is shown below. (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.
...
Scenario
Use the following scenario to see how the transaction mediator works. Assume we have a record in one database and we want to delete that record from the first database and add it to the second database (these two databases can be run on the same server or they can be in two remote servers). The database tables are defined in such a way that the same entry cannot be added twice. So, in the successful scenario, the record will be deleted from the first table (of the first database) and will be added to the second table (of the second database). In a failure scenario (the record is already in the second database), no record will be deleted from first table and no record will be added into the second database.
...
System Requirements
Info | ||
---|---|---|
| ||
This scenario applies to version 3.0. In versions after, there is a Transaction Manager in Carbon itself, so you don't have to put the ESB in an application server to get it working. |
- Windows, Linux or Solaris operating systems with WSO2 ESB installed.
- Derby Database (db-derby-10.5.1.1-bin version was used).
- Apache ActiveMQ 5.3.1.
...
Running the Example
- Copy the Derby client JARs (
derby.jar
,derbynet.jar
, andderbyclient.jar
) from$DERBY_HOME/lib
into<ESB_HOME>/repository/components/lib
. Copy and paste the following configuration into the Synapse configuration in
$ESB_HOME/repository/conf/synapse-config/synapse.xml
.
We use here a sample similar to sample 361. 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 that is already in the second database, the whole transaction will roll back.Code Block XML XML <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()"
...
...
5. To run the sample, you need two distributed Derby databases ("esbdb" and "esbdb1"). Refer here for details to set up the databases. The database table was created using the following SQL query.
Info | ||
---|---|---|
| ||
In the table schema we cannot have the same entry twice. |
...
CREATE table company(name varchar(10) primary key, id varchar(10), price double);
Add few records to the two tables:
Database1:
...
INSERT into company values ('IBM','c1',0.0);
INSERT into company values ('SUN','c2',0.0);
Database2:
...
INSERT into company values ('SUN','c2',0.0);
INSERT into company values ('MSFT','c3',0.0);
Info | ||
---|---|---|
| ||
The order of the record matters. |
6. Create two data source declarations for JBoss AS for the two distributed databases.
Datasource1:esb-derby-xa-ds.xml
...
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>
To run the sample, you need two distributed Derby databases ("esbdb" and "esbdb1"); see Setting up with Derby for details on setting up the databases. The database table was created using the following SQL query. Note that in the table schema, you cannot have the same entry twice.
Code Block SQL SQL CREATE table company(name varchar(10) primary key, id varchar(10), price double);
Add a few records to the two tables as follows (the order of the records matters):
Database1:Code Block SQL SQL INSERT into company values ('IBM','c1',0.0); INSERT into company values ('SUN','c2',0.0);
Database2:
Code Block SQL SQL INSERT into company values ('SUN','c2',0.0); INSERT into company values ('MSFT','c3',0.0);
In the
master-datasources.xml
file located at$CARBON_HOME/repository/conf/datasources
, create data source declarations for the distributed databases, ensuring that the datasource file names are*-xa-ds.xml
:
Datasource1: esb-derby-xa-ds.xmlCode Block XML XML <?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>
...
...
...
Info | ||
---|---|---|
| ||
The two datasource file names should be |
...
<type-mapping>Derby</type-mapping> </metadata> </xa-datasource> </datasources>
Datasource2: esb-derby1-xa-ds.xml
Code Block XML XML <
...
?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> </
...
7. Go into $JBOSS_HOME/bin
and start the server. Run the run.sh (run.bat)
script.
Info | ||
---|---|---|
| ||
You need to set the |
...
metadata> </xa-datasource> </datasources>
Try the samples. Refer to sample set up guide to
...
learn how
...
to set up the server. Deploy the
SimpleStockQuote
service
...
that comes with the WSO2 ESB samples.
Successful Scenario
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 |
2. Check both databases to see how the record is deleted from the first database and added to the second database.
Failure Scenario
1. Try to add an entry which is that already there exists in the second database. This time use Symbol the 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 rollbackrolls back. Check both databases again; there is no record deleted from the first database and no record added into the second database. Excerpt
hidden | true |
---|