Skip to content

Latest commit

 

History

History
1145 lines (950 loc) · 49.4 KB

File metadata and controls

1145 lines (950 loc) · 49.4 KB

ejb-txn-remote-call: Demonstrates remote EJB calls and transaction propagation

The ejb-txn-remote-call quickstart demonstrates remote transactional EJB calls over two application servers of JBoss EAP.

What is it?

The ejb-txn-remote-call quickstart demonstrates the remote transactional EJB calls over two Red Hat JBoss Enterprise Application Platforms. The remote side forms a HA cluster.

Description

This quickstart demonstrates how EJB remote calls propagate JTA transaction across Red Hat JBoss Enterprise Application Platforms. Further, this quickstart demonstrates the transaction recovery, which is run for both servers when a failure occurs.

This quickstart contains two Maven projects. The first maven project represents the sender side, and is intended to be deployed on the first JBoss EAP (server1). The second project represents the receiver side. This project is intended to be deployed to the other two JBoss EAP (server2 and server3). The two projects must not be deployed to the same server.

Table 1. Maven projects in this quickstart
Project Description

client

The application deployed to the first JBoss EAP server. Users can interact with this application through some REST endpoints, which start remote EJB calls toward the server application deployed on the other two JBoss EAPs. In more details, the transaction initiated at the client side enlists two participants: a database, and the EJB remote server. The transaction manager then uses the two-phase commit to commit the transactions over the two servers. Moreover, this quickstart shows how transactional failures how dealt with.

server

The application deployed to the second and third JBoss EAP servers. This application receives the remote EJB calls from the client application and, depending on the scenario, process the propagated transaction. In more details, the transaction initiated at the server side enlists two participants: a database, and a mock XAResource.

Running the Quickstart

This quickstart demonstrates its functionalities on bare metal, using JBoss EAP Maven plugin, and on OpenShift.

System Requirements

The application this project produces is designed to be run on Red Hat JBoss Enterprise Application Platform 8.1 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.

The Goal

The EJB remote call propagates transaction from client application to server application. The remote call hits one of the two servers where the server application is deployed.

Running in a bare metal environment

First of all, an environment variable should be defined to point to this quickstart’s root folder. From the root of this quickstart, the following command should be executed:

export PATH_TO_QUICKSTART_DIR=$(pwd)

Second, another environment variable should be defined to point to the JBoss EAP installation directory:

export EAP_HOME=...

Then, three JBoss EAP servers needs to be configured:

  1. The client application gets deployed to the first server (server1)

  2. The server application gets deployed to the other two JBoss EAP servers (server2, and server3, which are configured as a cluster)

Setup JBoss EAP servers

The easiest way to start multiple instances of JBoss EAP on a local computer is to copy the JBoss EAP installation directory to three separate directories.

The installation directories are named:

  • EAP_HOME_1 for server1

  • EAP_HOME_2 for server2

  • EAP_HOME_3 for server3

Given that the installation directory of the JBoss EAP is identified with $EAP_HOME:

cp -r $EAP_HOME server1; \
EAP_HOME_1="$PWD/server1"
cp -r $EAP_HOME server2; \
EAP_HOME_2="$PWD/server2"
cp -r $EAP_HOME server3; \
EAP_HOME_3="$PWD/server3"

Creating a user for server2 and server3

To successfully process EJB remote calls from server1 to either server2 or to server3 a user to authenticate the EJB remote calls must be created on the receiving servers.

Type the following command to add the user to server2:

$EAP_HOME_2/bin/add-user.sh -a -u 'quickstartUser' -p 'quickstartPwd1!'

And type the following command to add the user to server3:

$EAP_HOME_3/bin/add-user.sh -a -u 'quickstartUser' -p 'quickstartPwd1!'
Note
For Windows, use the EAP_HOME\bin\add-user.bat script.

Configure datasources

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

The JBoss EAP servers need to be configured to be able to connect to the database. First of all, a JDBC driver needs to be installed as jboss module.

The following command downloads the PostgreSQL driver automatically through Maven:

cd ${PATH_TO_QUICKSTART_DIR};
mvn clean process-sources

Then, the PostgreSQL driver needs to be loaded as jboss module in all JBoss EAP servers:

cd $EAP_HOME_1; \
./bin/jboss-cli.sh "embed-server,\
  module add --name=org.postgresql.jdbc \
  --resources=${PATH_TO_QUICKSTART_DIR}/client/target/postgresql/postgresql.jar"
cd $EAP_HOME_2; \
./bin/jboss-cli.sh "embed-server,\
  module add --name=org.postgresql.jdbc \
  --resources=${PATH_TO_QUICKSTART_DIR}/client/target/postgresql/postgresql.jar"
cd $EAP_HOME_3; \
./bin/jboss-cli.sh "embed-server,\
  module add --name=org.postgresql.jdbc \
  --resources=${PATH_TO_QUICKSTART_DIR}/client/target/postgresql/postgresql.jar"

Moreover, the PostgreSQL driver needs to be installed on all JBoss EAP servers. For server1, the configuration file standalone.xml will be used. For server2 and server3 the configuration file standalone-ha.xml will be used.

cd $EAP_HOME_1; \
./bin/jboss-cli.sh "embed-server --server-config=standalone.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)"
cd $EAP_HOME_2; \
./bin/jboss-cli.sh "embed-server --server-config=standalone-ha.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)"
cd $EAP_HOME_3; \
./bin/jboss-cli.sh "embed-server --server-config=standalone-ha.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 scripts for adding the PostgreSQL datasource to the JBoss EAP servers:

cd $EAP_HOME_1; \
./bin/jboss-cli.sh -DpostgresqlUsername="test" -DpostgresqlPassword="test" \
  --file=${PATH_TO_QUICKSTART_DIR}/client/scripts/postgresql-datasource.cli \
  --properties=${PATH_TO_QUICKSTART_DIR}/client/scripts/cli.local.properties
cd $EAP_HOME_2; \
./bin/jboss-cli.sh -DpostgresqlUsername="test" -DpostgresqlPassword="test" \
  --file=${PATH_TO_QUICKSTART_DIR}/server/scripts/postgresql-datasource.cli \
  --properties=${PATH_TO_QUICKSTART_DIR}/server/scripts/cli.local.properties
cd $EAP_HOME_3; \
./bin/jboss-cli.sh -DpostgresqlUsername="test" -DpostgresqlPassword="test" \
  --file=${PATH_TO_QUICKSTART_DIR}/server/scripts/postgresql-datasource.cli \
  --properties=${PATH_TO_QUICKSTART_DIR}/server/scripts/cli.local.properties

Configuring EJB remoting on server1

EJB remote calls from server1 to either server2 or server3 need to be authenticated. To achieve this configuration, the script ${PATH_TO_QUICKSTART_DIR}/client/scripts/remoting-configuration.cli will be executed on server1.

Note

remoting-configuration.cli is configured with properties in cli.local.properties and runs against standalone.xml

cd $EAP_HOME_1; \
./bin/jboss-cli.sh -DremoteServerUsername='quickstartUser' -DremoteServerPassword='quickstartPwd1!' \
  --file=${PATH_TO_QUICKSTART_DIR}/client/scripts/remoting-configuration.cli \
  --properties=${PATH_TO_QUICKSTART_DIR}/client/scripts/cli.local.properties
Note
For Windows, use the bin\jboss-cli.bat script.

Running remoting-configuration.cli results in the creation of:

  • A remote outbound socket that points to the port on server2/server3 where EJB remoting endpoints can be reached

  • A remote outbound connection that can be referenced in the war deployment with jboss-ejb-client.xml descriptor (see ${PATH_TO_QUICKSTART_DIR}/client/src/main/webapp/WEB-INF/jboss-ejb-client.xml).

  • An authentication context auth_context that is used by the new created remoting connection remote-ejb-connection; the authentication context uses the same username and password created for server2 and server3

Start JBoss EAP servers

At this point, the configuration of the JBoss EAP servers is completed. server1 must be started with the standalone.xml configuration, while server2 and server3 must be started with the standalone-ha.xml configuration to create a cluster. As all JBoss EAP servers will be run in the same bare metal environment, a port offset will be applied to server2 and server3. Moreover, each server has to define a unique transaction node identifier and jboss node name.

Start each server in a separate terminal.

cd $EAP_HOME_1; \
./bin/standalone.sh -c standalone.xml -Djboss.tx.node.id=server1 -Djboss.node.name=server1
cd $EAP_HOME_2; \
./bin/standalone.sh -c standalone-ha.xml -Djboss.tx.node.id=server2 -Djboss.node.name=server2 -Djboss.socket.binding.port-offset=100
cd $EAP_HOME_3; \
./bin/standalone.sh -c standalone-ha.xml -Djboss.tx.node.id=server3 -Djboss.node.name=server3 -Djboss.socket.binding.port-offset=200
Note
For Windows, use the bin\standalone.bat script.

Deploying the Quickstart applications

  1. With all JBoss EAP servers configured and running, the client and server application can be deployed

  2. Ensure the whole project is built:

    cd ${PATH_TO_QUICKSTART_DIR}/
    mvn clean package
  3. Then, the client application can be deployed using the following commands:

    cd ${PATH_TO_QUICKSTART_DIR}/client
    mvn wildfly:deploy
  4. Lastly, the server application can be deployed using the following commands:

    cd ${PATH_TO_QUICKSTART_DIR}/server
    mvn wildfly:deploy -Dwildfly.port=10090
    mvn wildfly:deploy -Dwildfly.port=10190

The commands just run employed the WildFly Maven plugin to connect to the running instances of JBoss EAP and deploy the war archives to the servers.

The following warnings might appear in the server output after the applications are deployed. These warnings can be safely ignored in a development environment.

WARN  [org.jgroups.protocols.UDP] (ServerService Thread Pool -- 90) JGRP000015: the receive buffer of socket ManagedMulticastSocketBinding was set to 20MB, but the OS only allocated 6.71MB
WARN  [org.jgroups.protocols.UDP] (ServerService Thread Pool -- 90) JGRP000015: the receive buffer of socket ManagedMulticastSocketBinding was set to 25MB, but the OS only allocated 6.71MB

Checkpoints

  1. If errors occur, verify that the JBoss EAP servers are running and that they are configured properly

  2. Verify that all deployments are published into all three servers

    1. On server1 check the log to confirm that the client/target/client.war archive is deployed

      ...
      INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 76) WFLYUT0021: Registered web context: '/client' for server 'default-server'
      INFO  [org.jboss.as.server] (management-handler-thread - 2) WFLYSRV0010: Deployed "client.war" (runtime-name : "client.war")
    2. On server2 and server3, check the log to confirm that the server/target/server.war archive is deployed.

      ...
      INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 86) WFLYUT0021: Registered web context: '/server' for server 'default-server'
      INFO  [org.jboss.as.server] (management-handler-thread - 1) WFLYSRV0010: Deployed "server.war" (runtime-name : "server.war")
  3. Verify that server2 and server3 formed a HA cluster.

    1. Check the server log of either server2 and server3, or both.

      [org.infinispan.CLUSTER] () ISPN000094: Received new cluster view for channel ejb: [server2|1] (2) [server2, server3]
      [org.infinispan.CLUSTER] () ISPN100000: Node server3 joined the cluster
      ...
      INFO  [org.infinispan.CLUSTER] () [Context=server.war/infinispan] ISPN100010: Finished rebalance with members [server2, server3], topology id 5

Examining the Quickstart

Once the JBoss EAP servers are configured and started, and the quickstart artifacts are deployed, it is possible to invoke the endpoints of server1, which generate EJB remote invocations against the HA cluster formed by server2 and server3.

The following table defines the available endpoints, and their expected behaviour.

Note

The endpoints return data in JSON format. You can use curl for the invocation and jq for formatting the results. For example:

Note

On Windows, curl and jq might not be available. If so, enter the endpoints directly to a browser of your choice. The behaviour and the obtained JSON will be the same as for the curl command.

The HTTP invocations return the hostnames of the contacted servers.

Table 2. HTTP endpoints of the test invocation
URL Behaviour Expectation

http://localhost:8080/client/remote-outbound-stateless

Two invocations under the transaction context started on server1 (client application). The EJB remote call is configured from the remote-outbound-connection. Both calls are directed to the same remote server instance (server application) due to transaction affinity.

The two returned hostnames must be the same.

http://localhost:8080/client/remote-outbound-notx-stateless

Several remote invocations to stateless EJB without a transaction context. The EJB remote call is configured from the remote-outbound-connection. The EJB client is expected to load balance the calls on various servers.

The list of the returned hostnames should contain occurrences of both server2 and server3.

http://localhost:8080/client/direct-stateless

Two invocations under the transaction context started on server1 (client application). The stateless bean is invoked on the remote side. The EJB remote call is configured from data in the client application source code. The remote invocation is run via the EJB remoting protocol.

The returned hostnames must be the same.

http://localhost:8080/client/direct-stateless-http

Two invocations under the transaction context started on server1 (client application). The stateless bean is invoked on the remote side. The EJB remote call is configured from data in the client application source code. The remote invocation is run, unlike the other calls of this quickstarts, via EJB over HTTP.

The returned hostnames must be the same.

http://localhost:8080/client/remote-outbound-notx-stateful

Two invocations under the transaction context started on server1 (client application). The EJB remote call is configured from the remote-outbound-connection. Both calls are directed to the same stateful bean on the remote server because the stateful bean invocations are sticky ensuring affinity to the same server instance.

The returned hostnames must be the same.

http://localhost:8080/client/remote-outbound-fail-stateless

An invocation under the transaction context started on server1 (client application). The call goes to one of the remote servers, where errors occur during transaction processing. The failure is simulated at time of two-phase commit. This HTTP call finishes with success. Only the server log shows some warnings. This is an expected behaviour. An intermittent failure during commit phase of two-phase protocol makes the transaction manager obliged to finish the work eventually. The finalization of work is done in the background (by Narayana recovery manager, see details below), and the HTTP call may inform the client back with success.

When the recovery manager finishes the work all the transaction resources are committed.

Observing the recovery processing after client/remote-outbound-fail-stateless call

The EJB call to the endpoint client/remote-outbound-fail-stateless simulates the presence of an intermittent network error happening at the commit phase of the two-phase commit protocol (2PC).

The transaction recovery manager periodically tries to recover the unfinished work and only when this attempt is successful, the transaction is completed (which makes the update in the database visible). It is possible to confirm the completion of the transaction by invoking the REST endpoint server/commits at both servers server2 and server3.

curl -s http://localhost:8180/server/commits
curl -s http://localhost:8280/server/commits

The response of server/commits is a tuple composed by the host’s info and the number of commits. For example the output could be ["host: mydev.narayana.io/192.168.0.1, jboss node name: server2","3"] and it says that the hostname is mydev.narayana.io, the jboss node name is server2, and the number of commits is 3.

The Transaction recovery manager runs periodically (by default, it runs every 2 minutes) on all servers. Nevertheless, as the transaction is initiated on server1, the recovery manager on this server will be responsible to initiate the recovery process.

Note

The recovery process can be started manually. Using telnet and connecting to localhost:4712 (i.e. the port where the recovery process is listening to), it is possible to send the SCAN command to force a recovery cycle

telnet localhost 4712
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
SCAN
DONE
Connection closed by foreign host.
Steps to observe that the recovery processing was done
  1. Before invoking the remote-outbound-fail-stateless endpoint, double check the number of commits on server2 and server3 by invoking the server/commits endpoints.

    curl http://localhost:8180/server/commits; echo
    # output example:
    # ["host: mydev.narayana.io/192.168.0.1, jboss node name: server2","1"]
    curl http://localhost:8280/server/commits; echo
    # output example:
    # ["host: mydev.narayana.io/192.168.0.1, jboss node name: server3","2"]
  2. Invoke the REST endpoint client/remote-outbound-fail-stateless

    curl http://localhost:8080/client/remote-outbound-fail-stateless | jq .

    The JSON output from the previous command reports the name of server the request was sent to.

  3. At the server reported by the previous command, verify the number of commits by invoking the server/commits endpoint.

  4. Check the log of server1 for the following warning message

    ARJUNA016036: commit on < formatId=131077, gtrid_length=35, bqual_length=36, tx_uid=..., node_name=server1, branch_uid=..., subordinatenodename=null, eis_name=unknown eis name > (Subordinate XAResource at remote+http://localhost:8180) failed with exception $XAException.XA_RETRY: javax.transaction.xa.XAException: WFTXN0029: The peer threw an XA exception

    This message means that the transaction manager was not able to commit the transaction as an error occurred while committing the transaction on the remote server. The XAException.XA_RETRY exception, meaning an intermittent failure, was reported in the logs.

  5. The logs on server2 or server3 contain a warning about the XAResource failure as well.

    ARJUNA016036: commit on < formatId=131077, gtrid_length=35, bqual_length=43, tx_uid=..., node_name=server1, branch_uid=..., subordinatenodename=server2, eis_name=unknown eis name > (org.jboss.as.quickstarts.ejb.mock.MockXAResource@731ae22) failed with exception $XAException.XAER_RMFAIL: javax.transaction.xa.XAException
  6. Wait for the recovery process at server1 to recover the unfinished transaction (or force a recovery cycle manually)

  7. The number of commits on the targeted server should be incremented by one.

Run the Integration Tests

This quickstart includes integration tests, which are located under the src/test/ directory. The integration tests verify that the quickstart runs correctly when deployed on the server.

Follow these steps to run the integration tests.

  1. Make sure JBoss EAP server is started.

  2. Make sure the quickstart is deployed.

  3. Type the following command to run the verify goal with the integration-testing profile activated.

    $ mvn verify -Pintegration-testing 

Undeploy the Quickstart

When you are finished testing the quickstart, execute these commands to undeploy the archives:

cd ${PATH_TO_QUICKSTART_DIR}/client
mvn wildfly:undeploy

cd ${PATH_TO_QUICKSTART_DIR}/server
mvn wildfly:undeploy -Dwildfly.port=10090
mvn wildfly:undeploy -Dwildfly.port=10190

Server Log: Expected Warnings and Errors

This quickstart is not production grade. The server logs include the following warnings during the startup. It is safe to ignore these warnings.

WFLYDM0111: Keystore standalone/configuration/application.keystore not found, it will be auto generated on first use with a self signed certificate for host localhost

WFLYELY01084: KeyStore .../standalone/configuration/application.keystore not found, it will be auto generated on first use with a self-signed certificate for host localhost

WFLYSRV0018: Deployment "deployment.server.war" is using a private module ("org.jboss.jts") which may be changed or removed in future versions without notice.

Building and running the quickstart application with provisioned JBoss EAP server

Instead of using a standard JBoss EAP server distribution, the three JBoss EAP servers to deploy and run the quickstart can be provisioned:

cd ${PATH_TO_QUICKSTART_DIR}/client;
mvn clean package \
  -DremoteServerUsername="quickstartUser" -DremoteServerPassword='quickstartPwd1!' \
  -DpostgresqlUsername="test" -DpostgresqlPassword="test"
cd ${PATH_TO_QUICKSTART_DIR}/server;
mvn clean package \
  -Dwildfly.provisioning.dir=server2 -Djboss-as.home=target/server2 \
  -DpostgresqlUsername="test" -DpostgresqlPassword="test" -Dorg.jboss.eap.datasources.postgresql.driver.version="42.7.4";
mvn package \
  -Dwildfly.provisioning.dir=server3 -Djboss-as.home=target/server3 \
  -DpostgresqlUsername="test" -DpostgresqlPassword="test" -Dorg.jboss.eap.datasources.postgresql.driver.version="42.7.4"

The provisioned JBoss EAP servers, with the quickstart deployed, can then be found in ${PATH_TO_QUICKSTART_DIR}/client/target/server, ${PATH_TO_QUICKSTART_DIR}/server/target/server2, and ${PATH_TO_QUICKSTART_DIR}/server/target/server3 directories, and their usage is similar to a standard server distribution, with the simplification that there is never the need to specify the server configuration to be started.

The server provisioning functionality is provided by the WildFly Maven Plugin, and you may find its configuration in the pom.xml files of the quickstart.

The quickstart user should be added after provisioning the servers, and before running them:

cd ${PATH_TO_QUICKSTART_DIR}/server;
./target/server2/bin/add-user.sh -a -u 'quickstartUser' -p 'quickstartPwd1!';
./target/server3/bin/add-user.sh -a -u 'quickstartUser' -p 'quickstartPwd1!'
Note

For Windows, use the EAP_HOME\bin\add-user.bat script.

Run the Integration Tests with a provisioned server

The integration tests included with this quickstart, which verify that the quickstart runs correctly, may also be run with provisioned server.

Follow these steps to run the integration tests.

  1. Ensure the PostgreSQL database is running, as described in Configure datasources.

  2. Make sure the servers are provisioned by running the commands reported in Building and running the quickstart application with provisioned JBoss EAP server

  3. Add the quickstart user to the provisioned server2 and server3 by running the commands reported in Building and running the quickstart application with provisioned JBoss EAP server

  4. Start the JBoss EAP provisioned servers in three distinct terminals, this time using the JBoss EAP Maven Plugin, which is recommended for testing due to simpler automation.

    cd ${PATH_TO_QUICKSTART_DIR}/client;
    mvn wildfly:start \
      -DpostgresqlUsername="test" -DpostgresqlPassword="test" \
      -Dwildfly.javaOpts="-Djboss.tx.node.id=server1 -Djboss.node.name=server1"
    cd ${PATH_TO_QUICKSTART_DIR}/server;
    mvn wildfly:start -Djboss-as.home=target/server2 \
      -DpostgresqlUsername="test" -DpostgresqlPassword="test" \
      -Dwildfly.javaOpts="-Djboss.socket.binding.port-offset=100 -Djboss.tx.node.id=server2 -Djboss.node.name=server2"
    cd ${PATH_TO_QUICKSTART_DIR}/server;
    mvn wildfly:start -Djboss-as.home=target/server3 \
      -DpostgresqlUsername="test" -DpostgresqlPassword="test" \
      -Dwildfly.javaOpts="-Djboss.socket.binding.port-offset=200 -Djboss.tx.node.id=server3 -Djboss.node.name=server3"
  5. Type the following command to run the verify goal with the integration-testing profile activated, and specifying the quickstart’s URL using the server.host system property.

    cd ${PATH_TO_QUICKSTART_DIR}/client;
    mvn verify -Pintegration-testing
    cd ${PATH_TO_QUICKSTART_DIR}/server;
    mvn verify -Pintegration-testing -Dserver.host="http://localhost:8180"
    cd ${PATH_TO_QUICKSTART_DIR}/server;
    mvn verify -Pintegration-testing -Dserver.host="http://localhost:8280"
  6. To shut down the JBoss EAP provisioned servers using the JBoss EAP Maven Plugin:

    mvn wildfly:shutdown
    mvn wildfly:shutdown -Dwildfly.port=10090
    mvn wildfly:shutdown -Dwildfly.port=10190

Running on OpenShift

The ephemeral nature of OpenShift does not work smoothly with JBoss EAP’s ability to handle transactions. In fact, JBoss EAP’s transaction management saves logs to keep record of transactions' history in case of extreme scenarios, like crashes or network issues. Moreover, EJB remoting requires a stable remote endpoint to guarantee:

  • The transaction affinity of stateful beans and

  • The recovery of transactions.

To fulfil the aforementioned requirements, applications that requires ACID transactions must be deployed to JBoss EAP using the JBoss EAP’s Operator, which can employ OpenShift’s StatefulSet. Failing to do so might result in no-ACID transactions.

Prerequisites

Install JBoss EAP’s Operator

To install JBoss EAP’s Operator, follow the official documentation (which instructions are also reported here for convenience)

Note
  • You have access to an OpenShift Container Platform cluster using an account with cluster-admin permissions.

  • You have installed the oc tool in your local system.

  1. View the list of operators available to the cluster from the OperatorHub:

    oc get packagemanifests -n openshift-marketplace | grep eap
  2. Create a Subscription object YAML file (for example, eap-operator-sub.yaml) to subscribe a namespace to your EAP operator. The following is an example Subscription object YAML file:

    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: eap
      namespace: openshift-operators
    spec:
      channel: stable
      installPlanApproval: Automatic
      name: eap
      source:  redhat-operators
      sourceNamespace: openshift-marketplace
  3. Create the Subscription object from the YAML file:

    oc apply -f eap-operator-sub.yaml

    The EAP operator is successfully installed. At this point, the OLM is aware of the EAP operator. A ClusterServiceVersion (CSV) for the operator appears in the target namespace, and APIs provided by the EAP operator is available for creation. To verify that the JBoss EAP Operator is running, execute the following command:

    oc get csv -n openshift-operators

Start a PostgreSQL database

This quickstart requires a PostgreSQL database to run correctly. In the scope of this quickstart, a PostgreSQL database will be deployed on the OpenShift instance using the Helm chart provided by bitnami:

helm repo add bitnami https://charts.bitnami.com/bitnami
helm install postgresql bitnami/postgresql -f charts/postgresql.yaml --wait --timeout="5m"

Build the applications

To build the client and the server applications, this quickstart employs JBoss EAP’s Helm charts. For more information about JBoss EAP’s Helm chart, please refer to the official documentation.

helm repo add jboss-eap https://jbossas.github.io/eap-charts/

helm install client -f charts/client.yaml jboss-eap/eap81
helm install server -f charts/server.yaml jboss-eap/eap81

Wait for the builds to finish. Their status can be verified by executing the oc get pod command.

Deploy the Quickstart

To deploy the client and the server applications, this quickstart uses the WildFlyServer custom resource, thanks to which the JBoss EAP Operator is able to create a JBoss EAP pod and deploy an application.

Note
Make sure that view permissions are granted to the default system account. The KUBE_PING protocol, which is used for forming the HA JBoss EAP cluster on OpenShift, requires view permissions to read the labels of the pods: oc policy add-role-to-user view system:serviceaccount:$(oc project -q):default -n $(oc project -q)
cd ${PATH_TO_QUICKSTART_DIR};
oc create -f client/client-cr.yaml;
oc create -f server/server-cr.yaml

If the above commands are successful, the oc get pod command shows all the pods required for the quickstart, i.e. the client pod and two server pods (and the PostgreSQL database).

NAME                                READY   STATUS      RESTARTS   AGE
client-0                            1/1     Running     0          29m
postgresql-f9f475f87-l944r          1/1     Running     1          22h
server-0                            1/1     Running     0          11m
server-1                            1/1     Running     0          11m

Verify the Quickstarts

The JBoss EAP Operator creates routes that make the client and the server applications accessible outside the OpenShift environment. The oc get route command shows the addresses of the HTTP endpoints. An example of the output is:

oc get route

NAME           HOST/PORT                                                            PATH   SERVICES              PORT
client-route   client-route-ejb-txn-remote-call-client-artifacts.apps-crc.testing          client-loadbalancer   http
server-route   server-route-ejb-txn-remote-call-client-artifacts.apps-crc.testing          server-loadbalancer   http

With the following commands, it is possible to verify the some functionalities of this quickstart:

curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/remote-outbound-stateless | jq .
curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/remote-outbound-stateless | jq .
curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/remote-outbound-notx-stateless | jq .
curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/direct-stateless | jq .
curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/remote-outbound-notx-stateful | jq .

For other HTTP endpoints, refer to the table above.

If you like to observe the recovery process then you can follow these shell commands.

# To check failure resolution
# verify the number of commits that come from the first and second node of the `server` deployments.
# Two calls are needed, as each reports the commit count of different node.
# Remember the reported number of commits to be compared with the results after crash later.
curl -s $(oc get route server-route --template='{{ .spec.host }}')/server/commits
curl -s $(oc get route server-route --template='{{ .spec.host }}')/server/commits

# Run the remote call that causes the JVM of the server to crash.
curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/remote-outbound-fail-stateless
# The platforms restarts the server back to life.
# The following commands then make us waiting while printing the number of commits happened at the servers.
while true; do
  curl -s $(oc get route server-route --template='{{ .spec.host }}')/server/commits
  curl -s $(oc get route server-route --template='{{ .spec.host }}')/server/commits
  I=$((I+1))
  echo " <<< Round: $I >>>"
  sleep 2
done

Running on OpenShift: Quickstart application removal

To delete the client and the server applications, the WildFlyServer definitions needs to be deleted. This is achievable running:

oc delete WildFlyServer client;
oc delete WildFlyServer server

The client and the server applications will be stopped, and the two pods will be removed.

To remove the Helm charts installed previously:

helm uninstall client;
helm uninstall server;
helm uninstall postgresql

Finally, to undeploy and uninstall the JBoss EAP’s operator:

oc delete -f eap-operator-sub.yaml