diff --git a/.ci/openshift-ci/build-root/scripts/qs-overrides/ejb-txn-remote-call/overridable-functions.sh b/.ci/openshift-ci/build-root/scripts/qs-overrides/ejb-txn-remote-call/overridable-functions.sh new file mode 100644 index 0000000000..5106d46254 --- /dev/null +++ b/.ci/openshift-ci/build-root/scripts/qs-overrides/ejb-txn-remote-call/overridable-functions.sh @@ -0,0 +1,116 @@ +# These functions are 'overridable in the individual quickstarts. +# To do so create a ./qs-overrides/${qs_dir}/overridable-functions.sh and override the +# functions you need to. ${qs_dir} in this case is the same as the name of the quickstart directory +# that you want to tweak + +# Installs any prerequisites before doing the Helm install. +# The current directory is the quickstart directory. +# The default is to use the quickstart directory as the name, but in some cases +# a quickstart may need to shorten the name of the application in order to control +# the length of the resources created by OpenShift +# +# Parameters +# 1 - the name of the qs directory (not the full path) +function applicationName() { + #echo "${1}" + # The fill microprofile-reactive-messaging-kafka name results in names of generated resources which are too long for + # OpenShift to handle + echo "ejb-txn-remote-call" +} + + +# Installs any prerequisites before doing the Helm install. +# The current directory is the quickstart directory +# +# Parameters +# 1 - application name +function installPrerequisites() +{ + application="${1}" + + CURRENT_FOLDER=$(pwd) + + echo "Installing the PostgreSQL database" + + # Install bitnami and PostgreSQL + helm repo add bitnami https://charts.bitnami.com/bitnami + helm install postgresql bitnami/postgresql -f charts/postgresql.yaml --wait --timeout="${helm_install_timeout}" + + echo "Cloning WildFly operator repository in /tmp" + + cd /tmp || return + git clone https://github.com/wildfly/wildfly-operator.git + + cd wildfly-operator || return + + echo "Installing and deploying the 'WildFly operator' to the cluster" + + oc adm policy add-cluster-role-to-user cluster-admin developer + make install || return + make deploy || return + + seconds=120 + now=$(date +%s) + end=$(($seconds + $now)) + + echo "Waiting for 2 minutes that the 'WildFly operator' pod is in the 'Running' status." + while [ $now -lt $end ]; do + sleep 5 + + if [[ $(oc get pods --field-selector=status.phase==Running -l name=wildfly-operator | awk '{ if ($3 == "Running" && $2 == "1/1") { print } }') ]]; then + break + fi + + now=$(date +%s) + done + + cd $CURRENT_FOLDER || return +} + +function helmInstall() { + helm_set_arguments="$2" + + # TODO https://issues.redhat.com/browse/WFLY-18574 remove this when persistence is working + # This seems to work with my postgresql.yaml :fingers_crossed + # helm_set_arguments="${helm_set_arguments} --set postgresql.primary.persistence.enabled=false" + + # Don't quote ${helm_set_arguments} as it breaks the command when empty, and seems to work without + helm install client -f charts/client.yaml wildfly/wildfly --wait --timeout="${helm_install_timeout}" ${helm_set_arguments} + echo "$?" + # TODO: should we check when the build is done? + helm install server -f charts/server.yaml wildfly/wildfly --wait --timeout="${helm_install_timeout}" ${helm_set_arguments} + echo "$?" + # TODO: should we check when the build is done? +} + +# Commands to run once the Helm install has completed +function runPostHelmInstallCommands() { + + # Make sure that view permissions are granted to the default system account. + oc policy add-role-to-user view system:serviceaccount:$(oc project -q):default -n $(oc project -q) + + oc create -f client/client-cr.yaml + # TODO: should we check when the deployment is completed? + oc create -f server/server-cr.yaml + # TODO: should we check when the deployment is completed? +} + +# Cleans any prerequisites after doing the Helm uninstall. +# The current directory is the quickstart directory +# +# Parameters +# 1 - application name +function cleanPrerequisites() +{ + cd /tmp/wildfly-operator || return + + make undeploy + make uninstall + + cd .. + rm -rf wildfly-operator + + # Uninstall PostgreSQL and remove bitnami + helm uninstall postgresql + helm repo remove bitnami +} diff --git a/.github/workflows/quickstart_ejb-txn-remote-call_ci.yml b/.github/workflows/quickstart_ejb-txn-remote-call_ci.yml new file mode 100644 index 0000000000..c3165e0082 --- /dev/null +++ b/.github/workflows/quickstart_ejb-txn-remote-call_ci.yml @@ -0,0 +1,237 @@ +name: WildFly ejb-txn-remote-call Quickstart CI + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + paths: + - 'ejb-txn-remote-call/**' + - .github/workflows/quickstart_ci.yml + +# Only run the latest job +concurrency: + group: '${{ github.workflow }} @ ${{ github.ref || github.run_id }}' + cancel-in-progress: true + +env: + QUICKSTART_PATH: ejb-txn-remote-call + TEST_PROVISIONED_SERVER: true + TEST_BOOTABLE_JAR: false + TEST_OPENSHIFT: true + MATRIX_JDK: '"11", "17"' + MATRIX_OS: '"ubuntu-latest"' + SERVER_PROVISIONING_SERVER_HOST: 'http://localhost' + +jobs: + Matrix-Setup: + runs-on: ubuntu-latest + outputs: + os: ${{ steps.setup-matrix-os.outputs.os }} + jdk: ${{ steps.setup-matrix-jdk.outputs.jdk }} + steps: + - id: setup-matrix-jdk + run: echo 'jdk=[${{ env.MATRIX_JDK }}]' >> $GITHUB_OUTPUT + - id: setup-matrix-os + run: echo 'os=[${{ env.MATRIX_OS }}]' >> $GITHUB_OUTPUT + + Test-build-default-matrix: + name: BUILD DEFAULT - JDK${{ matrix.jdk }} - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + needs: Matrix-Setup + strategy: + fail-fast: false + matrix: + jdk: ${{ fromJSON(needs.Matrix-Setup.outputs.jdk) }} + os: ${{ fromJSON(needs.Matrix-Setup.outputs.os) }} + steps: + - uses: actions/checkout@v4 + with: + path: quickstarts + - name: Set up JDK ${{ matrix.jdk }} + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.jdk }} + distribution: 'temurin' + cache: 'maven' + - name: Run before script + env: + FILE: "./quickstarts/.github/workflows/quickstart_${{ env.QUICKSTART_PATH }}_ci_before.sh" + run: | + if test -f $FILE; + then + chmod +x $FILE + bash $FILE + fi + shell: bash + - name: Build ${{ env.QUICKSTART_PATH }} Quickstart for Release + run: | + cd quickstarts + cd ${{ env.QUICKSTART_PATH }} + mvn -fae clean install -Drelease + shell: bash + - name: Build, run & test ${{ env.QUICKSTART_PATH }} Quickstart with provisioned-server profile + if: ${{ env.TEST_PROVISIONED_SERVER }} + run: | + cd quickstarts + cd ${{ env.QUICKSTART_PATH }}/client + echo "Building 'client' provisioned server..." + mvn -fae clean package -Pprovisioned-server -DremoteServerUsername="quickstartUser" -DremoteServerPassword="quickstartPwd1!" -DpostgresqlUsername="test" -DpostgresqlPassword="test" + mvn wildfly:start -Djboss-as.home=target/server -Dwildfly.javaOpts="-Djboss.tx.node.id=server1 -Djboss.node.name=server1" -Dstartup-timeout=120 + cd ../server + echo "Building 'server' provisioned server..." + mvn -fae clean package -Pprovisioned-server -Dwildfly.provisioning.dir=server2 -Djboss-as.home=target/server2 -DpostgresqlUsername="test" -DpostgresqlPassword="test" + mvn -fae package -Pprovisioned-server -Dwildfly.provisioning.dir=server3 -Djboss-as.home=target/server3 -DpostgresqlUsername="test" -DpostgresqlPassword="test" + echo "Add quickstartUser to both 'server' builds..." + ./target/server2/bin/add-user.sh -a -u 'quickstartUser' -p 'quickstartPwd1!' -g 'guest,user,JBossAdmin,Users' + ./target/server3/bin/add-user.sh -a -u 'quickstartUser' -p 'quickstartPwd1!' -g 'guest,user,JBossAdmin,Users' + echo "Add quickstartAdmin to both 'server' builds..." + ./target/server2/bin/add-user.sh -a -u 'quickstartAdmin' -p 'adminPwd1!' -g 'guest,user,admin' + ./target/server2/bin/add-user.sh -a -u 'quickstartAdmin' -p 'adminPwd1!' -g 'guest,user,admin' + echo "Starting provisioned server..." + mvn wildfly:start -Djboss-as.home=target/server2 -Dwildfly.port=10090 -Dwildfly.serverConfig=standalone-ha.xml -Dwildfly.javaOpts="-Djboss.socket.binding.port-offset=100 -Djboss.tx.node.id=server2 -Djboss.node.name=server2" -Dstartup-timeout=120 + mvn wildfly:start -Djboss-as.home=target/server3 -Dwildfly.port=10190 -Dwildfly.serverConfig=standalone-ha.xml -Dwildfly.javaOpts="-Djboss.socket.binding.port-offset=200 -Djboss.tx.node.id=server3 -Djboss.node.name=server3" -Dstartup-timeout=120 + echo "Testing provisioned server..." + cd ../client + mvn -fae verify -Dserver.host=${{ env.SERVER_PROVISIONING_SERVER_HOST }}:8080 -Pintegration-testing + cd ../server + mvn -fae verify -Dserver.host=${{ env.SERVER_PROVISIONING_SERVER_HOST }}:8180 -Pintegration-testing + mvn -fae verify -Dserver.host=${{ env.SERVER_PROVISIONING_SERVER_HOST }}:8280 -Pintegration-testing + echo "Shutting down provisioned server..." + cd ../client + mvn wildfly:shutdown + cd ../server + mvn wildfly:shutdown -Dwildfly.port=10090 + mvn wildfly:shutdown -Dwildfly.port=10190 + shell: bash + - name: Build ${{ env.QUICKSTART_PATH }} Quickstart with openshift profile + if: ${{ env.TEST_OPENSHIFT }} + run: | + cd quickstarts + cd ${{ env.QUICKSTART_PATH }}/client + mvn -fae clean package -Popenshift -DremoteServerUsername="quickstartUser" -DremoteServerPassword="quickstartPwd1!" -DpostgresqlUsername="test" -DpostgresqlPassword="test" + cd ../server + mvn -fae clean package -Popenshift -DpostgresqlUsername="test" -DpostgresqlPassword="test" + shell: bash + - name: Run after script + env: + FILE: "./quickstarts/.github/workflows/quickstart_${{ env.QUICKSTART_PATH }}_ci_after.sh" + run: | + if test -f $FILE; + then + chmod +x $FILE + bash $FILE + fi + shell: bash + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: surefire-reports-JDK${{ matrix.jdk }}-${{ matrix.os }} + path: 'quickstarts/${{ env.QUICKSTART_PATH }}/**/surefire-reports/*.txt' + + # Use the shared-wildfly-build workflow to have a consistent WildFly build. Note the branch names MUST match what + # is used in WildFly. + WildFly-build: + uses: wildfly/wildfly/.github/workflows/shared-wildfly-build.yml@main + with: + wildfly-branch: ${{ github.base_ref }} + wildfly-repo: "wildfly/wildfly" + + Test-build-with-deps-matrix: + name: BUILD WITH DEPS - JDK${{ matrix.jdk }} - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + needs: [Matrix-Setup, WildFly-build] + strategy: + fail-fast: false + matrix: + jdk: ${{ fromJSON(needs.Matrix-Setup.outputs.jdk) }} + os: ${{ fromJSON(needs.Matrix-Setup.outputs.os) }} + steps: + - uses: actions/checkout@v4 + with: + path: quickstarts + - uses: actions/download-artifact@v4 + with: + name: wildfly-maven-repository + path: . + - name: Extract Maven Repo + shell: bash + run: tar -xzf wildfly-maven-repository.tar.gz -C ~ + - name: Set up JDK ${{ matrix.jdk }} + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.jdk }} + distribution: 'temurin' + cache: 'maven' + - name: Run before script + env: + FILE: "./quickstarts/.github/workflows/quickstart_${{ env.QUICKSTART_PATH }}_ci_before.sh" + run: | + if test -f $FILE; + then + chmod +x $FILE + bash $FILE + fi + shell: bash + - name: Build Quickstart for Release with built Server version + run: | + cd quickstarts + cd ${{ env.QUICKSTART_PATH }} + mvn -fae clean package -Drelease -Dversion.server=${{ needs.wildfly-build.outputs.wildfly-version }} + shell: bash + - name: Build, run & test ${{ env.QUICKSTART_PATH }} Quickstart with provisioned-server profile, and built Server version + if: ${{ env.TEST_PROVISIONED_SERVER }} + run: | + cd quickstarts + cd ${{ env.QUICKSTART_PATH }}/client + echo "Building 'client' provisioned server..." + mvn -fae clean package -Pprovisioned-server -DremoteServerUsername="quickstartUser" -DremoteServerPassword="quickstartPwd1!" -DpostgresqlUsername="test" -DpostgresqlPassword="test" -Dversion.server=${{ needs.wildfly-build.outputs.wildfly-version }} + mvn wildfly:start -Djboss-as.home=target/server -Dwildfly.javaOpts="-Djboss.tx.node.id=server1 -Djboss.node.name=server1" -Dstartup-timeout=120 + cd ../server + echo "Building 'server' provisioned server..." + mvn -fae clean package -Pprovisioned-server -Dwildfly.provisioning.dir=server2 -Djboss-as.home=target/server2 -DpostgresqlUsername="test" -DpostgresqlPassword="test" -Dversion.server=${{ needs.wildfly-build.outputs.wildfly-version }} + mvn -fae package -Pprovisioned-server -Dwildfly.provisioning.dir=server3 -Djboss-as.home=target/server3 -DpostgresqlUsername="test" -DpostgresqlPassword="test" -Dversion.server=${{ needs.wildfly-build.outputs.wildfly-version }} + echo "Add quickstartUser to both 'server' builds..." + ./target/server2/bin/add-user.sh -a -u 'quickstartUser' -p 'quickstartPwd1!' -g 'guest,user,JBossAdmin,Users' + ./target/server3/bin/add-user.sh -a -u 'quickstartUser' -p 'quickstartPwd1!' -g 'guest,user,JBossAdmin,Users' + echo "Add quickstartAdmin to both 'server' builds..." + ./target/server2/bin/add-user.sh -a -u 'quickstartAdmin' -p 'adminPwd1!' -g 'guest,user,admin' + ./target/server2/bin/add-user.sh -a -u 'quickstartAdmin' -p 'adminPwd1!' -g 'guest,user,admin' + echo "Starting provisioned server..." + mvn wildfly:start -Djboss-as.home=target/server2 -Dwildfly.port=10090 -Dwildfly.serverConfig=standalone-ha.xml -Dwildfly.javaOpts="-Djboss.socket.binding.port-offset=100 -Djboss.tx.node.id=server2 -Djboss.node.name=server2" -Dstartup-timeout=120 + mvn wildfly:start -Djboss-as.home=target/server3 -Dwildfly.port=10190 -Dwildfly.serverConfig=standalone-ha.xml -Dwildfly.javaOpts="-Djboss.socket.binding.port-offset=200 -Djboss.tx.node.id=server3 -Djboss.node.name=server3" -Dstartup-timeout=120 + echo "Testing provisioned server..." + cd ../client + mvn -fae verify -Dserver.host=${{ env.SERVER_PROVISIONING_SERVER_HOST }}:8080 -Pintegration-testing + cd ../server + mvn -fae verify -Dserver.host=${{ env.SERVER_PROVISIONING_SERVER_HOST }}:8180 -Pintegration-testing + mvn -fae verify -Dserver.host=${{ env.SERVER_PROVISIONING_SERVER_HOST }}:8280 -Pintegration-testing + echo "Shutting down provisioned server..." + cd ../client + mvn wildfly:shutdown + cd ../server + mvn wildfly:shutdown -Dwildfly.port=10090 + mvn wildfly:shutdown -Dwildfly.port=10190 + shell: bash + - name: Build ${{ env.QUICKSTART_PATH }} Quickstart with openshift profile, and built Server version + if: ${{ env.TEST_OPENSHIFT }} + run: | + cd quickstarts + cd ${{ env.QUICKSTART_PATH }}/client + mvn -fae clean package -Popenshift -DremoteServerUsername="quickstartUser" -DremoteServerPassword="quickstartPwd1!" -DpostgresqlUsername="test" -DpostgresqlPassword="test" -Dversion.server=${{ needs.wildfly-build.outputs.wildfly-version }} + cd ../server + mvn -fae clean package -Popenshift -DpostgresqlUsername="test" -DpostgresqlPassword="test" -Dversion.server=${{ needs.wildfly-build.outputs.wildfly-version }} + shell: bash + - name: Run after script + env: + FILE: "./quickstarts/.github/workflows/quickstart_${{ env.QUICKSTART_PATH }}_ci_after.sh" + run: | + if test -f $FILE; + then + chmod +x $FILE + bash $FILE + fi + shell: bash + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: surefire-reports-JDK${{ matrix.jdk }}-${{ matrix.os }} + path: 'quickstarts/**/surefire-reports/*.txt' \ No newline at end of file diff --git a/.github/workflows/quickstart_ejb-txn-remote-call_ci_before.sh b/.github/workflows/quickstart_ejb-txn-remote-call_ci_before.sh new file mode 100644 index 0000000000..e87bc43ce9 --- /dev/null +++ b/.github/workflows/quickstart_ejb-txn-remote-call_ci_before.sh @@ -0,0 +1 @@ +docker run -d -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 \ No newline at end of file diff --git a/ejb-txn-remote-call/README.adoc b/ejb-txn-remote-call/README.adoc index 59f64e01e4..289c17ac0b 100644 --- a/ejb-txn-remote-call/README.adoc +++ b/ejb-txn-remote-call/README.adoc @@ -16,16 +16,16 @@ The `ejb-txn-remote-call` quickstart demonstrates remote transactional EJB calls == What is it? -The `ejb-txn-remote-call` quickstart demonstrates the remote transactional EJB calls over two application servers of {productNameFull}. The remote side forms a HA cluster. +The `ejb-txn-remote-call` quickstart demonstrates the remote transactional EJB calls over two {productNameFull}s. The remote side forms a HA cluster. == Description -The EJB remote call propagates a JTA transaction. Further, the quickstart demonstrates the transaction recovery, which is run for both servers when a failure occurs. +This quickstart demonstrates how EJB remote calls propagate JTA transaction across {productNameFull}s. 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 server (`server1`). -The second project represents the called side. This project is intended to be deployed -to the other two servers (`server2` and `server3`). The two projects should not be deployed to the same server. +The first maven project represents the sender side, and is intended to be deployed on the first {productName} (`server1`). +The second project represents the receiver side. This project is intended to be deployed +to the other two {productName} (`server2` and `server3`). The two projects must not be deployed to the same server. .Maven projects in this quickstart [cols="40%,60%",options="headers"] @@ -33,25 +33,18 @@ to the other two servers (`server2` and `server3`). The two projects should not |Project |Description |`client` -|An application that you deploy to the first server, to `server1`. -It includes REST endpoints that provide EJB remote calls to the `server application` -residing on the other servers. -In addition, the remote EJB calls the REST endpoint invocation process to insert data into a database. -The REST invocation starts a transaction that enlists two participants -(the database and the EJB remote invocation). -The transaction manager then uses the two-phase commit to commit the transaction -over the two servers. -Further, the quickstart examines failures and shows the transactional behaviour -in such cases. +|The application deployed to the first {productName} 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 {productName}s. +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` -|An application that receives the remote EJB calls from the `client` application. -This `server` application is deployed to `server2` and `server3`. -The EJB component receives the EJB remote call and, depending on the scenario, -resumes on the transaction propagated in the context of the remote EJB call. -The call inserts data to the database. -The propagated transaction enlists two participants -(the database, and a mock XAResource used for quickstart demonstration purposes). +|The application deployed to the second and third {productName} 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. |=== // Link to the quickstart source @@ -59,50 +52,56 @@ include::../shared-doc/view-the-source.adoc[leveloffset=+1] == Running the Quickstart -The quickstart elaborates on running the example in <<_running_in_a_bare_metal_environment, a bare metal environment>> and on OpenShift. +This quickstart demonstrates its functionalities on <<_running_in_a_bare_metal_environment, bare metal>>, using {productName} Maven plugin, and on OpenShift. // System Requirements include::../shared-doc/system-requirements.adoc[leveloffset=+1] // Use of {jbossHomeName}_1 and {jbossHomeName}_2 include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] -// Run the Quickstart in Red Hat CodeReady Studio or Eclipse -include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1] - == The Goal -Your goal is to set up and start 3 {productName} servers, first deploys the `client` -application the other two configure a cluster and deploy the `server` application. 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, three {productName} servers needs to be configured. Then, the `client` application gets deployed to the first server (`server1`), +while the `server` application gets deployed to the other two {productName} servers (`server2`, and `server3`, which are configured as a cluster). + [[_setup_productname_servers]] === Setup {productName} servers -The easiest way to start multiple instances on a local computer is to copy the {productName} installation directory +The easiest way to start multiple instances of {productName} on a local computer is to copy the {productName} installation directory to three separate directories. -The installation directory for `server1` (`client` application) is named `__{jbossHomeName}_1__`, -for `server2` it is named `__{jbossHomeName}_2__` (`server` application) and for `server3` it is named `__{jbossHomeName}_3__` (`server` application). +The installation directories are named: +* `__{jbossHomeName}_1__` for `server1` +* `__{jbossHomeName}_2__` for `server2` +* `__{jbossHomeName}_3__` for `server3` + +Given that the installation directory of the {productName} is identified with ${jbossHomeName}: [source,sh,subs="+quotes,attributes+"] ---- -# considering the ${jbossHomeName} is installation directory of the {productName} -cp -r ${jbossHomeName} server1 +cp -r ${jbossHomeName} server1; \ {jbossHomeName}_1="$PWD/server1" -cp -r ${jbossHomeName} server2 +---- +[source,sh,subs="+quotes,attributes+"] +---- +cp -r ${jbossHomeName} server2; \ {jbossHomeName}_2="$PWD/server2" -cp -r ${jbossHomeName} server3 +---- +[source,sh,subs="+quotes,attributes+"] +---- +cp -r ${jbossHomeName} server3; \ {jbossHomeName}_3="$PWD/server3" ---- -=== Configure EJB remoting, and authentication of the remote call +=== Creating a user for `server2` and `server3` -To successfully process the remote call from `server1` to either `server2` -or to `server3` you must create a user on the receiver server -that the remote call will be authenticated to. +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. Run the following procedure in the directories `__{jbossHomeName}_2__` and `__{jbossHomeName}_3__` to create the user for `server2` and `server3`. @@ -123,147 +122,172 @@ To represent the user add the following to the server-identities definition > and <<_start_productname_servers, started.>> -. Clean and build the project by navigating to the root directory of this quickstart in terminal and running +. With all {productName} servers <<_setup_productname_servers, configured>> and <<_start_productname_servers, running>>, +the `client` and `server` application can be deployed + +. The whole project can be built using the following commands: + [source,sh,subs="+quotes,attributes+",options="nowrap"] ---- cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/ -mvn clean install +mvn clean package ---- + -. On `server1`, navigate to the `client` subfolder of the `ejb-txn-remote-call` quickstart and deploy the application `war` file. +. Then, the `client` application can be deployed using the following commands: + [source,sh,subs="+quotes,attributes+",options="nowrap"] ---- @@ -271,7 +295,7 @@ cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client mvn wildfly:deploy ---- + -. On `server2` and `server3`, navigate to the `server` subfolder of the `ejb-txn-remote-call` quickstart and deploy the application `war` file. +. Lastly, the `server` application can be deployed using the following commands: + [source,sh,subs="+quotes,attributes+",options="nowrap"] ---- @@ -280,17 +304,14 @@ mvn wildfly:deploy -Dwildfly.port=10090 mvn wildfly:deploy -Dwildfly.port=10190 ---- -The commands should finish without any errors. -The commands connect to running instances of the {productName} -and deploys the `war` archives to the servers. -If an error occurs first verify that the {productName} is running -and that's bound to the correct port. -Then consult the error message details. +The commands just run employed the WildFly Maven plugin to connect to the running instances of {productName} +and deploy the `war` archives to the servers. -If you run the commands then verify -that the deployments are published on the all three servers. +==== Checkpoints -. On to `server1` check the log to confirm that the `client/target/client.war` archive is deployed. +. If errors occur, verify that the {productName} servers are running and that they are configured properly +. Verify that all deployments are published into all three servers +.. On `server1` check the log to confirm that the `client/target/client.war` archive is deployed + [source,options="nowrap"] ---- @@ -299,7 +320,7 @@ INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 76) WFLYUT0 INFO [org.jboss.as.server] (management-handler-thread - 2) WFLYSRV0010: Deployed "client.war" (runtime-name : "client.war") ---- + -. On `server2` and `server3`, check the log to confirm that the `server/target/server.war` archive is deployed. +.. On `server2` and `server3`, check the log to confirm that the `server/target/server.war` archive is deployed. + [source,options="nowrap"] ---- @@ -309,8 +330,8 @@ INFO [org.jboss.as.server] (management-handler-thread - 1) WFLYSRV0010: Deploye ---- . Verify that `server2` and `server3` formed a HA cluster. -Check the server log of either `server2` and `server3`, or both. - +.. Check the server log of either `server2` and `server3`, or both. ++ [source,options="nowrap"] ---- [org.infinispan.CLUSTER] () ISPN000094: Received new cluster view for channel ejb: [server2|1] (2) [server2, server3] @@ -322,32 +343,22 @@ INFO [org.infinispan.CLUSTER] () [Context=server.war/infinispan] ISPN100010: Fi [#_examining_the_quickstart] === Examining the Quickstart -After the {productName} servers are configured and started, and the quickstart artifacts are deployed -you can invoke the methods and examine their results. - -The `client.war` deployed to `server1` exposes several endpoints that invoke -EJB remote invocations to the HA cluster that `server2` and `server3` formed. +Once the {productName} 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 expected behaviour varies depending on type -of the remote call. It depends on running the call as part of the transaction – -then the transaction affinity makes all calls to hit the same server instance. -When the calls go to stateful EJB then the affinity again ensures -the multiple calls hitting the same server instance (the calls to stateful EJB are sticky). -When the call runs against the stateless EJB out of the transaction context then -the calls should be load balanced over the both servers in the HA cluster. -The following table defines the available endpoints, and the expected behaviour -when they are invoked. +The following table defines the available endpoints, and their expected behaviour. [NOTE] ==== -The endpoints return data in JSON format. You can use `curl` for invocation -and `jq` command to format the results. For example: +The endpoints return data in JSON format. You can use `curl` for the invocation +and `jq` for formatting the results. For example: + `curl -s http://localhost:8080/client/remote-outbound-stateless | jq .` ==== [NOTE] ==== -On Windows, the `curl` and `jq` commands might not be available. +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. ==== @@ -409,31 +420,39 @@ eventually. The finalization of work is done in the background [[_details_on_recovery]] ==== Observing the recovery processing after __client/remote-outbound-fail-stateless__ call -The EJB call simulates the presence of an intermittent network error -happening at the commit phase of two-phase commit protocol (2PC). +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 http://jbossts.blogspot.com/2018/01/narayana-periodic-recovery-of-xa.html[transaction recovery manager] -periodically retries to recover the unfinished work. -When it makes the work successfully committed, the transaction is complete, -and the database update will be visible. You can confirm the database update -was processed by issuing REST endpoint reporting number of finished commits. - -You can invoke the endpoint `server/commits` at both servers `server2` and `server3` -where `server` application is deployed (i.e. __http://localhost:8180/server/commits__ -and __http://localhost:8280/server/commits__). -The output of this command is a tuple. It shows the node info, and the number of commits recorded. 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`, +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`. + + +[source] +---- +curl -s http://localhost:8180/server/commits +---- + +[source] +---- +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`. -Transaction recovery manager runs periodically (by default, it runs every 2 minutes) -on all servers. The transaction was initiated on `server1`, -and you will need to wait until is initiated there. +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] ==== -You can speed up the process and invoke the recovery process manually by accessing -the port on which the recovery process listens. -When the https://docs.wildfly.org/22/wildscribe/subsystem/transactions/index.html#attr-recovery-listener[listener is enabled] you can force the recovery to start on demand. -Use `telnet` to send the `SCAN` command to the recovery manager socket at `localhost:4712`. +The recovery process can be started manually. Using `telnet` and connecting to `localhost:4712` +(i.e. the port where https://docs.wildfly.org/22/wildscribe/subsystem/transactions/index.html#attr-recovery-listener[the recovery process is listening to]), +it is possible to send the `SCAN` command to force a recovery cycle [source] ---- @@ -450,26 +469,32 @@ Connection closed by foreign host. [[_steps_to_observe_recovery_processing]] ===== Steps to observe that the recovery processing was done -. Before the executing the __remote-outbound-fail-stateless__ endpoint do verify - how many `commits` are counted on `server2` and `server3` by executing the `/commits` - HTTP endpoints. +. Before invoking the __remote-outbound-fail-stateless__ endpoint, double check + the number of `commits` on `server2` and `server3` by invoking the `server/commits` + endpoints. + [source,sh,subs="+quotes,attributes+",options="nowrap"] ---- curl http://localhost:8180/server/commits; echo -# output: +# output example: # ["host: mydev.narayana.io/192.168.0.1, jboss node name: server2","1"] curl http://localhost:8280/server/commits; echo -# output: +# output example: # ["host: mydev.narayana.io/192.168.0.1, jboss node name: server3","2"] ---- + -. Invoke the HTTP request to __http://localhost:8080/client/remote-outbound-fail-stateless__ +. Invoke the REST endpoint `client/remote-outbound-fail-stateless` ++ +[source,sh,subs="+quotes,attributes+",options="nowrap"] +---- +curl http://localhost:8080/client/remote-outbound-fail-stateless | jq . +---- + -The output prints the name of server the request hits. -Immediately verify the number of commits finished by running the `/commit` HTTP endpoint at that server again. +The JSON output from the previous command reports the name of server the request was sent to. + -. Verify that the number of commits has not changed yet. + +. At the server reported by the previous command, verify the number of `commits` by invoking the `server/commits` endpoint. + . Check the log of `server1` for the following warning message + [source,options="nowrap"] @@ -477,9 +502,9 @@ Immediately verify the number of commits finished by running the `/commit` HTTP 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 ---- + -The message means that the transaction manager was not able to commit the transaction. -An error occurred during committing the transaction on the remote server. -The `XAException.XA_RETRY` exception, meaning an intermittent failure, was reported to the log. +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. . The logs on `server2` or `server3` contain a warning about the `XAResource` failure as well. + [source,options="nowrap"] @@ -487,23 +512,24 @@ The `XAException.XA_RETRY` exception, meaning an intermittent failure, was repor 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 ---- + -. Wait (or force) recovery to be processed at `server1`. -. The number of commits on the targeted server instance has increased by one. +. Wait for the recovery process at `server1` to recover the unfinished transaction (or force a recovery cycle manually) + +. The number of commits on the targeted server should be incremented by one. include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] -Repeat the same for the `server2` and `server3` by navigating -to the quickstart sub-folder `${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/server` and run: +Repeat the last step for `server2` and `server3`: [source,sh,options="nowrap"] ---- -mvn wildfly:undeploy -Dwildfly.port=10090 +cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/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 log includes the following +This quickstart is not production grade. The server logs include the following warnings during the startup. It is safe to ignore these warnings. [source,options="nowrap"] @@ -515,246 +541,236 @@ WFLYELY01084: KeyStore .../standalone/configuration/application.keystore not fou WFLYSRV0018: Deployment "deployment.server.war" is using a private module ("org.jboss.jts") which may be changed or removed in future versions without notice. ---- +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] -== Running on OpenShift +[[build_and_run_the_quickstart_with_provisioned_server]] +== Building and running the quickstart application with provisioned {productName} server -=== OpenShift deployment +Instead of using a standard {productName} server distribution, the three {productName} servers to deploy and run the quickstart can be alternatively provisioned by activating the Maven profile named `provisioned-server` when building the quickstart: -Before deploying this quickstart to OpenShift Container Platform we need to inspect -a bit the platform. The {productName} server runs in a pod. The pod is an ephemeral object -that could be rescheduled, restarted or moved to a different machine by the platform. -The ephemeral nature of the pod is a poor match for the transaction manager handling transactions -and for EJB remoting passing the context as well. -The transaction manager requires a persistent log to be saved -for each {productName} server instance. -The EJB remoting requires a stable remote endpoint for connection to guarantee -the state of stateful beans and the transaction affinity. -The stability of the remote endpoint address is important for transaction -recovery calls to eventually finish the transactions too. -For these properties being guaranteed from the platform -we use _StatefulSet_ object in OpenShift. +[source,sh,subs="+quotes,attributes+",options="nowrap"] +---- +cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client; +mvn clean package -Pprovisioned-server \ + -DremoteServerUsername="quickstartUser" -DremoteServerPassword="quickstartPwd1!" \ + -DpostgresqlUsername="test" -DpostgresqlPassword="test" +---- +[source,sh,subs="+quotes,attributes+",options="nowrap"] +---- +cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/server; +mvn clean package -Pprovisioned-server \ + -Dwildfly.provisioning.dir=server2 -Djboss-as.home=target/server2 \ + -DpostgresqlUsername="test" -DpostgresqlPassword="test"; +mvn package -Pprovisioned-server \ + -Dwildfly.provisioning.dir=server3 -Djboss-as.home=target/server3 \ + -DpostgresqlUsername="test" -DpostgresqlPassword="test" +---- -The recommended way to deploy applications to {productName} is using -the {productName} Operator which utilizes the StatefulSet to manage {productName} -as the default option in the background. +The provisioned {productName} servers, with the quickstart deployed, can then be found in the `target/server` directory, 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. -NOTE: link:../shared-doc/cd-openshift-getting-started.adoc[Other quickstarts discuss deploying] - of the applications with _ReplicaSet_ defined by DeploymentConfig in a template. - It's a different approach that does not match well with the transaction affinity - and cannot be used here. +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. -=== Running on OpenShift: Prerequisites +The quickstart user should be added before running the provisioned server: +[source,subs="+quotes,attributes+",options="nowrap"] +---- +cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/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 `__{jbossHomeName}__\bin\add-user.bat` script. +==== -include::../shared-doc/cd-create-project.adoc[leveloffset=+4] +=== Run the Integration Tests with a provisioned server -[#_running_on_openshift_start_postgresql_database] -==== Running on OpenShift: Start PostgreSQL database +The integration tests included with this quickstart, which verify that the quickstart runs correctly, may also be run with provisioned server. -The quickstart requires the PostgreSQL database to be running. -For testing purposes you can use the provided yaml template -which deploys the database on your OpenShift instance -(usable only for the testing purpose). +Follow these steps to run the integration tests. -[source,sh,options="nowrap",subs="+quotes,attributes+"] +. 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: ++ +[source,sh] ---- -# change path to ${PATH_TO_QUICKSTART_DIR} -cd ${PATH_TO_QUICKSTART_DIR} -# deploy not-production ready XA capable PostgreSQL database to OpenShift -oc new-app --namespace=$(oc project -q) \ - --file=${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client/extensions/postgresql.deployment.yaml +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 ---- -[#_running_on_openshift_build_the_application] -==== Running on OpenShift: Build the application +. Make sure the servers are provisioned by running the commands reported in <> -For building the application the {productName} s2i functionality -(provided out-of-boxy by OpenShift) needs to be used. +. Add the quickstart user to the provisioned `server2` and `server3` by running the commands reported in <> -The {productName} provides `ImageStream` definition of builder images and runtime images. -The builder image makes the application to be built, configure the application server -with s2i scripts. The resulted image may be used for running, -but it's big as it contains many dependencies needed only for the build. -The chain build defines the next step which is to get the runtime image -and copy there the configured {productName} server with the application. - -ifndef::ProductRelease,EAPCDRelease,EAPXPRelease[] -[source,sh,options="nowrap",subs="+quotes,attributes+"] +. Start the {productName} provisioned servers in three distinct terminals, this time using the {productName} Maven Plugin, which is recommended for testing due to simpler automation. ++ +[source,subs="attributes+",options="nowrap"] ---- -# Install builder image streams -oc create -f {ImageandTemplateImportURL}imagestreams/wildfly-centos7.json -# Install runtime image streams -oc create -f {ImageandTemplateImportURL}imagestreams/wildfly-runtime-centos7.json - -# Deploy template with chain build to get the quickstart -# being deployed within runtime image -oc create -f {ImageandTemplateImportURL}templates/wildfly-s2i-chained-build-template.yml +cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client; +mvn wildfly:start -Djboss-as.home=target/server \ + -Dwildfly.javaOpts="-Djboss.tx.node.id=server1 -Djboss.node.name=server1" +---- ++ +[source,subs="attributes+",options="nowrap"] +---- +cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/server; +mvn wildfly:start -Djboss-as.home=target/server2 \ + -Dwildfly.port=10090 \ + -Dwildfly.serverConfig=standalone-ha.xml \ + -Dwildfly.javaOpts="-Djboss.socket.binding.port-offset=100 -Djboss.tx.node.id=server2 -Djboss.node.name=server2" +---- ++ +[source,subs="attributes+",options="nowrap"] +---- +cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/server; +mvn wildfly:start -Djboss-as.home=target/server3 \ + -Dwildfly.port=10190 \ + -Dwildfly.serverConfig=standalone-ha.xml \ + -Dwildfly.javaOpts="-Djboss.socket.binding.port-offset=200 -Djboss.tx.node.id=server3 -Djboss.node.name=server3" ---- -endif::[] -ifdef::ProductRelease,EAPCDRelease,EAPXPRelease[] -[source,sh,options="nowrap",subs="+quotes,attributes+"] +. 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. ++ +[source,subs="attributes+",options="nowrap"] +---- +cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client; +mvn verify -Pintegration-testing +---- ++ +[source,subs="attributes+",options="nowrap"] +---- +cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/server; +mvn verify -Pintegration-testing -Dserver.host="http://localhost:8180/server" +---- ++ +[source,subs="attributes+",options="nowrap"] +---- +cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/server; +mvn verify -Pintegration-testing -Dserver.host="http://localhost:8280/server" ---- -# Install builder and runtime image streams -oc create -f {ImageandTemplateImportURL}{ImagePrefixVersion}-openjdk11-image-stream.json -# Deploy template with chain build to get the quickstart -# being deployed within runtime image -oc create -f {ImageandTemplateImportBaseURL}/master/eap-s2i-build.yaml +. To shut down the {productName} provisioned servers using the {productName} Maven Plugin: ++ +[source,subs="attributes+",options="nowrap"] +---- +mvn wildfly:shutdown +---- ++ +[source,subs="attributes+",options="nowrap"] +---- +mvn wildfly:shutdown -Dwildfly.port=10090 +---- ++ +[source,subs="attributes+",options="nowrap"] ---- +mvn wildfly:shutdown -Dwildfly.port=10190 +---- + endif::[] -The final step for starting the application start -is the `s2i` chain build execution. +== Running on OpenShift + +The ephemeral nature of OpenShift does not work smoothly with {productName}'s ability to handle transactions. +In fact, {productName}'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 {productName} using the {productName}'s Operator, which can employ OpenShift's _StatefulSet_. Failing to do so +might result in no-ACID transactions. + +=== Prerequisites + +include::../shared-doc/cd-create-project.adoc[leveloffset=+3] + +[#_install_operator] +==== Install {productName}'s Operator + +To install {productName}'s Operator, follow the https://github.com/wildfly/wildfly-operator[official documentation] +(which instructions are also reported here for convenience) ifndef::ProductRelease,EAPCDRelease,EAPXPRelease[] [source,sh,options="nowrap",subs="+quotes,attributes+"] ---- -# s2i chain build for client application -oc new-app --template=wildfly-s2i-chained-build-template \ - -p IMAGE_STREAM_NAMESPACE=$(oc project -q) \ - -p APPLICATION_NAME=client \ - -p GIT_REPO={githubRepoUrl} \ - -p GIT_BRANCH={productVersion}.0.0.Final \ - -p GIT_CONTEXT_DIR=ejb-txn-remote-call/client -# s2i chain build for server application -oc new-app --template=wildfly-s2i-chained-build-template \ - -p IMAGE_STREAM_NAMESPACE=$(oc project -q) \ - -p APPLICATION_NAME=server \ - -p GIT_REPO={githubRepoUrl} \ - -p GIT_BRANCH={productVersion}.0.0.Final \ - -p GIT_CONTEXT_DIR=ejb-txn-remote-call/server ----- -endif::[] +cd /tmp +git clone https://github.com/wildfly/wildfly-operator.git -ifdef::ProductRelease,EAPCDRelease,EAPXPRelease[] -[source,sh,options="nowrap",subs="+quotes,attributes+"] ----- -# s2i chain build for client application -oc new-app --template=eap-s2i-build \ - -p EAP_IMAGESTREAM_NAMESPACE=$(oc project -q) \ - -p APPLICATION_IMAGE=client \ - -p SOURCE_REPOSITORY_URL={EAPQuickStartRepo} \ - -p SOURCE_REPOSITORY_REF={EAPQuickStartRepoRef} \ - -p CONTEXT_DIR=ejb-txn-remote-call/client \ - -p EAP_IMAGE={BuildImageStream} \ - -p EAP_RUNTIME_IMAGE={RuntimeImageStream} -# s2i chain build for server application -oc new-app --template=eap-s2i-build \ - -p EAP_IMAGESTREAM_NAMESPACE=$(oc project -q) \ - -p APPLICATION_IMAGE=server \ - -p SOURCE_REPOSITORY_URL={EAPQuickStartRepo} \ - -p SOURCE_REPOSITORY_REF={EAPQuickStartRepoRef} \ - -p CONTEXT_DIR=ejb-txn-remote-call/server \ - -p EAP_IMAGE={BuildImageStream} \ - -p EAP_RUNTIME_IMAGE={RuntimeImageStream} +cd wildfly-operator + +oc adm policy add-cluster-role-to-user cluster-admin developer +make install +make deploy ---- endif::[] -Wait for the builds to finish. You can verify the build status by executing -the `oc get pod` command. - -The expected output, after few whiles, shows that the `*-build` jobs -have got the value `Completed` in the `STATUS` column. +To verify that the {productName} Operator is running, execute the following command: -[source,sh,options="nowrap"] +ifndef::ProductRelease,EAPCDRelease,EAPXPRelease[] +[source,sh,options="nowrap",subs="+quotes,attributes+"] ---- -oc get pod +oc get po -n $(oc project -q) + NAME READY STATUS RESTARTS AGE -client-2-build 0/1 Completed 0 35m -client-build-artifacts-1-build 0/1 Completed 0 45m -server-2-build 0/1 Completed 0 15m -server-build-artifacts-1-build 0/1 Completed 0 19m +wildfly-operator-5d4b7cc868-zfxcv 1/1 Running 1 22h ---- +endif::[] -[#_running_on_openshift_install_productname_operator] -==== Running on OpenShift: Install {productName} Operator - -With the prior step we have got the application image with the server being part of. -The next step is to install the {productName} Operator which is responsible -for managing the life cycle of the application image. +[#_start_postgresql_database] +==== Start a PostgreSQL database -ifndef::ProductRelease,EAPCDRelease,EAPXPRelease[] -Manual installation of the {productName} Operator on OpenShift is summarized in the script -https://github.com/wildfly/wildfly-operator/blob/master/build/run-openshift.sh[build/run-openshift.sh]. +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 +https://github.com/bitnami/charts/tree/main/bitnami/postgresql[bitnami]: -[source,sh] +[source,sh,options="nowrap",subs="+quotes,attributes+"] ---- -git clone https://github.com/wildfly/wildfly-operator/ -./wildfly-operator/build/run-openshift.sh +helm repo add bitnami https://charts.bitnami.com/bitnami +helm install postgresql bitnami/postgresql -f charts/postgresql.yaml --wait --timeout="5m" ---- -endif::[] -ifdef::ProductRelease,EAPCDRelease,EAPXPRelease[] -Consult necessary steps to install the {productName} Operator -at {productName} documentation -https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/ +[#_build_the_application] +=== Build the applications -The following steps can be used as a quickstart guide +To build the `client` and the `server` applications, this quickstart employs +{productName}'s https://github.com/wildfly/wildfly-charts/tree/main[Helm charts]. +For more information about {productName}'s Helm chart, please refer to the official +https://github.com/wildfly/wildfly-charts/blob/main/charts/wildfly/README.md[documentation]. +ifndef::ProductRelease,EAPCDRelease,EAPXPRelease[] [source,sh,options="nowrap",subs="+quotes,attributes+"] ---- -# 1. log in to account with cluster-admin permission -# 2. create a YAML file containing Subscription object -cat >> /tmp/eap-operator-sub.yaml << EOF -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: eap - namespace: openshift-operators -spec: - channel: alpha - installPlanApproval: Automatic - name: eap - source: redhat-operators - sourceNamespace: openshift-marketplace -EOF -# 3. create the Subscription object in the OpenShift -oc apply -f eap-operator-sub.yaml -# 4. verify the openshift-operators namespace that the object was created -oc get csv -n openshift-operators +helm repo add wildfly https://docs.wildfly.org/wildfly-charts/ + +helm install client -f charts/client.yaml wildfly/wildfly +helm install server -f charts/server.yaml wildfly/wildfly ---- endif::[] -[#_running_on_openshift_run_the_quickstart_with_productname_operator] -==== Running on OpenShift: Run the Quickstart with {productName} Operator - -After you install the {productName} Operator, you can deploy the `CustomResource` that uses it. -The `CustomResource.yaml` definition contains information the {productName} Operator uses -to start the application pods for the client application and for the server application. +Wait for the builds to finish. Their status can be verified by executing the `oc get pod` command. -Before deploying the application, ensure the `view` permissions for the default system account -is set up. The `KUBE_PING` protocol, that is used for forming the HA {productName} cluster -on OpenShift, requires `view` permissions to read labels of pods. +[#_deploy_the_quickstart] +=== Deploy the Quickstart -[source,sh] ----- -oc policy add-role-to-user view system:serviceaccount:$(oc project -q):default -n $(oc project -q) ----- +To deploy the `client` and the `server` applications, this quickstart uses the `WildFlyServer` custom resource, +thanks to which the {productName} Operator is able to create a {productName} pod and +deploy an application. -After granting the permissions, deploy the `CustomResource`, managed by {productName} Operator -that, referencing to the <<_running_on_openshift_build_the_application, built application images>>. - -[CAUTION] -==== -Adjust the value of the `applicationImage` value in the OpenShift deployment templates -`${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client/client-cr.yaml` and -`${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/server/server-cr.yaml` -to match the project. It is the most probably {artifactId}-project. -==== +NOTE: Make sure that `view` permissions are granted to the default system account. +The `KUBE_PING` protocol, which is used for forming the HA {productName} 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)` [source,sh,options="nowrap"] ---- -cd ${PATH_TO_QUICKSTART_DIR} - -# deploying client definition, one replica, PostgreSQL database has to be available -oc create -f ejb-txn-remote-call/client/client-cr.yaml -# deploying server definition, two replicas, PostgreSQL database has to be available -oc create -f ejb-txn-remote-call/server/server-cr.yaml +cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call; +oc create -f client/client-cr.yaml; +oc create -f server/server-cr.yaml ---- -If these commands are successful, the `oc get pod` command shows -all the pods required for the quickstart, namely the quickstart client and two -server pods and the PostgreSQL database pod that the application connects to. +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). [source,sh,options="nowrap"] ---- @@ -765,44 +781,23 @@ server-0 1/1 Running 0 11m server-1 1/1 Running 0 11m ---- -To observe the {productName} Operator look at +[#_verify_the_quickstarts] +==== Verify the Quickstarts -ifndef::ProductRelease,EAPCDRelease,EAPXPRelease[] -[source,sh,options="nowrap",subs="+quotes,attributes+"] ----- -oc get po -n $(oc project -q) - -NAME READY STATUS RESTARTS AGE -wildfly-operator-5d4b7cc868-zfxcv 1/1 Running 1 22h ----- -endif::[] - -ifdef::ProductRelease,EAPCDRelease,EAPXPRelease[] -[source,sh,options="nowrap",subs="+quotes,attributes+"] ----- -oc get po -n openshift-operators - -NAME READY STATUS RESTARTS AGE -eap-operator-75c77c789c-2zdnd 1/1 Running 0 86m ----- -endif::[] - -[#_running_on_openshift_verify_the_quickstarts] -==== Running on OpenShift: Verify the Quickstarts - -The {productName} Operator creates routes that make the applications accessible -outside the OpenShift environment. Run the `oc get route` command to find the location of the REST endpoint. +The {productName} 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: [source,sh,options="nowrap"] ---- +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 ---- -For HTTP endpoints provided by the quickstart application -check <>. +With the following commands, it is possible to verify the some functionalities of this quickstart: [source,sh,options="nowrap"] ---- @@ -813,7 +808,9 @@ curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/direct curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/remote-outbound-notx-stateful | jq . ---- -If you like to <<_steps_to_observe_recovery_processing,observe the recovery processing>> +For other HTTP endpoints, refer to <>. + +If you like to <<_steps_to_observe_recovery_processing,observe the recovery process>> then you can follow these shell commands. [source,sh,options="nowrap"] @@ -838,18 +835,38 @@ while true; do done ---- +// TODO: Read the following document to see what can be integrated +//include::../shared-doc/build-and-run-the-quickstart-with-openshift.adoc[leveloffset=+1] + ==== Running on OpenShift: Quickstart application removal -To remove the application you need to remove the `WildFlyServer` definition -(which was deployed by <<_running_on_openshift_run_the_quickstart_with_productname_operator,`*-cr` yaml descriptor>>). -You can do that by running `oc remove WildFlyServer client` -and `oc remove WildFlyServer server`. -With that the application will be stopped, and the pods will be removed. +To delete the `client` and the `server` applications, the `WildFlyServer` definitions needs to be deleted. +This is achievable running: -== Conclusion +[source,sh,options="nowrap"] +---- +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: + +[source,sh,options="nowrap"] +---- +helm uninstall client; +helm uninstall server; +helm uninstall postgresql +---- + +Finally, to undeploy and uninstall the {productName}'s operator: + +[source,sh,options="nowrap"] +---- +cd /tmp/wildfly-operator; +make undeploy; +make uninstall +---- -This quickstarts is a showcase for the EJB remoting calls from one {productName} server -to other with transaction propagation being involved. -It shows things from multiple areas from setting-up the datasources, through security definition -for remote connection, EJB remoting in the application, up to observing the transaction recovery processing. -On top of that it shows running this all in OpenShift managed with {productName} Operator. +The above commands completely clean the OpenShift namespace \ No newline at end of file diff --git a/ejb-txn-remote-call/charts/.helmignore b/ejb-txn-remote-call/charts/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/ejb-txn-remote-call/charts/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/ejb-txn-remote-call/charts/client.yaml b/ejb-txn-remote-call/charts/client.yaml new file mode 100644 index 0000000000..b505fc64db --- /dev/null +++ b/ejb-txn-remote-call/charts/client.yaml @@ -0,0 +1,16 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: ejb-txn-remote-call/client + env: + - name: MAVEN_ARGS_APPEND + value: "-DremoteServerUsername=quickstartUser -DremoteServerPassword=quickstartPwd1! -DpostgresqlUsername=test -DpostgresqlPassword=test" +deploy: + enabled: false + +# TODO try to use an env var to load the postgresql password from the secret defined by the postgresql helm chart +# - name: POSTGRESQL_PASSWORD +# valueFrom: +# secretKeyRef: +# name: postgresql +# key: password \ No newline at end of file diff --git a/ejb-txn-remote-call/charts/postgresql.yaml b/ejb-txn-remote-call/charts/postgresql.yaml new file mode 100644 index 0000000000..75f7504391 --- /dev/null +++ b/ejb-txn-remote-call/charts/postgresql.yaml @@ -0,0 +1,29 @@ +# Overwrites values of the default values.yaml file, +# which is located in the folder where the PostgresSQL +# helm chart [lives] +# (https://github.com/bitnami/charts/tree/main/bitnami/postgresql) +# +# Please, refer to [official Helm's documentation] +# (https://helm.sh/docs/chart_template_guide/values_files/) for +# further information about values overwriting + +global: + postgresql: + auth: + postgresPassword: "test" + username: "test" + password: "test" + database: "test" + +primary: + extendedConfiguration: |- + max_prepared_transactions = 42 + podSecurityContext: + enabled: false + fsGroup: "" + containerSecurityContext: + enabled: false + runAsUser: "auto" + persistence: + enabled: true + size: 2Gi \ No newline at end of file diff --git a/ejb-txn-remote-call/charts/server.yaml b/ejb-txn-remote-call/charts/server.yaml new file mode 100644 index 0000000000..63ae0715be --- /dev/null +++ b/ejb-txn-remote-call/charts/server.yaml @@ -0,0 +1,16 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: ejb-txn-remote-call/server + env: + - name: MAVEN_ARGS_APPEND + value: "-DpostgresqlUsername=test -DpostgresqlPassword=test" +deploy: + enabled: false + +# TODO try to use an env var to load the postgresql password from the secret defined by the postgresql helm chart +# - name: POSTGRESQL_PASSWORD +# valueFrom: +# secretKeyRef: +# name: postgresql +# key: password diff --git a/ejb-txn-remote-call/client/.s2i/environment b/ejb-txn-remote-call/client/.s2i/environment deleted file mode 100644 index 37a3a162e1..0000000000 --- a/ejb-txn-remote-call/client/.s2i/environment +++ /dev/null @@ -1 +0,0 @@ -S2I_IMAGE_SOURCE_MOUNTS=extensions \ No newline at end of file diff --git a/ejb-txn-remote-call/client/client-cr.yaml b/ejb-txn-remote-call/client/client-cr.yaml index db52dee548..b5f2882323 100644 --- a/ejb-txn-remote-call/client/client-cr.yaml +++ b/ejb-txn-remote-call/client/client-cr.yaml @@ -3,35 +3,5 @@ kind: WildFlyServer metadata: name: client spec: - applicationImage: "image-registry.openshift-image-registry.svc:5000/ejb-txn-remote-call-project/client:latest" - replicas: 1 - env: - - name: JAVA_OPTS_APPEND - value: -Dwildfly.config.url=$JBOSS_HOME/standalone/configuration/custom-config.xml - - name: DB_SERVICE_PREFIX_MAPPING - value: test-postgresql=TEST - - name: TEST_NONXA - value: 'false' - - name: TEST_JNDI - value: java:jboss/datasources/ejbJtaDs - - name: TEST_POSTGRESQL_SERVICE_HOST - value: postgresql - - name: TEST_POSTGRESQL_SERVICE_PORT - value: '5432' - - name: TEST_DRIVER - value: postgresql - - name: TEST_DATABASE - valueFrom: - secretKeyRef: - name: postgresql - key: database-name - - name: TEST_USERNAME - valueFrom: - secretKeyRef: - name: postgresql - key: username - - name: TEST_PASSWORD - valueFrom: - secretKeyRef: - name: postgresql - key: password + applicationImage: "client:latest" + replicas: 1 \ No newline at end of file diff --git a/ejb-txn-remote-call/client/extensions/cli.openshift.properties b/ejb-txn-remote-call/client/extensions/cli.openshift.properties deleted file mode 100644 index ae01bf00fa..0000000000 --- a/ejb-txn-remote-call/client/extensions/cli.openshift.properties +++ /dev/null @@ -1,5 +0,0 @@ -remoteServerHost=server-0.server-headless -remoteServerPort=8080 -remoteDeploymentName=server -serverConfig=standalone-openshift.xml -clientMappingsSocketBinding=${env.HOSTNAME}.${env.STATEFULSET_HEADLESS_SERVICE_NAME} diff --git a/ejb-txn-remote-call/client/extensions/install.sh b/ejb-txn-remote-call/client/extensions/install.sh deleted file mode 100644 index 10cfd35e61..0000000000 --- a/ejb-txn-remote-call/client/extensions/install.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# This script (install.sh) will be executed during build 'client-build-artifacts' -# This script copies the CLI scripts to $JBOSS_HOME/extensions to be processed in the post hook -# The post hook part means that on launching of the application server the postconfigure.sh is executed - -set -x -echo "Running ejb-txn-remote-call/client/install.sh" -injected_dir=$1 -# copy any needed files into the target build. -cp -rf ${injected_dir} $JBOSS_HOME/extensions diff --git a/ejb-txn-remote-call/client/extensions/postconfigure.sh b/ejb-txn-remote-call/client/extensions/postconfigure.sh deleted file mode 100644 index 0024e83f77..0000000000 --- a/ejb-txn-remote-call/client/extensions/postconfigure.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -# This script (postconfigure.sh) is executed during launch of the application server (not during the build) -# This script is expected to be copied to $JBOSS_HOME/extensions/ folder by script install.sh - -STANDALONE_XML='standalone-openshift.xml' -POSTCONFIGURE_PROPERTIES_FILE="${JBOSS_HOME}/extensions/cli.openshift.properties" - -# on JBoss EAP with standalone-openshift.xml, on with WildFly standalone.xml -if [ ! -f "${JBOSS_HOME}/standalone/configuration/${STANDALONE_XML}" ]; then - STANDALONE_XML='standalone.xml' - sed -i "s/serverConfig=.*/serverConfig=${STANDALONE_XML}/" "${POSTCONFIGURE_PROPERTIES_FILE}" -fi - -# container does not provide PostgreSQL driver -if [ ! -f "${JBOSS_HOME}/modules/org/postgresql/jdbc/main/module.xml" ]; then - echo "Creating PostgreSQL JDBC module and driver under ${STANDALONE_XML}" - "${JBOSS_HOME}"/bin/jboss-cli.sh "embed-server --server-config=${STANDALONE_XML},\ - module add --name=org.postgresql.jdbc --module-xml=${JBOSS_HOME}/extensions/postgresql-module.xml" - "${JBOSS_HOME}"/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)" -fi - -echo "Executing ejb-txn-remote-call/client ${JBOSS_HOME}/extensions/remote-configuration.cli file with properties file: ${POSTCONFIGURE_PROPERTIES_FILE}." -[ "x$SCRIPT_DEBUG" = "xtrue" ] && cat "${JBOSS_HOME}/extensions/remote-configuration.cli" -"${JBOSS_HOME}"/bin/jboss-cli.sh --file="${JBOSS_HOME}/extensions/remote-configuration.cli" --properties="${POSTCONFIGURE_PROPERTIES_FILE}" - -echo "Using client.war instead of ROOT.war" -if [ -f "${JBOSS_HOME}"/standalone/deployments/ROOT.war ]; then - mv "${JBOSS_HOME}"/standalone/deployments/ROOT.war "${JBOSS_HOME}"/standalone/deployments/client.war -fi \ No newline at end of file diff --git a/ejb-txn-remote-call/client/extensions/postgresql-module.xml b/ejb-txn-remote-call/client/extensions/postgresql-module.xml deleted file mode 100644 index 40dd75cb8b..0000000000 --- a/ejb-txn-remote-call/client/extensions/postgresql-module.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/ejb-txn-remote-call/client/extensions/postgresql.deployment.yaml b/ejb-txn-remote-call/client/extensions/postgresql.deployment.yaml deleted file mode 100644 index 0a827fbd9d..0000000000 --- a/ejb-txn-remote-call/client/extensions/postgresql.deployment.yaml +++ /dev/null @@ -1,75 +0,0 @@ -apiVersion: v1 -kind: Template -metadata: - name: postgresql-template - annotations: - description: "Creating PostgreSQL database" - iconClass: "iconpostgresql" - tags: "database,sql" -parameters: - - description: PostgreSQL image to use - name: POSTGRESQL_IMAGE - value: registry.access.redhat.com/rhscl/postgresql-10-rhel7:latest -labels: - template: "postgresql" -objects: - - apiVersion: v1 - kind: Secret - metadata: - name: postgresql - type: Opaque - stringData: - database-name: test - username: test - password: test - # non-production ready deployment of PostgreSQL to show WildFly quickstarts capabilities - - apiVersion: apps/v1 - kind: Deployment - metadata: - name: postgresql - labels: - app: postgresql - spec: - replicas: 1 - selector: - matchLabels: - app: postgresql - template: - metadata: - labels: - app: postgresql - spec: - containers: - - name: postgresql - image: ${POSTGRESQL_IMAGE} - ports: - - containerPort: 5432 - env: - - name: POSTGRESQL_DATABASE - valueFrom: - secretKeyRef: - key: database-name - name: postgresql - - name: POSTGRESQL_USER - valueFrom: - secretKeyRef: - key: username - name: postgresql - - name: POSTGRESQL_PASSWORD - valueFrom: - secretKeyRef: - key: password - name: postgresql - - name: POSTGRESQL_MAX_PREPARED_TRANSACTIONS - value: "42" - - apiVersion: v1 - kind: Service - metadata: - name: postgresql - spec: - selector: - app: postgresql - ports: - - protocol: TCP - port: 5432 - targetPort: 5432 diff --git a/ejb-txn-remote-call/client/pom.xml b/ejb-txn-remote-call/client/pom.xml index 11454294b1..d2faa93491 100644 --- a/ejb-txn-remote-call/client/pom.xml +++ b/ejb-txn-remote-call/client/pom.xml @@ -36,8 +36,14 @@ The project is the application to be deployed on the client server to call the second server - - 31.0.0.Beta1 + + 30.0.0.Final + + ${version.server} + 4.2.0.Final + 42.7.0 + 5.0.2.Final + 6.0.0.Final @@ -101,7 +107,7 @@ org.wildfly.bom wildfly-ee-with-tools - ${version.server.bom} + ${version.bom.ee} pom import @@ -160,18 +166,204 @@ jakarta.jms jakarta.jms-api + + + org.postgresql + postgresql + ${version.postgresql} + + + + + junit + junit + test + client + + + + org.wildfly.plugins + wildfly-maven-plugin + ${version.plugin.wildfly} + + + maven-war-plugin - ${version.war.plugin} + client false + + + + provisioned-server + + + + org.wildfly.plugins + wildfly-maven-plugin + + client.war + standalone.xml + + + + package + package + + package + + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly:wildfly-datasources-galleon-pack:${version.wildfly-datasources-galleon-pack} + + + + ee-core-profile-server + jaxrs + ejb + jpa + core-tools + + postgresql-driver + + + + + run-script + package + + execute-commands + + + true + target/server + + + + + + scripts/cli.local.properties + + + ${remoteServerUsername} + ${remoteServerPassword} + ${postgresqlUsername} + ${postgresqlPassword} + + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + client.war + standalone.xml + + + + package + package + + package + + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly:wildfly-datasources-galleon-pack:${version.wildfly-datasources-galleon-pack} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.wildfly-cloud-galleon-pack} + + + + cloud-server + jaxrs + ejb + jpa + core-tools + + postgresql-driver + + + + + run-script + package + + execute-commands + + + true + target/server + + + + + + scripts/cli.openshift.properties + + + ${remoteServerUsername} + ${remoteServerPassword} + ${postgresqlUsername} + ${postgresqlPassword} + + + + + + + + + + integration-testing + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + **/*IT + + + + + + integration-test + verify + + + + + + + + diff --git a/ejb-txn-remote-call/client/extensions/cli.local.properties b/ejb-txn-remote-call/client/scripts/cli.local.properties similarity index 73% rename from ejb-txn-remote-call/client/extensions/cli.local.properties rename to ejb-txn-remote-call/client/scripts/cli.local.properties index 77b060a14e..dc57508214 100644 --- a/ejb-txn-remote-call/client/extensions/cli.local.properties +++ b/ejb-txn-remote-call/client/scripts/cli.local.properties @@ -1,5 +1,5 @@ remoteServerHost=127.0.0.1 remoteServerPort=8180 remoteDeploymentName=server +postgresqlServerName=localhost serverConfig=standalone.xml -clientMappingsSocketBinding=127.0.0.1 diff --git a/ejb-txn-remote-call/client/scripts/cli.openshift.properties b/ejb-txn-remote-call/client/scripts/cli.openshift.properties new file mode 100644 index 0000000000..69457dba19 --- /dev/null +++ b/ejb-txn-remote-call/client/scripts/cli.openshift.properties @@ -0,0 +1,6 @@ +remoteServerHost=server-0.server-headless +remoteServerPort=8080 +remoteDeploymentName=server +# This is the service's name of the PostgreSQL database on OpenShift +postgresqlServerName=postgresql +serverConfig=standalone.xml \ No newline at end of file diff --git a/ejb-txn-remote-call/client/scripts/postgresql-datasource.cli b/ejb-txn-remote-call/client/scripts/postgresql-datasource.cli new file mode 100644 index 0000000000..0f35496c13 --- /dev/null +++ b/ejb-txn-remote-call/client/scripts/postgresql-datasource.cli @@ -0,0 +1,27 @@ +# Adding postgresql datasource to the server +# +# NOTE: When running this script using wildfly-maven-plugin, wildfly-datasources-galleon-pack should be added +# to feature-packs and the postgresql-driver layer should be used. + +set serverConfig=${serverConfig} +set postgresqlUsername=${postgresqlUsername} +set postgresqlPassword=${postgresqlPassword} +set postgresqlServerName=${postgresqlServerName} + +# running embeded server with server config +embed-server --server-config=$serverConfig + +xa-data-source add\ + --name=ejbJtaDs\ + --driver-name=postgresql\ + --jndi-name=java:jboss/datasources/ejbJtaDs\ + --user-name=$postgresqlUsername\ + --password=$postgresqlPassword\ + --xa-datasource-properties=ServerName=$postgresqlServerName + +/subsystem=datasources/xa-data-source=ejbJtaDs/xa-datasource-properties=PortNumber:add(value=5432) +/subsystem=datasources/xa-data-source=ejbJtaDs/xa-datasource-properties=DatabaseName:add(value=test) + +echo "postgresql-datasource.cli script finished" + +quit \ No newline at end of file diff --git a/ejb-txn-remote-call/client/extensions/remote-configuration.cli b/ejb-txn-remote-call/client/scripts/remoting-configuration.cli similarity index 77% rename from ejb-txn-remote-call/client/extensions/remote-configuration.cli rename to ejb-txn-remote-call/client/scripts/remoting-configuration.cli index f1c6bbd151..2049c67e34 100644 --- a/ejb-txn-remote-call/client/extensions/remote-configuration.cli +++ b/ejb-txn-remote-call/client/scripts/remoting-configuration.cli @@ -5,17 +5,15 @@ set remoteServerPort=${remoteServerPort} set remoteServerUsername=${remoteServerUsername} set remoteServerPassword=${remoteServerPassword} set serverConfig=${serverConfig} -set clientMappingsSocketBinding=${clientMappingsSocketBinding} # running embeded server with server config embed-server --server-config=$serverConfig /system-property=remote.server.host:add(value=$remoteServerHost) /system-property=remote.server.port:add(value=$remoteServerPort) -/system-property=remote.server.username:add(value=quickstartUser) -/system-property=remote.server.password:add(value=quickstartPwd1!) +/system-property=remote.server.username:add(value=$remoteServerUsername) +/system-property=remote.server.password:add(value=$remoteServerPassword) /system-property=remote.deployment.name:add(value=$remoteDeploymentName) -/system-property=client.mappings.socket.binding:add(value=$clientMappingsSocketBinding) echo "System properties defined" @@ -46,12 +44,6 @@ echo "Transaction recovery listener enabled" # to get detailed insight on what happening during transaction processing switch on the TRACE logging for Narayana # /subsystem=logging/logger=com.arjuna:write-attribute(name=level,value=TRACE) -# needed for ejb client works fine with multiple servers in ha cluster -if (result == undefined) of /socket-binding-group=standard-sockets/socket-binding=http:read-attribute(name=client-mappings) - echo "Configuring server socket binding with client-mappings..." - /socket-binding-group=standard-sockets/socket-binding=http:list-add(name=client-mappings, value={destination-address="${client.mappings.socket.binding}"}) -end-if +echo "remoting-configuration.cli script finished" -echo "remote-configuration.cli script finished" - -quit +quit \ No newline at end of file diff --git a/ejb-txn-remote-call/client/src/main/java/org/jboss/as/quickstarts/ejb/client/RemoteBeanCaller.java b/ejb-txn-remote-call/client/src/main/java/org/jboss/as/quickstarts/ejb/client/RemoteBeanCaller.java index 47f86ec55b..9311ca8b7c 100644 --- a/ejb-txn-remote-call/client/src/main/java/org/jboss/as/quickstarts/ejb/client/RemoteBeanCaller.java +++ b/ejb-txn-remote-call/client/src/main/java/org/jboss/as/quickstarts/ejb/client/RemoteBeanCaller.java @@ -231,7 +231,7 @@ public List remoteOutboundStatefulNoTxBeanCall() throws NamingException *

* The recovery manager runs periodically, by default every 2 minutes. For making the recovery faster * we may force the recovery to be processed. This could be done if the recovery listener is enabled - * (see remote-configuration.cli script). Then it's possible to send command 'SCAN' + * (see remoting-configuration.cli script). Then it's possible to send command 'SCAN' * to socket at port 4712). The unfinished transaction is then finished. *

* diff --git a/ejb-txn-remote-call/client/configuration/custom-config.xml b/ejb-txn-remote-call/client/src/main/resources/META-INF/wildfly-config.xml similarity index 96% rename from ejb-txn-remote-call/client/configuration/custom-config.xml rename to ejb-txn-remote-call/client/src/main/resources/META-INF/wildfly-config.xml index e2ae46beb1..f15cd3b057 100644 --- a/ejb-txn-remote-call/client/configuration/custom-config.xml +++ b/ejb-txn-remote-call/client/src/main/resources/META-INF/wildfly-config.xml @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. --> + diff --git a/ejb-txn-remote-call/client/src/test/java/org/jboss/as/quickstarts/ejb/BasicRuntimeIT.java b/ejb-txn-remote-call/client/src/test/java/org/jboss/as/quickstarts/ejb/BasicRuntimeIT.java new file mode 100644 index 0000000000..ab3810eba5 --- /dev/null +++ b/ejb-txn-remote-call/client/src/test/java/org/jboss/as/quickstarts/ejb/BasicRuntimeIT.java @@ -0,0 +1,69 @@ +/* + * Copyright 2022 JBoss by Red Hat. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.ejb; + +import org.junit.Test; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; + +import static org.junit.Assert.assertEquals; + +/** + * The very basic runtime integration testing. + * @author Emmanuel Hugonnet + * @author emartins + */ +public class BasicRuntimeIT { + + private static final String DEFAULT_SERVER_HOST = "http://localhost:8080/"; + private static final String DEFAULT_APPLICATION = "/client"; + + @Test + public void testHTTPEndpointIsAvailable() throws IOException, InterruptedException, URISyntaxException { + String serverHost = System.getenv("SERVER_HOST"); + if (serverHost == null) { + serverHost = System.getProperty("server.host"); + } + if (serverHost == null) { + serverHost = DEFAULT_SERVER_HOST; + } + testEndpoint(serverHost, DEFAULT_APPLICATION,"/remote-outbound-stateless",200); + testEndpoint(serverHost, DEFAULT_APPLICATION,"/remote-outbound-notx-stateless",200); + testEndpoint(serverHost, DEFAULT_APPLICATION,"/direct-stateless",200); + testEndpoint(serverHost, DEFAULT_APPLICATION,"/direct-stateless-http",200); + testEndpoint(serverHost, DEFAULT_APPLICATION,"/remote-outbound-notx-stateful",200); + testEndpoint(serverHost, DEFAULT_APPLICATION,"/remote-outbound-fail-stateless",200); + } + + private void testEndpoint(String serverHost, String application, String endpoint, int expectedCode) throws URISyntaxException, IOException, InterruptedException { + final HttpRequest request = HttpRequest.newBuilder() + .uri(new URI(serverHost + application + endpoint)) + .GET() + .build(); + final HttpClient client = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.ALWAYS) + .connectTimeout(Duration.ofMinutes(1)) + .build(); + final HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(expectedCode, response.statusCode()); + } +} \ No newline at end of file diff --git a/ejb-txn-remote-call/server/.s2i/environment b/ejb-txn-remote-call/server/.s2i/environment deleted file mode 100644 index 37a3a162e1..0000000000 --- a/ejb-txn-remote-call/server/.s2i/environment +++ /dev/null @@ -1 +0,0 @@ -S2I_IMAGE_SOURCE_MOUNTS=extensions \ No newline at end of file diff --git a/ejb-txn-remote-call/server/extensions/cli.openshift.properties b/ejb-txn-remote-call/server/extensions/cli.openshift.properties deleted file mode 100644 index 3a06e2e134..0000000000 --- a/ejb-txn-remote-call/server/extensions/cli.openshift.properties +++ /dev/null @@ -1 +0,0 @@ -serverConfig=standalone-openshift.xml \ No newline at end of file diff --git a/ejb-txn-remote-call/server/extensions/clustering.cli b/ejb-txn-remote-call/server/extensions/clustering.cli deleted file mode 100644 index c3c458e2ad..0000000000 --- a/ejb-txn-remote-call/server/extensions/clustering.cli +++ /dev/null @@ -1,66 +0,0 @@ -# setup from cli.*.properties -set serverConfig=${serverConfig} - -embed-server --std-out=echo --server-config=$serverConfig - -echo "Adding jgroups extension and subsystem..." - -# adding jgroups extension for clustering may start use kube ping protocol -batch -/socket-binding-group=standard-sockets/socket-binding=jgroups-tcp:add(port=7600) -/extension=org.jboss.as.clustering.jgroups:add() -/subsystem=jgroups:add() -run-batch -batch -/subsystem=jgroups/stack=tcp:add(transport={type=TCP, socket-binding=jgroups-tcp},protocols=[{type=kubernetes.KUBE_PING},{type=MERGE3},{type=FD_SOCK},{type=FD_ALL},{type=VERIFY_SUSPECT},{type=pbcast.NAKACK2},{type=UNICAST3},{type=pbcast.STABLE},{type=pbcast.GMS},{type=MFC},{type=FRAG3}]) -/subsystem=jgroups/channel=ee:add(stack=tcp,cluster=ejb) -/subsystem=jgroups:write-attribute(name=default-channel, value=ee) -run-batch - -echo "Rewriting infinispan caches configuration to dist..." - -# server cache-container -batch -/subsystem=infinispan/cache-container=server:list-add(name=aliases, value="cluster singleton") -/subsystem=infinispan/cache-container=server/transport=jgroups:add(lock-timeout=60000) -/subsystem=infinispan/cache-container=server/local-cache=default:remove -/subsystem=infinispan/cache-container=server/replicated-cache=default:add -/subsystem=infinispan/cache-container=server/replicated-cache=default/component=transaction:add(mode=BATCH) -run-batch - -# ejb cache-container -batch -/subsystem=infinispan/cache-container=ejb/transport=jgroups:add(lock-timeout=60000) -/subsystem=infinispan/cache-container=ejb/distributed-cache=dist:add() -/subsystem=infinispan/cache-container=ejb/distributed-cache=dist/store=file:add() -/subsystem=infinispan/cache-container=ejb:write-attribute(name=default-cache, value=dist) -run-batch -reload --start-mode=admin-only -batch -/subsystem=infinispan/cache-container=ejb/distributed-cache=dist/component=transaction:write-attribute(name=mode,value=BATCH) -/subsystem=infinispan/cache-container=ejb/distributed-cache=dist/component=locking:write-attribute(name=isolation, value=REPEATABLE_READ) -/subsystem=infinispan/cache-container=ejb/local-cache=passivation:remove -run-batch - -# web cache-container -batch -/subsystem=infinispan/cache-container=web/transport=jgroups:add(lock-timeout=60000) -/subsystem=infinispan/cache-container=web/distributed-cache=dist:add() -/subsystem=infinispan/cache-container=web/distributed-cache=dist/store=file:add(passivation=true, purge=false) -/subsystem=infinispan/cache-container=web:write-attribute(name=default-cache, value=dist) -run-batch -batch -/subsystem=infinispan/cache-container=web/distributed-cache=dist/component=transaction:write-attribute(name=mode,value=BATCH) -/subsystem=infinispan/cache-container=web/distributed-cache=dist/component=locking:write-attribute(name=isolation, value=REPEATABLE_READ) -/subsystem=infinispan/cache-container=web/local-cache=passivation:remove -run-batch - -# needed for ejb client works fine with multiple servers in ha cluster -if (result == undefined) of /socket-binding-group=standard-sockets/socket-binding=http:read-attribute(name=client-mappings) - echo "Configuring server socket binding with client-mappings..." - /socket-binding-group=standard-sockets/socket-binding=http:list-add(name=client-mappings, value={destination-address="${env.HOSTNAME}.${env.STATEFULSET_HEADLESS_SERVICE_NAME}"}) -end-if - -echo "clustering.cli script finished" - -quit diff --git a/ejb-txn-remote-call/server/extensions/install.sh b/ejb-txn-remote-call/server/extensions/install.sh deleted file mode 100644 index 93a9e3d73f..0000000000 --- a/ejb-txn-remote-call/server/extensions/install.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -# This script (install.sh) will be executed during build 'server-build-artifacts' -# This script copies the CLI scripts to $JBOSS_HOME/extensions to be processed in the post hook -# The post hook part means that on launching of the application server the postconfigure.sh is executed - -set -x -echo "Running ejb-txn-remote-call/server/install.sh" -injected_dir=$1 -# copy any needed files into the target build. -cp -rf ${injected_dir} $JBOSS_HOME/extensions - diff --git a/ejb-txn-remote-call/server/extensions/postconfigure.sh b/ejb-txn-remote-call/server/extensions/postconfigure.sh deleted file mode 100644 index ea8a5f5e24..0000000000 --- a/ejb-txn-remote-call/server/extensions/postconfigure.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -# This script (postconfigure.sh) is executed during launch of the application server (not during the build) -# This script is expected to be copied to $JBOSS_HOME/extensions/ folder by script install.sh - -STANDALONE_XML='standalone-openshift.xml' -POSTCONFIGURE_PROPERTIES_FILE="${JBOSS_HOME}/extensions/cli.openshift.properties" - -# on JBoss EAP with standalone-openshift.xml, on with WildFly standalone.xml -if [ ! -f "${JBOSS_HOME}/standalone/configuration/${STANDALONE_XML}" ]; then - STANDALONE_XML='standalone.xml' - sed -i "s/serverConfig=.*/serverConfig=${STANDALONE_XML}/" "${POSTCONFIGURE_PROPERTIES_FILE}" -fi - -# container does not provide PostgreSQL driver -if [ ! -f "${JBOSS_HOME}/modules/org/postgresql/jdbc/main/module.xml" ]; then - echo "Creating PostgreSQL JDBC module and driver under ${STANDALONE_XML}" - "${JBOSS_HOME}"/bin/jboss-cli.sh "embed-server --server-config=${STANDALONE_XML},\ - module add --name=org.postgresql.jdbc --module-xml=${JBOSS_HOME}/extensions/postgresql-module.xml" - "${JBOSS_HOME}"/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)" -fi - -echo "Executing ejb-txn-remote-call/server ${JBOSS_HOME}/extensions/clustering.cli file with properties file: ${POSTCONFIGURE_PROPERTIES_FILE}." -[ "x$SCRIPT_DEBUG" = "xtrue" ] && cat "${JBOSS_HOME}/extensions/clustering.cli" -"${JBOSS_HOME}"/bin/jboss-cli.sh --file="${JBOSS_HOME}/extensions/clustering.cli" --properties="${POSTCONFIGURE_PROPERTIES_FILE}" - -echo "Using server.war instead of ROOT.war" -if [ -f "${JBOSS_HOME}"/standalone/deployments/ROOT.war ]; then - mv "${JBOSS_HOME}"/standalone/deployments/ROOT.war "${JBOSS_HOME}"/standalone/deployments/server.war -fi \ No newline at end of file diff --git a/ejb-txn-remote-call/server/extensions/postgresql-module.xml b/ejb-txn-remote-call/server/extensions/postgresql-module.xml deleted file mode 100644 index 40dd75cb8b..0000000000 --- a/ejb-txn-remote-call/server/extensions/postgresql-module.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/ejb-txn-remote-call/server/pom.xml b/ejb-txn-remote-call/server/pom.xml index 2a6edc5982..adc1d69163 100644 --- a/ejb-txn-remote-call/server/pom.xml +++ b/ejb-txn-remote-call/server/pom.xml @@ -36,9 +36,14 @@ The project is the application to be deployed on the second server to receive the call - - 5.13.0.Final - 31.0.0.Beta1 + + 30.0.0.Final + + ${version.server} + 7.0.0.Final + 4.2.0.Final + 5.0.2.Final + 6.0.0.Final @@ -102,7 +107,7 @@ org.wildfly.bom wildfly-ee-with-tools - ${version.server.bom} + ${version.bom.ee} pom import @@ -149,21 +154,206 @@ org.jboss.narayana.jts - narayana-jts-idlj-jakarta + narayana-jts-idlj ${version.narayana} provided + + + + junit + junit + test + server + + + + org.wildfly.plugins + wildfly-maven-plugin + ${version.plugin.wildfly} + + + maven-war-plugin + server false + + ${project.build.directory}/serverWebAppOutput + + + + provisioned-server + + + + org.wildfly.plugins + wildfly-maven-plugin + + server.war + standalone-ha.xml + + + + package + package + + package + + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly:wildfly-datasources-galleon-pack:${version.wildfly-datasources-galleon-pack} + + + + ee-core-profile-server + jaxrs + ejb + ejb-dist-cache + jpa-distributed + core-tools + + postgresql-driver + + + ejb-local-cache + + standalone-ha.xml + + + + run-script + package + + execute-commands + + + true + + + + + scripts/cli.local.properties + + + ${postgresqlUsername} + ${postgresqlPassword} + + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + server.war + + + + package + package + + package + + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly:wildfly-datasources-galleon-pack:${version.wildfly-datasources-galleon-pack} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.wildfly-cloud-galleon-pack} + + + + ee-core-profile-server + jaxrs + ejb + ejb-dist-cache + jpa-distributed + core-tools + + postgresql-driver + + + ejb-local-cache + + + + + run-script + package + + execute-commands + + + true + target/server + + + + + scripts/cli.openshift.properties + + + ${postgresqlUsername} + ${postgresqlPassword} + + + + + + + + + + + integration-testing + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + **/*IT + + + + + + integration-test + verify + + + + + + + + diff --git a/ejb-txn-remote-call/server/extensions/cli.local.properties b/ejb-txn-remote-call/server/scripts/cli.local.properties similarity index 100% rename from ejb-txn-remote-call/server/extensions/cli.local.properties rename to ejb-txn-remote-call/server/scripts/cli.local.properties diff --git a/ejb-txn-remote-call/server/scripts/cli.openshift.properties b/ejb-txn-remote-call/server/scripts/cli.openshift.properties new file mode 100644 index 0000000000..4f5fc93553 --- /dev/null +++ b/ejb-txn-remote-call/server/scripts/cli.openshift.properties @@ -0,0 +1,3 @@ +# This is the service's name of the PostgreSQL database on OpenShift +postgresqlServerName=postgresql +serverConfig=standalone.xml \ No newline at end of file diff --git a/ejb-txn-remote-call/server/scripts/postgresql-datasource.cli b/ejb-txn-remote-call/server/scripts/postgresql-datasource.cli new file mode 100644 index 0000000000..0f35496c13 --- /dev/null +++ b/ejb-txn-remote-call/server/scripts/postgresql-datasource.cli @@ -0,0 +1,27 @@ +# Adding postgresql datasource to the server +# +# NOTE: When running this script using wildfly-maven-plugin, wildfly-datasources-galleon-pack should be added +# to feature-packs and the postgresql-driver layer should be used. + +set serverConfig=${serverConfig} +set postgresqlUsername=${postgresqlUsername} +set postgresqlPassword=${postgresqlPassword} +set postgresqlServerName=${postgresqlServerName} + +# running embeded server with server config +embed-server --server-config=$serverConfig + +xa-data-source add\ + --name=ejbJtaDs\ + --driver-name=postgresql\ + --jndi-name=java:jboss/datasources/ejbJtaDs\ + --user-name=$postgresqlUsername\ + --password=$postgresqlPassword\ + --xa-datasource-properties=ServerName=$postgresqlServerName + +/subsystem=datasources/xa-data-source=ejbJtaDs/xa-datasource-properties=PortNumber:add(value=5432) +/subsystem=datasources/xa-data-source=ejbJtaDs/xa-datasource-properties=DatabaseName:add(value=test) + +echo "postgresql-datasource.cli script finished" + +quit \ No newline at end of file diff --git a/ejb-txn-remote-call/server/server-cr.yaml b/ejb-txn-remote-call/server/server-cr.yaml index 249aea8099..119c26e0a0 100644 --- a/ejb-txn-remote-call/server/server-cr.yaml +++ b/ejb-txn-remote-call/server/server-cr.yaml @@ -3,33 +3,5 @@ kind: WildFlyServer metadata: name: server spec: - applicationImage: "image-registry.openshift-image-registry.svc:5000/ejb-txn-remote-call-project/server:latest" - replicas: 2 - env: - - name: DB_SERVICE_PREFIX_MAPPING - value: test-postgresql=TEST - - name: TEST_NONXA - value: 'false' - - name: TEST_JNDI - value: java:jboss/datasources/ejbJtaDs - - name: TEST_POSTGRESQL_SERVICE_HOST - value: postgresql - - name: TEST_POSTGRESQL_SERVICE_PORT - value: '5432' - - name: TEST_DRIVER - value: postgresql - - name: TEST_DATABASE - valueFrom: - secretKeyRef: - name: postgresql - key: database-name - - name: TEST_USERNAME - valueFrom: - secretKeyRef: - name: postgresql - key: username - - name: TEST_PASSWORD - valueFrom: - secretKeyRef: - name: postgresql - key: password + applicationImage: "server:latest" + replicas: 2 \ No newline at end of file diff --git a/ejb-txn-remote-call/server/src/test/java/org/jboss/as/quickstarts/ejb/BasicRuntimeIT.java b/ejb-txn-remote-call/server/src/test/java/org/jboss/as/quickstarts/ejb/BasicRuntimeIT.java new file mode 100644 index 0000000000..3d5d731fb5 --- /dev/null +++ b/ejb-txn-remote-call/server/src/test/java/org/jboss/as/quickstarts/ejb/BasicRuntimeIT.java @@ -0,0 +1,64 @@ +/* + * Copyright 2022 JBoss by Red Hat. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.ejb; + +import org.junit.Test; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; + +import static org.junit.Assert.assertEquals; + +/** + * The very basic runtime integration testing. + * @author Emmanuel Hugonnet + * @author emartins + */ +public class BasicRuntimeIT { + + private static final String DEFAULT_SERVER_HOST = "http://localhost:8180/server"; + private static final String DEFAULT_APPLICATION = "/server"; + + @Test + public void testHTTPEndpointIsAvailable() throws IOException, InterruptedException, URISyntaxException { + String serverHost = System.getenv("SERVER_HOST"); + if (serverHost == null) { + serverHost = System.getProperty("server.host"); + } + if (serverHost == null) { + serverHost = DEFAULT_SERVER_HOST; + } + testEndpoint(serverHost, DEFAULT_APPLICATION,"/commits",200); + } + + private void testEndpoint(String serverHost, String application, String endpoint, int expectedCode) throws URISyntaxException, IOException, InterruptedException { + final HttpRequest request = HttpRequest.newBuilder() + .uri(new URI(serverHost + application + endpoint)) + .GET() + .build(); + final HttpClient client = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.ALWAYS) + .connectTimeout(Duration.ofMinutes(1)) + .build(); + final HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(expectedCode, response.statusCode()); + } +} \ No newline at end of file