The microprofile-fault-tolerance
quickstart demonstrates how to use Eclipse MicroProfile Fault Tolerance in JBoss EAP XP.
One of the challenges brought by the distributed nature of microservices is that communication with external systems is inherently unreliable. This increases demand on resiliency of applications. To simplify making more resilient applications, JBoss EAP XP contains an implementation of the MicroProfile Fault Tolerance specification.
In this guide, we demonstrate usage of MicroProfile Fault Tolerance annotations such as @Timeout
, @Fallback
,
@Retry
and @CircuitBreaker
. The specification also introduces @Bulkhead
and @Asynchronous
interceptor bindings not
covered in this guide.
Scenario
The application built in this guide simulates a simple backend for a gourmet coffee on-line store. It implements a REST endpoint providing information about coffee samples we have in store.
Let’s imagine, although it’s not implemented as such, that some methods in our endpoint require communication to external services like a database or an external microservice, which introduces a factor of unreliability. This is simulated in our code by intentionally throwing exceptions with certain probability. Then we use the MicroProfile Fault Tolerance annotations to overcome these failures.
Solution
We recommend that you follow the instructions that create the application from scratch. However, you can also deploy the completed example which is available in this directory.
System Requirements
The application this project produces is designed to be run on Red Hat JBoss Enterprise Application Platform expansion pack 2.0 or later.
All you need to build this project is Java 8.0 (Java SDK 1.8) or later and Maven 3.3.1 or later. See Configure Maven to Build and Deploy the Quickstarts to make sure you are configured correctly for testing the quickstarts.
Use of the EAP_HOME and QUICKSTART_HOME Variables
In the following instructions, replace EAP_HOME
with the actual path to your JBoss EAP XP installation. The installation path is described in detail here: Use of EAP_HOME and JBOSS_HOME Variables.
When you see the replaceable variable QUICKSTART_HOME, replace it with the path to the root directory of all of the quickstarts.
Start the JBoss EAP XP Standalone Server
-
Open a terminal and navigate to the root of the JBoss EAP XP directory.
-
Start the JBoss EAP XP server with the MicroProfile profile by typing the following command.
$ EAP_HOME/bin/standalone.sh -c standalone-microprofile.xml
NoteFor Windows, use the EAP_HOME\bin\standalone.bat
script.
Creating an Application from Scratch
In this section we will go through the steps to create a new JAX-RS deployment from scratch and then make it more resilient by using MicroProfile Fault Tolerance annotations.
Project Generation
First, we need to generate a maven project. Open a terminal and create an empty maven project with following command:
mvn archetype:generate \
-DgroupId=org.wildfly.quickstarts.microprofile.faulttolerance \
-DartifactId=microprofile-fault-tolerance \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-webapp \
-DinteractiveMode=false
cd microprofile-fault-tolerance
Now, open the project in your favorite IDE.
pom.xml Updates
Next the project’s pom.xml
should be updated so the dependencies required by this quickstart are
available and so we have a plug-in installed which can deploy the quickstart directly to JBoss EAP XP.
Add the following properties to the pom.xml
:
<version.microprofile.bom>2.0.0.GA</version.microprofile.bom>
<version.server.bom>7.3.4.GA</version.server.bom>
Also the project can be updated to use Java 8 as the minimum:
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
Before the dependencies are defined add the following boms:
<dependencyManagement>
<dependencies>
<!-- importing the jakartaee8-with-tools BOM adds specs and other useful artifacts as managed dependencies -->
<dependency>
<groupId>org.jboss.bom</groupId>
<artifactId>jboss-eap-jakartaee8-with-tools</artifactId>
<version>7.3.4.GA</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- importing the microprofile BOM adds MicroProfile specs -->
<dependency>
<groupId>org.jboss.bom</groupId>
<artifactId>jboss-eap-xp-microprofile</artifactId>
<version>2.0.0.GA</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
By using boms the majority of dependencies used within this quickstart align with the version uses by the application server.
The following dependencies can now be added to the project.
<dependencies>
<dependency>
<groupId>org.eclipse.microprofile.fault-tolerance</groupId>
<artifactId>microprofile-fault-tolerance-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
Note that all dependencies have the scope provided
.
As we are going to be deploying this application to the JBoss EAP XP server, let’s also add a maven plugin that will simplify working with the application server. Add the following section under configuration:
<build>
<plugins>
...
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Setup the required repositories (if you don’t have them set up globally):
<repositories>
<repository>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
<id>jboss-public-repository-group</id>
<name>JBoss Public Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/public</url>
<layout>default</layout>
</repository>
<repository>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
<id>jboss-enterprise-maven-repository</id>
<name>JBoss Enterprise Maven Repository</name>
<url>https://maven.repository.redhat.com/ga/</url>
<layout>default</layout>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>jboss-public-repository-group</id>
<name>JBoss Public Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/public</url>
</pluginRepository>
<pluginRepository>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>jboss-enterprise-maven-repository</id>
<name>JBoss Enterprise Maven Repository</name>
<url>https://maven.repository.redhat.com/ga/</url>
</pluginRepository>
</pluginRepositories>
Now we are ready to start developing an application with MicroProfile Fault Tolerance capabilities.
Preparing an Application: REST Endpoint and CDI Bean
In this section we create a skeleton of our application, so that we have something that we can extend and to which we can add fault tolerance features later on.
First, create a simple entity representing a coffee sample in our store:
package org.wildfly.quickstarts.microprofile.faulttolerance;
public class Coffee {
public Integer id;
public String name;
public String countryOfOrigin;
public Integer price;
public Coffee() {
}
public Coffee(Integer id, String name, String countryOfOrigin, Integer price) {
this.id = id;
this.name = name;
this.countryOfOrigin = countryOfOrigin;
this.price = price;
}
}
Now, lets expose our JAX-RS application at the context path:
package org.wildfly.quickstarts.microprofile.faulttolerance;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/")
public class CoffeeApplication extends Application {
}
Let’s continue with a simple CDI bean, that would work as a repository of our coffee samples.
package org.wildfly.quickstarts.microprofile.faulttolerance;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class CoffeeRepositoryService {
private Map<Integer, Coffee> coffeeList = new HashMap<>();
public CoffeeRepositoryService() {
coffeeList.put(1, new Coffee(1, "Fernandez Espresso", "Colombia", 23));
coffeeList.put(2, new Coffee(2, "La Scala Whole Beans", "Bolivia", 18));
coffeeList.put(3, new Coffee(3, "Dak Lak Filter", "Vietnam", 25));
}
public List<Coffee> getAllCoffees() {
return new ArrayList<>(coffeeList.values());
}
public Coffee getCoffeeById(Integer id) {
return coffeeList.get(id);
}
public List<Coffee> getRecommendations(Integer id) {
if (id == null) {
return Collections.emptyList();
}
return coffeeList.values().stream()
.filter(coffee -> !id.equals(coffee.id))
.limit(2)
.collect(Collectors.toList());
}
}
Finally, create the org.wildfly.quickstarts.microprofile.faulttolerance.CoffeeResource
class as follows:
package org.wildfly.quickstarts.microprofile.faulttolerance;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jboss.logging.Logger;
@Path("/coffee")
@Produces(MediaType.APPLICATION_JSON)
public class CoffeeResource {
private static final Logger LOGGER = Logger.getLogger(CoffeeResource.class);
@Inject
private CoffeeRepositoryService coffeeRepository;
private AtomicLong counter = new AtomicLong(0);
@GET
public List<Coffee> coffees() {
final Long invocationNumber = counter.getAndIncrement();
maybeFail(String.format("CoffeeResource#coffees() invocation #%d failed", invocationNumber));
LOGGER.infof("CoffeeResource#coffees() invocation #%d returning successfully", invocationNumber);
return coffeeRepository.getAllCoffees();
}
private void maybeFail(String failureLogMessage) {
if (new Random().nextBoolean()) {
LOGGER.error(failureLogMessage);
throw new RuntimeException("Resource failure.");
}
}
}
At this point, we expose a single REST method that will show a list of coffee samples in a JSON format. Note
that we introduced some fault making code in our CoffeeResource#maybeFail()
method, which is going to cause failures
in the CoffeeResource#coffees()
endpoint method in about 50% of requests.
Build and Deploy the Initial Application
Let’s check that our application works!
-
Make sure the JBoss EAP XP server is started as described above.
-
Open new terminal and navigate to the root directory of your project.
-
Type the following command to build and deploy the project:
mvn clean package wildfly:deploy
Then, open http://localhost:8080/microprofile-fault-tolerance/coffee
in your browser and make a couple of requests.
Some requests should show us the list of our coffee samples in JSON, the rest will fail
with a RuntimeException
thrown in CoffeeResource#maybeFail()
.
Adding Resiliency: Retries
Let the JBoss EAP XP server running and in your IDE add the @Retry
annotation to the CoffeeResource#coffees()
method as follows and save the file:
import org.eclipse.microprofile.faulttolerance.Retry;
...
public class CoffeeResource {
...
@GET
@Retry(maxRetries = 4)
public List<Coffee> coffees() {
...
}
...
}
Rebuild and redeploy the application in JBoss EAP XP server:
mvn wildfly:deploy
You can reload the page couple more times. Practically all requests should now be succeeding. The CoffeeResource#coffees()
method is still in fact failing in about 50% of cases, but every time it happens the platform automatically retries
the call!
To see that the failures still happen, check the output of the development server. The log messages should be similar to these:
18:29:20,901 ERROR [org.wildfly.quickstarts.microprofile.faulttolerance.CoffeeResource] (default task-3) CoffeeResource#coffees() invocation #0 failed
18:29:20,901 INFO [org.wildfly.quickstarts.microprofile.faulttolerance.CoffeeResource] (default task-3) CoffeeResource#coffees() invocation #1 returning successfully
18:29:21,315 ERROR [org.wildfly.quickstarts.microprofile.faulttolerance.CoffeeResource] (default task-3) CoffeeResource#coffees() invocation #0 failed
18:29:21,337 ERROR [org.wildfly.quickstarts.microprofile.faulttolerance.CoffeeResource] (default task-3) CoffeeResource#coffees() invocation #1 failed
18:29:21,502 ERROR [org.wildfly.quickstarts.microprofile.faulttolerance.CoffeeResource] (default task-3) CoffeeResource#coffees() invocation #2 failed
18:29:21,654 INFO [org.wildfly.quickstarts.microprofile.faulttolerance.CoffeeResource] (default task-3) CoffeeResource#coffees() invocation #3 returning successfully
You can see that every time an invocation fails, it’s immediately followed by another invocation, until one succeeds. Since we allowed 4 retries, it would require 5 invocations to fail in a row, in order for the user to be actually exposed to a failure. That is fairly unlikely to happen.
Adding Resiliency: Timeouts
So what else have we got in MicroProfile Fault Tolerance? Let’s look into timeouts.
Add following two methods to our CoffeeResource
endpoint and deploy onto the running server.
import org.jboss.resteasy.annotations.jaxrs.PathParam;
import org.eclipse.microprofile.faulttolerance.Timeout;
...
public class CoffeeResource {
...
@GET
@Path("/{id}/recommendations")
@Timeout(250)
public List<Coffee> recommendations(@PathParam("id") int id) {
long started = System.currentTimeMillis();
final long invocationNumber = counter.getAndIncrement();
try {
randomDelay();
LOGGER.infof("CoffeeResource#recommendations() invocation #%d returning successfully", invocationNumber);
return coffeeRepository.getRecommendations(id);
} catch (InterruptedException e) {
LOGGER.errorf("CoffeeResource#recommendations() invocation #%d timed out after %d ms",
invocationNumber, System.currentTimeMillis() - started);
return null;
}
}
private void randomDelay() throws InterruptedException {
Thread.sleep(new Random().nextInt(500));
}
}
Rebuild and redeploy the application:
mvn wildfly:deploy
We added some new functionality. We want to be able to recommend some related coffees based on a coffee that a user is currently looking at. It’s not a critical functionality, it’s a nice-to-have. When the system is overloaded, and the logic behind obtaining recommendations takes too long to execute, we would rather time out and render the UI without recommendations.
Note that the timeout was configured to 250 ms, and a random artificial delay between 0 and 500 ms was introduced
into the CoffeeResource#recommendations()
method.
In your browser, go to http://localhost:8080/microprofile-fault-tolerance/coffee/2/recommendations
and hit reload a couple of times.
You should see some requests time out with org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException
.
Requests that do not time out should show two recommended coffee samples in JSON.
Adding Resiliency: Fallbacks
Let’s improve the recommendations feature by providing a fallback functionality for the case when a timeout happens.
Add a fallback method to CoffeeResource
and a @Fallback
annotation to CoffeeResource#recommendations()
method
as follows:
import java.util.Collections;
import org.eclipse.microprofile.faulttolerance.Fallback;
...
public class CoffeeResource {
...
@Fallback(fallbackMethod = "fallbackRecommendations")
public List<Coffee> recommendations(@PathParam("id") int id) {
...
}
public List<Coffee> fallbackRecommendations(int id) {
LOGGER.info("Falling back to RecommendationResource#fallbackRecommendations()");
// safe bet, return something that everybody likes
return Collections.singletonList(coffeeRepository.getCoffeeById(1));
}
...
}
Rebuild and redeploy the application.
Hit reload several times on http://localhost:8080/microprofile-fault-tolerance/coffee/2/recommendations
.
The TimeoutException
should not appear anymore. Instead, in case of a timeout, the page will
display a single recommendation that we hardcoded in our fallback method fallbackRecommendations()
, rather than
two recommendations returned by the original method.
Check the server output to see that fallback is really happening:
18:36:01,873 INFO [org.wildfly.quickstarts.microprofile.faulttolerance.CoffeeResource] (default task-3) CoffeeResource#recommendations() invocation #0 returning successfully
18:36:02,705 ERROR [org.wildfly.quickstarts.microprofile.faulttolerance.CoffeeResource] (default task-3) CoffeeResource#recommendations() invocation #0 timed out after 253 ms
18:36:02,706 INFO [org.wildfly.quickstarts.microprofile.faulttolerance.CoffeeResource] (default task-3) Falling back to RecommendationResource#fallbackRecommendations()
Note
|
The fallback method is required to have the same parameters as the original method. |
Adding Resiliency: Circuit Breakers
A circuit breaker is useful for limiting number of failures happening in the system, when part of the system becomes temporarily unstable. The circuit breaker records successful and failed invocations of a method, and when the ratio of failed invocations reaches the specified threshold, the circuit breaker opens and blocks all further invocations of that method for a given time.
Add the following code into the CoffeeRepositoryService
bean, so that we can demonstrate a circuit breaker in action:
import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
...
public class CoffeeRepositoryService {
...
private AtomicLong counter = new AtomicLong(0);
@CircuitBreaker(requestVolumeThreshold = 4)
public Integer getAvailability(Coffee coffee) {
maybeFail();
return new Random().nextInt(30);
}
private void maybeFail() {
// introduce some artificial failures
final Long invocationNumber = counter.getAndIncrement();
if (invocationNumber % 4 > 1) { // alternate 2 successful and 2 failing invocations
throw new RuntimeException("Service failed.");
}
}
}
and inject the code below into the CoffeeResource
endpoint:
public class CoffeeResource {
...
@Path("/{id}/availability")
@GET
public Response availability(@PathParam("id") int id) {
final Long invocationNumber = counter.getAndIncrement();
Coffee coffee = coffeeRepository.getCoffeeById(id);
// check that coffee with given id exists, return 404 if not
if (coffee == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
try {
Integer availability = coffeeRepository.getAvailability(coffee);
LOGGER.infof("CoffeeResource#availability() invocation #%d returning successfully", invocationNumber);
return Response.ok(availability).build();
} catch (RuntimeException e) {
String message = e.getClass().getSimpleName() + ": " + e.getMessage();
LOGGER.errorf("CoffeeResource#availability() invocation #%d failed: %s", invocationNumber, message);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(message)
.type(MediaType.TEXT_PLAIN_TYPE)
.build();
}
}
...
}
Rebuild and redeploy the application.
We added another functionality - the application can return the amount of remaining packages of given coffee on our store (just a random number).
This time an artificial failure was introduced in the CDI bean: the CoffeeRepositoryService#getAvailability()
method is
going to alternate between two successful and two failed invocations.
We also added a @CircuitBreaker
annotation with requestVolumeThreshold = 4
. CircuitBreaker.failureRatio
is
by default 0.5, and CircuitBreaker.delay
is by default 5 seconds. That means that a circuit breaker will open
when 2 of the last 4 invocations failed. It will stay open for 5 seconds.
To test this out, do the following:
-
Go to
http://localhost:8080/microprofile-fault-tolerance/coffee/2/availability
in your browser. You should see a number being returned. -
Hit reload, this second request should again be successful and return a number.
-
Reload two more times. Both times you should see text "RuntimeException: Service failed.", which is the exception thrown by
CoffeeRepositoryService#getAvailability()
. -
Reload a couple more times. Unless you waited too long, you should again see exception, but this time it’s "CircuitBreakerOpenException: getAvailability". This exception indicates that the circuit breaker opened, and the
CoffeeRepositoryService#getAvailability()
method is not being called anymore. -
Give it 5 seconds during which circuit breaker should close. You should be able to make two successful requests again.
Working with the Completed Quickstart
This section shows how to work with the complete quickstart.
Build and Deploy the Quickstart
-
Make sure you start the JBoss EAP XP server as described above.
-
Open a terminal and navigate to the root directory of this quickstart.
-
Type the following command to build the artifacts.
$ mvn clean package wildfly:deploy
This deploys the microprofile-fault-tolerance/target/microprofile-fault-tolerance.war
to the running instance of the server.
You should see a message in the server log indicating that the archive deployed successfully.
Test the Deployed Application
You can visit following URLs in your browser:
-
http://localhost:8080/microprofile-fault-tolerance/coffee
This URL should almost always return a response with JSON data. Even though internally the endpoint fails in about 50% of cases (you can see those errors in the server log), it uses automatic retries to mitigate these failures.
See details in the section Adding More Resiliency: Retries.
-
http://localhost:8080/microprofile-fault-tolerance/coffee/1/recommendations
This endpoint also fails in about 50% of cases, but it uses fallback strategy to provide an alternative response if normal processing failed. As a result the response will either contain a JSON list with several items in it (a successful response) or just a single item in it (a fallback response).
See details in sections Adding More Resiliency: Timeouts and Adding More Resiliency: Fallbacks.
-
http://localhost:8080/microprofile-fault-tolerance/coffee/1/availability
This endpoint demonstrates the use of a circuit breaker. It returns a sequence of two successful responses, followed by a sequence of two failed ones. After that, the circuit breaker will open and will block all further request processing for the duration of 5 seconds.
See details in the section Adding More Resiliency: Cirquit Breakers.
Undeploy the Quickstart
When you are finished testing the quickstart, follow these steps to undeploy the archive.
-
Make sure you start the JBoss EAP XP server as described above.
-
Open a terminal and navigate to the root directory of this quickstart.
-
Type this command to undeploy the archive:
$ mvn wildfly:undeploy
Run the Arquillian Tests
This quickstart provides Arquillian tests. By default, these tests are configured to be skipped since Arquillian tests require the use of a container.
Note
|
The Arquillian tests deploy the application, so make sure you undeploy the quickstart before you begin. |
Follow these steps to run the tests.
-
Start the JBoss EAP XP server as described above.
-
Open a terminal and navigate to the root directory of this quickstart.
-
Type the following command to run the
verify
goal with thearq-remote
profile activated.$ mvn clean verify -Parq-remote
Note
|
You can also let Arquillian manage the JBoss EAP XP server by using the |
Run the Quickstart in Red Hat CodeReady Studio or Eclipse
You can also start the server and deploy the quickstarts or run the Arquillian tests in Red Hat CodeReady Studio or from Eclipse using JBoss tools. For general information about how to import a quickstart, add a JBoss EAP XP server, and build and deploy a quickstart, see Use Red Hat CodeReady Studio or Eclipse to Run the Quickstarts.
Getting Started with JBoss EAP for OpenShift
The following sections contains the basic instructions to build and deploy this quickstart to JBoss EAP for OpenShift.
See Getting Started with JBoss EAP for OpenShift Container Platform for more detailed information about building and running applications on JBoss EAP for OpenShift.
Prepare OpenShift for Quickstart Deployment
-
Log in to your OpenShift instance using the
oc login
command. -
Create a new project for the quickstart in OpenShift. You can create a project in OpenShift using the following command.
$ oc new-project microprofile-fault-tolerance-project
Before you can import and use the OpenShift image for JBoss EAP for OpenShift , you must configure authentication to the Red Hat Container Registry.
Create an authentication token using a registry service account to configure access to the Red Hat Container Registry. You need not use or store your Red Hat account’s username and password in your OpenShift configuration when you use an authentication token.
-
Follow the instructions on Red Hat Customer Portal to create an authentication token using a registry service account.
-
Download the YAML file containing the OpenShift secret for the token.
You can download the YAML file from the OpenShift Secret tab on your token’s Token Information page.
-
Create the authentication token secret for your OpenShift project using the YAML file that you downloaded:
oc create -f 1234567_myserviceaccount-secret.yaml
-
Configure the secret for your OpenShift project using the following commands, replacing the secret name below with the name of your secret created in the previous step.
oc secrets link default 1234567-myserviceaccount-pull-secret --for=pull oc secrets link builder 1234567-myserviceaccount-pull-secret --for=pull
Import the Latest JBoss EAP for OpenShift Image Streams and Templates
Important
|
If you are building and deploying this quickstart on JBoss EAP for OpenShift, you must configure authentication to the Red Hat Container Registry before you import the image streams and templates into your namespace. Getting Started with JBoss EAP for OpenShift Container Platform provides an example of one way to configure authentication to the registry. For additional information, see Red Hat Container Registry Authentication on the Red Hat Customer Portal. Configuration of authentication to the registry is not necessary if you are building and deploying this quickstart on JBoss EAP for OpenShift Online. |
-
Use the following commands to import the latest JDK 8 and JDK 11 image streams and templates for the OpenShift image for JBoss EAP for OpenShift, into your OpenShift project’s namespace.
-
Import JDK 8 image streams:
oc replace --force -f https://raw.githubusercontent.com/jboss-container-images/jboss-eap-openshift-templates/eap-xp2/jboss-eap-xp2-openjdk8-openshift.json
This command imports the following imagestreams and templates:
-
The JDK 8 builder imagestream: jboss-eap-xp2-openjdk8-openshift
-
The JDK 8 runtime imagestream: jboss-eap-xp2-openjdk8-runtime-openshift
-
-
Import JDK 11 image stream:
oc replace --force -f https://raw.githubusercontent.com/jboss-container-images/jboss-eap-openshift-templates/eap-xp2/jboss-eap-xp2-openjdk11-openshift.json
This command imports the following imagestreams and templates:
-
The JDK 11 builder imagestream: jboss-eap-xp2-openjdk11-openshift
-
The JDK 11 runtime imagestream: jboss-eap-xp2-openjdk11-runtime-openshift
-
-
Import the JDK 8 and JDK 11 templates:
for resource in \ eap-xp2-basic-s2i.json \ eap-xp2-third-party-db-s2i.json do oc replace --force -f \ https://raw.githubusercontent.com/jboss-container-images/jboss-eap-openshift-templates/eap-xp2/templates/${resource} done
-
Note
|
The JBoss EAP image streams and templates imported using the above command are only available within that OpenShift project. If you have administrative access to the general ... oc replace -n openshift --force -f \ ... |
Deploy the JBoss EAP Source-to-Image (S2I) Quickstart to OpenShift
-
Create a new OpenShift application using the JBoss EAP for OpenShift image and the quickstart’s source code. Use the following command to use the
eap-xp2-basic-s2i
template with the JDK 8 images and themicroprofile-fault-tolerance
source code on GitHub.$ oc new-app --template=eap-xp2-basic-s2i \ -p EAP_IMAGE_NAME=jboss-eap-xp2-openjdk8-openshift:latest \ -p EAP_RUNTIME_IMAGE_NAME=jboss-eap-xp2-openjdk8-runtime-openshift:latest \ -p IMAGE_STREAM_NAMESPACE="microprofile-fault-tolerance-project" \ -p SOURCE_REPOSITORY_URL="https://github.com/jboss-developer/jboss-eap-quickstarts" \ -p SOURCE_REPOSITORY_REF="xp-2.0.x" \ -p CONTEXT_DIR="microprofile-fault-tolerance"
-
--template
The template to use. -
-p IMAGE_STREAM_NAMESPACE
The latest images streams and templates were imported into the project’s namespace, so you must specify the namespace of where to find the image stream. This is usually the OpenShift project’s name. -
-p SOURCE_REPOSITORY_URL
The URL to the repository containing the application source code. -
-p SOURCE_REPOSITORY_REF
The Git repository reference to use for the source code. This can be a Git branch or tag reference. -
-p CONTEXT_DIR
The directory within the source repository to build.
Alternatively, to create the quickstart application using the JDK 11 images enter the following command.
$ oc new-app --template=eap-xp2-basic-s2i \ -p EAP_IMAGE_NAME=jboss-eap-xp2-openjdk11-openshift:latest \ -p EAP_RUNTIME_IMAGE_NAME=jboss-eap-xp2-openjdk11-runtime-openshift:latest \ -p IMAGE_STREAM_NAMESPACE="microprofile-fault-tolerance-project" \ -p SOURCE_REPOSITORY_URL="https://github.com/jboss-developer/jboss-eap-quickstarts" \ -p SOURCE_REPOSITORY_REF="xp-2.0.x" \ -p CONTEXT_DIR="microprofile-fault-tolerance"
-
--template
The template to use. -
-p IMAGE_STREAM_NAMESPACE
The latest images streams and templates were imported into the project’s namespace, so you must specify the namespace of where to find the image stream. This is usually the OpenShift project’s name. -
-p SOURCE_REPOSITORY_URL
The URL to the repository containing the application source code. -
-p SOURCE_REPOSITORY_REF
The Git repository reference to use for the source code. This can be a Git branch or tag reference. -
-p CONTEXT_DIR
The directory within the source repository to build.
NoteA template can specify default values for many template parameters, and you might have to override some, or all, of the defaults. To see template information, including a list of parameters and any default values, use the command oc describe template TEMPLATE_NAME
.TipIt is possible to trim down the JBoss EAP for OpenShift image that will be used to run this quickstart. To do so, please add the -p GALLEON_PROVISION_LAYERS=<galleon layers>
argument when creating the new application. Please refer to the JBoss EAP documentation for the list of supported galleon layers. -
-
Retrieve the name of the build configuration.
$ oc get bc -o name
-
Use the name of the build configurations from the previous step to view the Maven progress of the builds.
$ oc logs -f bc/${APPLICATION_NAME}-build-artifacts … Push successful $ oc logs -f bc/${APPLICATION_NAME} … Push successful
For example, for the previously created application, the following command shows the progress of the Maven builds.
$ oc logs -f bc/eap-xp2-basic-app-build-artifacts … Push successful $ oc logs -f bc/eap-xp2-basic-app … Push successful
OpenShift Post Deployment Tasks
Depending on your application, you might need to complete some tasks after your OpenShift application has been built and deployed.
Examples of post-deployment tasks include the following:
-
Exposing a service so that the application is viewable from outside of OpenShift.
-
Scaling your application to a specific number of replicas.
-
Get the service name of your application using the following command.
$ oc get service
-
Optional: Expose the main service as a route so you can access your application from outside of OpenShift. For example, for the previously created application, use the following command to expose the required service and port.
NoteIf you used a template to create the application, the route might already exist. If it does, continue on to the next step.
$ oc expose service/eap-xp2-basic-app --port=8080
-
Get the URL of the route.
$ oc get route
-
Access the application in your web browser using the URL. The URL is the value of the
HOST/PORT
field from previous command’s output.NoteFor example, to interact with this quickstart , the root of its application URLs should be
https://HOST_PORT_Value/
. -
Optionally, you can scale up the application instance by running the following command. This command increases the number of replicas to 3.
$ oc scale deploymentconfig DEPLOYMENTCONFIG_NAME --replicas=3
For example, for this` quickstart, use the following command to scale up the application.
$ oc scale deploymentconfig/eap-xp2-basic-app --replicas=3
Building and running the quickstart application in a bootable JAR
You can package a JBoss EAP XP server and an application inside a bootable JAR. You can then run the application on a JBoss EAP XP bare-metal platform or on a JBoss EAP XP Openshift platform.
On a JBoss EAP XP bare-metal platform
You can use the Maven plug-in to build a JBoss EAP XP bootable JAR, and then you can run the application on a JBoss EAP XP bare-metal platform. The following example demonstrates a quickstart pom.xml
file that contains a Maven profile named bootable-jar:
<profile>
<id>bootable-jar</id>
<build>
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-jar-maven-plugin</artifactId>
<configuration>
<feature-pack-location>org.jboss.eap:wildfly-galleon-pack:${version.server.bootable-jar}</feature-pack-location>
<layers>
<layer>jaxrs-server</layer>
<layer>microprofile-platform</layer>
</layers>
</configuration>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
-
Build the quickstart bootable JAR with the following command:
$ mvn clean package -Pbootable-jar
-
Run the quickstart application contained in the bootable JAR:
$ java -jar target/microprofile-fault-tolerance-bootable.jar
-
You can now interact with the quickstart application.
Note
|
After the quickstart application is deployed, the bootable JAR includes the application in the root context. Therefore, any URLs related to the application should not have the |
On a JBoss EAP XP OpenShift platform
You can use the Maven plug-in to build a JBoss EAP XP bootable JAR, and then you can run the application on a JBoss EAP XP OpenShift platform. The following example demonstrates a quickstart pom.xml
file that contains a Maven profile named bootable-jar-openshift:
<profile>
<id>bootable-jar-openshift</id>
<build>
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-jar-maven-plugin</artifactId>
<configuration>
<feature-pack-location>org.jboss.eap:wildfly-galleon-pack:${version.server.bootable-jar}</feature-pack-location>
<layers>
<layer>jaxrs-server</layer>
<layer>microprofile-platform</layer>
</layers>
<cloud/>
</configuration>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>openshift-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>resource</goal>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<enricher>
<config>
<jkube-service>
<type>NodePort</type>
</jkube-service>
</config>
</enricher>
</configuration>
</plugin>
</plugins>
</build>
</profile>
-
Log in to your OpenShift instance using the
oc login
command. -
Create a new project for the quickstart bootable JAR on OpenShift. For example:
$ oc new-project bootable-jar-project
-
Build the quickstart bootable JAR by issuing the following command. This command also completes the following tasks: creates the OpenShift deployment, service and route; generates a docker image and pushes the docker image to OpenShift; and runs the application.
$ mvn oc:deploy -Pbootable-jar-openshift
-
Get the URL of the route.
$ oc get route
-
Access the application in your web browser by using a URL. The URL is the value of the
HOST/PORT
field that was provided by theoc get route
command output. For example, the route of the URL for the quickstart used in this procedure ishttps://HOST_PORT_Value/
.
Customizing OpenShift resources with resource fragments
With the Eclipse JKube Maven plug-in, you can customize the generated OpenShift resources, such as deployments, routes, and so on, with YAML file extracts located in the src/main/jkube directory.
The route.yml
file, which is located in the src/main/jkube directory, is an example of a resource fragment. You can configure this resource fragment to change the Openshift application service route to use HTTPS:
spec: tls: insecureEdgeTerminationPolicy: Redirect termination: edge to: kind: Service name: microprofile-fault-tolerance
For more information about resource fragments, see the Eclipse JKube documentation.
Conclusion
MicroProfile Fault Tolerance allows improving resiliency of your application, without having an impact on the complexity of our business logic.