The jts
quickstart shows how to use JTS to perform distributed transactions across multiple containers, fulfilling the properties of an ACID transaction.
The jts
quickstart demonstrates how to perform distributed transactions across multiple containers in an application deployed to WildFly Application Server. A distributed transaction is a set of operations performed by two or more nodes, participating in an activity coordinated as a single entity of work, and fulfilling the properties of an ACID transaction.
ACID is a set of 4 properties that guarantee the resources are processed in the following manner:
-
Atomic - if any part of the transaction fails, all resources remain unchanged.
-
Consistent - the state will be consistent across resources after a commit
-
Isolated - the execution of the transaction for each resource is isolated from each others
-
Durable - the data will persist after the transaction is committed
The example uses Java Transaction Service (JTS) to propagate a transaction context across two Container-Managed Transaction (CMT) EJBs that, although deployed in separate servers, participate in the same transaction. In this example, one server processes the Customer and Account data and the other server processes the Invoice data.
The code base is essentially the same as the cmt quickstart.
As a consequence, developers should be familiar with the concepts introduced in that quickstart.
However, in this case the InvoiceManager
has been separated to a different deployment archive to demonstrate the usage of JTS. You can see the changes in the following ways:
-
cmt/src/main/java/org/jboss/as/quickstarts/cmt/ejb/InvoiceManagerEJB.java
has been moved toapplication-component-2/src/main/java/org/jboss/as/quickstarts/cmt/jts/ejb/InvoiceManagerEJB
-
cmt/src/main/java/org/jboss/as/quickstarts/cmt/ejb/CustomerManagerEJB.java
has been moved tojts/application-component-1/src/main/java/org/jboss/as/quickstarts/cmt/jts/ejb/CustomerManagerEJB.java
The changes to CustomerManagerEJB
are purely to accommodate the fact that InvoiceManager
is now distributed.
You will see that the CustomerManagerEJB
uses the EJB home for the remote EJB, this is expected to connect to remote EJBs. The example expects the EJBs to be deployed onto the same physical machine. This is not a restriction of JTS and the example can easily be converted to run on separate machines by editing the hostname value for the InvoiceManagerEJB
in org.jboss.as.quickstarts.cmt.jts.ejb.CustomerManagerEJB
.
A simple MDB has been provided that prints out the messages sent but this is not a transactional MDB and is purely provided for debugging purposes.
Also, while the cmt
quickstart uses the Jakarta EE container default datasource, which is not distributed, this quickstart instead uses an external PostgreSQL database.
The application this project produces is designed to be run on WildFly Application Server 36 or later.
All you need to build this project is Java SE 17.0 or later, and Maven 3.6.0 or later. See Configure Maven to Build and Deploy the Quickstarts to make sure you are configured correctly for testing the quickstarts.
This quickstart requires that you clone your WILDFLY_HOME
installation directory and run two servers. The installation path is described in detail here: Use of WILDFLY_HOME and JBOSS_HOME Variables.
In the following instructions, replace WILDFLY_HOME_1
with the path to your first WildFly server and replace WILDFLY_HOME_2
with the path to your second cloned WildFly server.
When you see the replaceable variable QUICKSTART_HOME, replace it with the path to the root directory of all of the quickstarts.
As this quickstart performs transactional work against a database, it is needed to create a new database. For the purpose of this quickstart, a simple PostgreSQL container will be used, please open another terminal and run the following command to download and start its image:
podman run -p 5432:5432 --rm -ePOSTGRES_DB=test -ePOSTGRES_USER=test -ePOSTGRES_PASSWORD=test postgres:9.4 -c max-prepared-transactions=110 -c log-statement=all
For this example, you will need two instances of the application server, with a subtle startup configuration difference. Application server 2 must be started up with a port offset parameter provided to the startup script as -Djboss.socket.binding.port-offset=100
.
Since both application servers must be configured in the same way, you must configure the first server and then clone it. After you clone the second server, the first server must be configured for PostgreSQL.
You configure JTS transactions by running JBoss CLI commands. For your convenience, this quickstart batches the commands into a configure-jts-transactions.cli
script provided in the root directory of this quickstart.
-
Before you begin, back up your server configuration file
-
If it is running, stop the WildFly server.
-
Back up the file:
WILDFLY_HOME_1/standalone/configuration/standalone-full.xml
-
After you have completed testing this quickstart, you can replace this file to restore the server to its original configuration.
-
-
Start the WildFly server with the standalone full profile, passing a unique node ID, by typing the following command. Make sure you replace
UNIQUE_NODE_ID_1
with a node identifier that is unique to both servers.$WILDFLY_HOME_1/bin/standalone.sh -c standalone-full.xml -Djboss.tx.node.id=UNIQUE_NODE_ID_1
NoteFor Windows, use the WILDFLY_HOME_1\bin\standalone.bat
script. -
Review the
configure-jts-transactions.cli
file in the root of this quickstart directory. This script configures the server to use jts transaction processing. -
Open a new terminal, navigate to the root directory of this quickstart, and run the following command, replacing
WILDFLY_HOME_1
with the path to your server:$WILDFLY_HOME_1/bin/jboss-cli.sh --connect --file=configure-jts-transactions.cli
NoteFor Windows, use the WILDFLY_HOME_1\bin\jboss-cli.bat
script.You should see the following result when you run the script:
The batch executed successfully process-state: restart-required
-
Stop the WildFly server.
Important
|
When you have completed testing this quickstart, it is important to Remove the JTS Configuration from the WildFly Server. |
After stopping the server, open the WILDFLY_HOME_1/standalone/configuration/standalone-full.xml
file and review the changes.
-
The orb initializers
transactions
attribute is changed fromspec
tofull
in theiiop-openjdk
subsystem to enable JTS.<subsystem xmlns="{IiopOpenJdkSubsystemNamespace}"> <initializers security="elytron" transactions="full" /> </subsystem>
-
An empty
<jts/>
element is added to the end of thetransactions
subsystem to enable JTS.<subsystem xmlns="{TransactionsSubsystemNamespace}"> <core-environment node-identifier="${jboss.tx.node.id}"> <process-id> <uuid/> </process-id> </core-environment> <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/> <coordinator-environment statistics-enabled="${wildfly.transactions.statistics-enabled:${wildfly.statistics-enabled:false}}"/> <object-store path="tx-object-store" relative-to="jboss.server.data.dir"/> <jts/> </subsystem>
Make a copy of this WildFly directory structure to use for the second server.
The WildFly server 1 need to be configured to be able to connect to the database created previously in the Create a PostgreSQL Database section. First of all, a JDBC driver needs to be installed as jboss module.
The following command downloads the PostgreSQL driver automatically through Maven. When needed, replace WILDFLY_HOME_1 with the path to your server
-
Open a new terminal, navigate to the root directory of this quickstart, and run the following command:
mvn clean package
-
Then, add a JBoss Module with the PostgreSQL driver to the WildFly server 1:
$WILDFLY_HOME_1/bin/jboss-cli.sh "embed-server,\ module add --name=org.postgresql.jdbc \ --resources=application-component-1/target/postgresql/postgresql.jar"
-
Moreover, the PostgreSQL driver needs to be added to the datasources subsystem, in the WildFly server 1:
$WILDFLY_HOME_1/bin/jboss-cli.sh "embed-server --server-config=standalone-full.xml,\ /subsystem=datasources/jdbc-driver=postgresql:add(driver-name=postgresql,driver-module-name=org.postgresql.jdbc,driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource)"
-
Finally, it is time to run the script for adding the PostgreSQL datasource to the WildFly server 1:
$WILDFLY_HOME_1/bin/jboss-cli.sh -DpostgresqlUsername="test" -DpostgresqlPassword="test" \ --file=application-component-1/scripts/postgresql-datasource.cli \ --properties=application-component-1/scripts/cli.local.properties
Start the two WildFly server with the standalone full profile, passing a unique node ID, by typing the following commands. You must pass a socket binding port offset on the command to start the second server. Make sure you replace UNIQUE_NODE_ID_1
and UNIQUE_NODE_ID_2
with node identifiers that are unique across both servers.
$WILDFLY_HOME_1/bin/standalone.sh -c standalone-full.xml -Djboss.tx.node.id=UNIQUE_NODE_ID_1
$WILDFLY_HOME_2/bin/standalone.sh -c standalone-full.xml -Djboss.tx.node.id=UNIQUE_NODE_ID_2 -Djboss.socket.binding.port-offset=100
Note
|
For Windows, use the WILDFLY_HOME_1\bin\standalone.bat and WILDFLY_HOME_2\bin\standalone.bat scripts.
|
Since this quickstart builds two separate components, you can not use the standard Build and Deploy commands used by most of the other quickstarts. You must follow these steps to build, deploy, and run this quickstart.
-
Make sure you have started the WildFly server with the PostgreSQL driver.
-
Open a terminal and navigate to the root directory of this quickstart.
-
Type this command to build and deploy the archive.
mvn clean install wildfly:deploy
-
This will deploy
jts-application-component-1.war
andjts-application-component-2.jar
to the running instance of the server.
The application will be running at the following URL: http://localhost:8080/jts-application-component-1/.
When you enter a name and click to Add
that customer, you will see the following in the application server 2 console:
INFO [class org.jboss.as.quickstarts.cmt.jts.mdb.HelloWorldMDB] (Thread-97 (ActiveMQ-client-global-threads-6840624)) Received Message: Created invoice for customer named: Tom
The web page will also change and show you the new list of customers.
When you are finished testing the quickstart, follow these steps to undeploy the archive.
-
Make sure WildFly server is started.
-
Open a terminal and navigate to the root directory of this quickstart.
-
Type this command to undeploy the archive:
$ mvn wildfly:undeploy
You must remove the JTS server configuration you did during setup because it interferes with the JTA quickstarts.
You can modify the server configuration by running the remove-jts-transactions.cli
script provided in the root directory of this quickstart, by using the JBoss CLI interactively, or by manually editing the configuration file.
-
Start the first WildFly server with the standalone full profile, passing a unique node ID, by typing the following command. Make sure you replace
UNIQUE_NODE_ID_1
with the node identifier that you used when you previously started the server.$WILDFLY_HOME_1/bin/standalone.sh -c standalone-full.xml -Djboss.tx.node.id=UNIQUE_NODE_ID_1
NoteFor Windows, use the WILDFLY_HOME_1\bin\standalone.bat
script. -
Open a new terminal, navigate to the root directory of this quickstart, and run the following command, replacing
WILDFLY_HOME_1
with the path to your server:$WILDFLY_HOME_1/bin/jboss-cli.sh --connect --file=remove-jts-transactions.cli
NoteFor Windows, use the WILDFLY_HOME_1\bin\jboss-cli.bat
script.This script removes the JTS configuration from the
iiop-openjdk
andtransactions
subsystems in the server configuration. You should see the following result when you run the script:The batch executed successfully process-state: restart-required { "outcome" => "success", "result" => undefined }
-
Start the first WildFly server with the standalone full profile, passing a unique node ID, by typing the following command. Make sure you replace
UNIQUE_NODE_ID_1
with the node identifier that you used when you previously started the server.$WILDFLY_HOME_1/bin/standalone.sh -c standalone-full.xml -Djboss.tx.node.id=UNIQUE_NODE_ID_1
NoteFor Windows, use the WILDFLY_HOME_1\bin\standalone.bat
script. -
To start the JBoss CLI tool, open a new terminal, navigate to the
WILDFLY_HOME_1
directory, and type the following:$WILDFLY_HOME_1/bin/jboss-cli.sh --connect
NoteFor Windows, use the WILDFLY_HOME_1\bin\jboss-cli.bat
script. -
At the prompt, type the following commands.
/subsystem=iiop-openjdk/:write-attribute(name=transactions,value=spec) /subsystem=transactions/:undefine-attribute(name=jts) /subsystem=transactions/:undefine-attribute(name=node-identifier)
-
You should see the following response after each command execution.
{ "outcome" => "success", "response-headers" => { "operation-requires-reload" => true, "process-state" => "restart-required" } }
-
Stop the server.
-
If you backed up the
WILDFLY_HOME_1/standalone/configuration/standalone-full.xml
file, ,simply replace the edited configuration file with the backup copy. -
If you did not make a backup copy, open the file
WILDFLY_HOME_1/standalone/configuration/standalone-full.`xml
and disable JTS as follows:-
Find the
orb
subsystem and change the configuration back to its original state.<subsystem xmlns="{IiopOpenJdkSubsystemNamespace}"> <initializers transactions="spec" security="identity"/> </subsystem>
-
Find the
transaction
subsystem and remove thenode-identifier
attribute from thecore-environment
element. Also remove the<jts/>
element.<subsystem xmlns="{TransactionsSubsystemNamespace}"> <core-environment> <process-id> <uuid/> </process-id> </core-environment> <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/> </subsystem>
-