You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jg...@apache.org on 2019/06/26 10:13:59 UTC
[tomee] branch tomee-7.1.x updated: TOMEE-2546 backporting MP
examples
This is an automated email from the ASF dual-hosted git repository.
jgallimore pushed a commit to branch tomee-7.1.x
in repository https://gitbox.apache.org/repos/asf/tomee.git
The following commit(s) were added to refs/heads/tomee-7.1.x by this push:
new e210d9e TOMEE-2546 backporting MP examples
new 2a783f2 Merge branch 'tomee-7.1.x' of https://github.com/jgallimore/tomee into tomee-7.1.x
e210d9e is described below
commit e210d9e7ea8411c6714166f97a317ee121ce2170
Author: Jonathan Gallimore <jo...@jrg.me.uk>
AuthorDate: Wed Jun 26 11:11:01 2019 +0100
TOMEE-2546 backporting MP examples
---
examples/mp-config-example/README.adoc | 67 ++++++
examples/mp-config-example/README_es.adoc | 70 ++++++
examples/mp-config-example/README_pt.adoc | 71 ++++++
examples/mp-config-example/pom.xml | 104 +++++++++
.../java/org/superbiz/config/PropertiesRest.java | 80 +++++++
.../src/main/resources/META-INF/beans.xml | 0
.../META-INF/microprofile-config.properties | 3 +
.../org/superbiz/config/PropertiesRestTest.java | 53 +++++
.../src/test/resources/arquillian.xml | 30 +++
examples/mp-config-source-database/README.adoc | 14 ++
examples/mp-config-source-database/pom.xml | 146 ++++++++++++
.../config/source/database/ApplicationBean.java | 47 ++++
.../source/database/DatabaseConfigSource.java | 93 ++++++++
...rg.eclipse.microprofile.config.spi.ConfigSource | 17 ++
.../src/main/tomee/conf/tomee.xml | 21 ++
.../tomee/lib/import-config-source-database.sql | 19 ++
.../source/database/DatabaseConfigSourceTest.java | 55 +++++
.../src/test/resources/arquillian.xml | 37 +++
examples/mp-faulttolerance-fallback/README.adoc | 125 ++++++++++
examples/mp-faulttolerance-fallback/README_es.adoc | 125 ++++++++++
examples/mp-faulttolerance-fallback/pom.xml | 119 ++++++++++
.../rest/WeatherDayStatusFallbackHandler.java | 36 +++
.../java/org/superbiz/rest/WeatherException.java | 20 ++
.../java/org/superbiz/rest/WeatherService.java | 60 +++++
.../java/org/superbiz/rest/WeatherServiceTest.java | 74 ++++++
.../src/test/resources/arquillian.xml | 30 +++
.../src/test/resources/beans.xml | 7 +
examples/mp-faulttolerance-retry/README.adoc | 255 +++++++++++++++++++++
examples/mp-faulttolerance-retry/pom.xml | 105 +++++++++
.../java/org/superbiz/rest/WeatherGateway.java | 115 ++++++++++
.../rest/WeatherGatewayBusyServiceException.java | 20 ++
.../rest/WeatherGatewayTimeoutException.java | 21 ++
.../java/org/superbiz/rest/WeatherService.java | 73 ++++++
.../java/org/superbiz/rest/WeatherServiceTest.java | 94 ++++++++
.../src/test/resources/arquillian.xml | 30 +++
.../src/test/resources/beans.xml | 7 +
examples/mp-faulttolerance-timeout/README.adoc | 108 +++++++++
examples/mp-faulttolerance-timeout/pom.xml | 107 +++++++++
.../java/org/superbiz/rest/WeatherGateway.java | 49 ++++
.../java/org/superbiz/rest/WeatherService.java | 39 ++++
.../java/org/superbiz/rest/WeatherServiceTest.java | 66 ++++++
.../src/test/resources/arquillian.xml | 30 +++
.../src/test/resources/beans.xml | 7 +
examples/mp-opentracing-traced/README.adoc | 63 +++++
examples/mp-opentracing-traced/pom.xml | 105 +++++++++
.../src/test/resources/arquillian.xml | 30 +++
examples/pom.xml | 5 +
47 files changed, 2852 insertions(+)
diff --git a/examples/mp-config-example/README.adoc b/examples/mp-config-example/README.adoc
new file mode 100644
index 0000000..c92ba31
--- /dev/null
+++ b/examples/mp-config-example/README.adoc
@@ -0,0 +1,67 @@
+= MicroProfile Config
+:index-group: MicroProfile
+:jbake-type: page
+:jbake-status: published
+
+This is an example on how to use microprofile config in TomEE.
+
+== Run the application:
+
+[source,bash]
+----
+mvn clean install tomee:run
+----
+
+== API
+
+Within the application there is an three way to inject values using config
+
+1 . For the ConfigProperty with default value call:
+----
+GET http://localhost:8080/mp-config-example/sample/defaultProperty
+----
+
+2 . For the get property inject with ConfigProperty call:
+----
+GET http://localhost:8080/mp-config-example/sample/injectedJavaVersion
+----
+
+3 . For the get property from Config with getValue call:
+----
+GET http://localhost:8080/mp-config-example/sample/javaVersion
+----
+
+== Config Feature
+
+MicroProfile Config is a solution to externalise configuration from microservices.
+Each individual property can be injected directly
+
+[source,java,numbered]
+----
+@Inject
+@ConfigProperty(name = "java.runtime.version")
+private String javaVersion;
+----
+
+You can also set a default value for it, case the config does not match the property in the context it will use the default value
+
+[source,java,numbered]
+----
+@Inject
+@ConfigProperty(name = "defaultProperty", defaultValue = "ALOHA")
+private String defaultProperty;
+----
+
+The config object can also be injected. Then use the getValue() method to retrieve the individual property.
+
+[source,java,numbered]
+----
+@Inject
+private Config config;
+
+@GET
+@Path("javaVersion")
+public String getJavaVersionPropertyFromSystemProperties() {
+ return config.getValue("java.runtime.version", String.class);
+}
+----
\ No newline at end of file
diff --git a/examples/mp-config-example/README_es.adoc b/examples/mp-config-example/README_es.adoc
new file mode 100644
index 0000000..0aefb12
--- /dev/null
+++ b/examples/mp-config-example/README_es.adoc
@@ -0,0 +1,70 @@
+
+= MicroProfile Config
+:index-group: MicroProfile
+:jbake-type: page
+:jbake-status: published
+
+Este es un ejemplo de cómo usar la configuración de microprofile en TomEE.
+
+== Ejecutar la aplicación:
+
+[source,bash]
+----
+mvn clean install tomee:run
+----
+
+== API
+
+Hay tres formas de inyectar valores en la aplicación usando configuración.
+
+1 . Para Valores por defecto con ConfigProperty ejecutar:
+
+----
+GET http://localhost:8080/mp-config-example/sample/defaultProperty
+----
+
+2 . Para obtener propiedades inyectadas con ConfigProperty ejecutar:
+----
+GET http://localhost:8080/mp-config-example/sample/injectedJavaVersion
+----
+
+3 . Para obtener una propiedad desde Config con getValue ejecutar:
+----
+GET http://localhost:8080/mp-config-example/sample/javaVersion
+----
+
+== Características de Config
+
+MicroProfile Config es una solución que permite externalizar la configuración de los microservicios. Cada propiedad
+puede ser inyectada directamente de forma individual.
+
+[source,java,numbered]
+----
+@Inject
+@ConfigProperty(name = "java.runtime.version")
+private String javaVersion;
+----
+
+
+Es posible establecer valores por defecto aún cuando la propiedad no está definida en el contexto, por tanto se usará la configuración por defecto.
+
+[source,java,numbered]
+----
+@Inject
+@ConfigProperty(name = "defaultProperty", defaultValue = "ALOHA")
+private String defaultProperty;
+----
+
+El objeto Config puede también ser inyectado, de manera que se puede invocar el método getValue() para obtener una propiedad particular.
+
+[source,java,numbered]
+----
+@Inject
+private Config config;
+
+@GET
+@Path("javaVersion")
+public String getJavaVersionPropertyFromSystemProperties() {
+ return config.getValue("java.runtime.version", String.class);
+}
+----
diff --git a/examples/mp-config-example/README_pt.adoc b/examples/mp-config-example/README_pt.adoc
new file mode 100644
index 0000000..9c7f1ae
--- /dev/null
+++ b/examples/mp-config-example/README_pt.adoc
@@ -0,0 +1,71 @@
+= MicroProfile Config
+:index-group: MicroProfile
+:jbake-type: page
+:jbake-status: published
+
+Este é um examplo de como usar o microprofile config no TomEE.
+
+== Rodando a aplicação:
+
+[source,bash]
+----
+mvn clean install tomee:run
+----
+
+== API
+
+Na aplicação existem 3 formas de injetar valores usando config
+
+1 . Para o ConfigProperty com valor padrão chamar:
+
+----
+GET http://localhost:8080/mp-config-example/sample/defaultProperty
+----
+
+2 . Para pegar propriedade injetada com ConfigProperty chamar:
+
+----
+GET http://localhost:8080/mp-config-example/sample/injectedJavaVersion
+----
+
+3 . Para pegar a propriedade do Config com getValue chamar:
+
+----
+GET http://localhost:8080/mp-config-example/sample/javaVersion
+----
+
+== Características de Config
+
+
+MicroProfile Config é uma solução para externalizar configurações de microsserviços.
+Cada propriedade individual pode ser injetada diretamente
+
+[source,java,numbered]
+----
+@Inject
+@ConfigProperty(name = "java.runtime.version")
+private String javaVersion;
+----
+
+Você pode também inserir um valor padrão para ele, caso o config não encontre a propriedade no contexto ele irá usar o valor padrão
+
+[source,java,numbered]
+----
+@Inject
+@ConfigProperty(name = "defaultProperty", defaultValue = "ALOHA")
+private String defaultProperty;
+----
+
+O objeto config também pode ser injetado. Então use o método getValue() para recuperar a propriedade individual.
+
+[source,java,numbered]
+----
+@Inject
+private Config config;
+
+@GET
+@Path("javaVersion")
+public String getJavaVersionPropertyFromSystemProperties() {
+ return config.getValue("java.runtime.version", String.class);
+}
+----
diff --git a/examples/mp-config-example/pom.xml b/examples/mp-config-example/pom.xml
new file mode 100644
index 0000000..016c8e6
--- /dev/null
+++ b/examples/mp-config-example/pom.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.superbiz</groupId>
+ <artifactId>mp-config-example</artifactId>
+ <version>7.1.2-SNAPSHOT</version>
+ <packaging>war</packaging>
+ <name>MicroProfile :: Examples :: Config</name>
+
+ <properties>
+ <version.javaee-api>7.0</version.javaee-api>
+ <microprofile.config.version>1.3</microprofile.config.version>
+ <tomee.version>7.1.2-SNAPSHOT</tomee.version>
+ <version.arquillian>1.1.13.Final</version.arquillian>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>javaee-api</artifactId>
+ <version>${version.javaee-api}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.microprofile.config</groupId>
+ <artifactId>microprofile-config-api</artifactId>
+ <version>${microprofile.config.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>openejb-cxf-rs</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.junit</groupId>
+ <artifactId>arquillian-junit-container</artifactId>
+ <version>${version.arquillian}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>arquillian-tomee-remote</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>apache-tomee</artifactId>
+ <version>${tomee.version}</version>
+ <type>zip</type>
+ <classifier>microprofile</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.tomee.maven</groupId>
+ <artifactId>tomee-maven-plugin</artifactId>
+ <version>${tomee.version}</version>
+ <configuration>
+ <tomeeClassifier>microprofile</tomeeClassifier>
+ <context>${project.artifactId}</context>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>3.1.0</version>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <!-- This section allows you to configure where to publish libraries for
+ sharing. It is not required and may be deleted. For more information see:
+ http://maven.apache.org/plugins/maven-deploy-plugin/ -->
+ <distributionManagement>
+ <repository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/repo/</url>
+ </repository>
+ <snapshotRepository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/snapshot-repo/</url>
+ </snapshotRepository>
+ </distributionManagement>
+
+</project>
diff --git a/examples/mp-config-example/src/main/java/org/superbiz/config/PropertiesRest.java b/examples/mp-config-example/src/main/java/org/superbiz/config/PropertiesRest.java
new file mode 100644
index 0000000..db50894
--- /dev/null
+++ b/examples/mp-config-example/src/main/java/org/superbiz/config/PropertiesRest.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.config;
+
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+@Path("/sample")
+@ApplicationScoped
+public class PropertiesRest {
+
+ @Inject
+ private Config config;
+
+ @Inject
+ @ConfigProperty(name = "defaultProperty", defaultValue = "ALOHA")
+ private String defaultProperty;
+
+ @Inject
+ @ConfigProperty(name = "java.runtime.version")
+ private String javaVersion;
+
+ /**
+ *
+ * Get the default value configured on @ConfigProperty, that because
+ * the property defaultProperty doesn't exists, so it will get the value
+ * configured on defaultValue
+ *
+ * @return defaultValue from @ConfigProperty
+ */
+ @GET
+ @Path("defaultProperty")
+ public String getDefaultProperty() {
+ return defaultProperty;
+ }
+
+ /**
+ *
+ * Get the value from property java.runtime.version, but in this case
+ * it shows how you can get the value using Config class.
+ *
+ * @return javaVersion from Config.getValue
+ */
+ @GET
+ @Path("javaVersion")
+ public String getJavaVersionPropertyFromSystemProperties() {
+ return config.getValue("java.runtime.version", String.class);
+ }
+
+ /**
+ * Get the value from property java.runtime.version, but in this case
+ * it shows how you can get value injected using @ConfigProperty.
+ *
+ * @return javaVersion injected from Config
+ */
+ @GET
+ @Path("injectedJavaVersion")
+ public String getJavaVersionWithInjection() {
+ return javaVersion;
+ }
+}
diff --git a/examples/mp-config-example/src/main/resources/META-INF/beans.xml b/examples/mp-config-example/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..e69de29
diff --git a/examples/mp-config-example/src/main/resources/META-INF/microprofile-config.properties b/examples/mp-config-example/src/main/resources/META-INF/microprofile-config.properties
new file mode 100644
index 0000000..2b67141
--- /dev/null
+++ b/examples/mp-config-example/src/main/resources/META-INF/microprofile-config.properties
@@ -0,0 +1,3 @@
+config_ordinal = 500
+sample.microprofile-config=ALOHA!!
+sample.microrpfile.name=DANIEL
\ No newline at end of file
diff --git a/examples/mp-config-example/src/test/java/org/superbiz/config/PropertiesRestTest.java b/examples/mp-config-example/src/test/java/org/superbiz/config/PropertiesRestTest.java
new file mode 100644
index 0000000..5f8a1c5
--- /dev/null
+++ b/examples/mp-config-example/src/test/java/org/superbiz/config/PropertiesRestTest.java
@@ -0,0 +1,53 @@
+package org.superbiz.config;
+
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.URL;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Arquillian.class)
+public class PropertiesRestTest {
+
+ @ArquillianResource
+ private URL base;
+
+ @Deployment
+ public static WebArchive createDeployment() {
+ return ShrinkWrap.create(WebArchive.class, "test.war")
+ .addClasses(PropertiesRest.class)
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+ }
+
+ @Test
+ public void testDefaultValue() {
+ final String message = WebClient.create(base.toExternalForm())
+ .path("/sample/defaultProperty")
+ .get(String.class);
+ assertEquals("ALOHA", message);
+ }
+
+ @Test
+ public void testGetJavaVersionFromConfig() {
+ final String message = WebClient.create(base.toExternalForm())
+ .path("/sample/javaVersion")
+ .get(String.class);
+ assertEquals(System.getProperty("java.runtime.version"), message);
+ }
+
+ @Test
+ public void testGetInjectedJavaVersion() {
+ final String message = WebClient.create(base.toExternalForm())
+ .path("/sample/injectedJavaVersion")
+ .get(String.class);
+ assertEquals(System.getProperty("java.runtime.version"), message);
+ }
+}
diff --git a/examples/mp-config-example/src/test/resources/arquillian.xml b/examples/mp-config-example/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..3029d48
--- /dev/null
+++ b/examples/mp-config-example/src/test/resources/arquillian.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <container qualifier="tomee" default="true">
+ <configuration>
+ <property name="httpPort">-1</property>
+ <property name="stopPort">-1</property>
+ <property name="classifier">microprofile</property>
+ <property name="dir">target/apache-tomee-remote</property>
+ <property name="appWorkingDir">target/arquillian-test-working-dir</property>
+ </configuration>
+ </container>
+</arquillian>
\ No newline at end of file
diff --git a/examples/mp-config-source-database/README.adoc b/examples/mp-config-source-database/README.adoc
new file mode 100644
index 0000000..98db897
--- /dev/null
+++ b/examples/mp-config-source-database/README.adoc
@@ -0,0 +1,14 @@
+= MicroProfile Configuration ConfigSource Database
+:index-group: MicroProfile
+:jbake-type: page
+:jbake-status: published
+
+This is an example on how to implement a custom MicroProfile Configuration ConfigSource. The custom ConfigSource is
+going to read configuration values from a Database.
+
+== Run the application:
+
+[source,bash]
+----
+mvn clean install tomee:run
+----
diff --git a/examples/mp-config-source-database/pom.xml b/examples/mp-config-source-database/pom.xml
new file mode 100644
index 0000000..4d7eb10
--- /dev/null
+++ b/examples/mp-config-source-database/pom.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.superbiz</groupId>
+ <artifactId>mp-config-source-database</artifactId>
+ <version>7.1.2-SNAPSHOT</version>
+ <packaging>war</packaging>
+
+ <name>MicroProfile :: Examples :: Config Source Database</name>
+
+ <properties>
+ <version.javaee-api>7.0</version.javaee-api>
+ <version.microprofile>2.0.1</version.microprofile>
+ <version.arquillian>1.1.13.Final</version.arquillian>
+ <tomee.version>7.1.2-SNAPSHOT</tomee.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>javaee-api</artifactId>
+ <version>${version.javaee-api}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.microprofile</groupId>
+ <artifactId>microprofile</artifactId>
+ <version>${version.microprofile}</version>
+ <type>pom</type>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-dbutils</groupId>
+ <artifactId>commons-dbutils</artifactId>
+ <version>1.7</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>apache-tomee</artifactId>
+ <version>${tomee.version}</version>
+ <type>zip</type>
+ <classifier>microprofile</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.junit</groupId>
+ <artifactId>arquillian-junit-container</artifactId>
+ <version>${version.arquillian}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>ziplock</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-impl-maven</artifactId>
+ <version>2.1.0</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>arquillian-tomee-remote</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>3.1.0</version>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.tomee.maven</groupId>
+ <artifactId>tomee-maven-plugin</artifactId>
+ <version>${tomee.version}</version>
+ <configuration>
+ <tomeeClassifier>microprofile</tomeeClassifier>
+ <context>${project.artifactId}</context>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.6.2</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <!-- This section allows you to configure where to publish libraries for
+ sharing. It is not required and may be deleted. For more information see:
+ http://maven.apache.org/plugins/maven-deploy-plugin/ -->
+ <distributionManagement>
+ <repository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/repo/</url>
+ </repository>
+ <snapshotRepository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/snapshot-repo/</url>
+ </snapshotRepository>
+ </distributionManagement>
+</project>
diff --git a/examples/mp-config-source-database/src/main/java/org/superbiz/microprofile/config/source/database/ApplicationBean.java b/examples/mp-config-source-database/src/main/java/org/superbiz/microprofile/config/source/database/ApplicationBean.java
new file mode 100644
index 0000000..88a3ca4
--- /dev/null
+++ b/examples/mp-config-source-database/src/main/java/org/superbiz/microprofile/config/source/database/ApplicationBean.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.microprofile.config.source.database;
+
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.Initialized;
+import javax.enterprise.event.Observes;
+import javax.inject.Inject;
+
+@ApplicationScoped
+public class ApplicationBean {
+ @Inject
+ @ConfigProperty(name = "application.currency")
+ private String applicationCurrrency;
+ @Inject
+ @ConfigProperty(name = "application.country")
+ private String applicationCountry;
+
+ public void init(@Observes @Initialized(ApplicationScoped.class) final Object init) {
+ System.out.println("applicationCurrrency = " + applicationCurrrency);
+ System.out.println("applicationCountry = " + applicationCountry);
+ }
+
+ public String getApplicationCurrrency() {
+ return applicationCurrrency;
+ }
+
+ public String getApplicationCountry() {
+ return applicationCountry;
+ }
+}
diff --git a/examples/mp-config-source-database/src/main/java/org/superbiz/microprofile/config/source/database/DatabaseConfigSource.java b/examples/mp-config-source-database/src/main/java/org/superbiz/microprofile/config/source/database/DatabaseConfigSource.java
new file mode 100644
index 0000000..53a0ebe
--- /dev/null
+++ b/examples/mp-config-source-database/src/main/java/org/superbiz/microprofile/config/source/database/DatabaseConfigSource.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.microprofile.config.source.database;
+
+import org.apache.commons.dbutils.DbUtils;
+import org.eclipse.microprofile.config.spi.ConfigSource;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class DatabaseConfigSource implements ConfigSource {
+ private DataSource dataSource;
+
+ public DatabaseConfigSource() {
+ try {
+ dataSource = (DataSource) new InitialContext().lookup("openejb:Resource/config-source-database");
+ } catch (final NamingException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ final Map<String, String> properties = new HashMap<>();
+
+ try {
+ final Connection connection = dataSource.getConnection();
+ final PreparedStatement query = connection.prepareStatement("SELECT NAME, VALUE FROM CONFIGURATIONS");
+ final ResultSet names = query.executeQuery();
+
+ while (names.next()) {
+ properties.put(names.getString(0), names.getString(1));
+ }
+
+ DbUtils.closeQuietly(names);
+ DbUtils.closeQuietly(query);
+ DbUtils.closeQuietly(connection);
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+
+ return properties;
+ }
+
+ @Override
+ public String getValue(final String propertyName) {
+ try {
+ final Connection connection = dataSource.getConnection();
+ final PreparedStatement query =
+ connection.prepareStatement("SELECT VALUE FROM CONFIGURATIONS WHERE NAME = ?");
+ query.setString(1, propertyName);
+ final ResultSet value = query.executeQuery();
+
+ if (value.next()) {
+ return value.getString(1);
+ }
+
+ DbUtils.closeQuietly(value);
+ DbUtils.closeQuietly(query);
+ DbUtils.closeQuietly(connection);
+ } catch (final SQLException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return DatabaseConfigSource.class.getSimpleName();
+ }
+}
diff --git a/examples/mp-config-source-database/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource b/examples/mp-config-source-database/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource
new file mode 100644
index 0000000..5c9d64e
--- /dev/null
+++ b/examples/mp-config-source-database/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource
@@ -0,0 +1,17 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+org.superbiz.microprofile.config.source.database.DatabaseConfigSource
diff --git a/examples/mp-config-source-database/src/main/tomee/conf/tomee.xml b/examples/mp-config-source-database/src/main/tomee/conf/tomee.xml
new file mode 100644
index 0000000..9841c23
--- /dev/null
+++ b/examples/mp-config-source-database/src/main/tomee/conf/tomee.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You 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.
+ -->
+<tomee>
+ <Resource id="config-source-database" type="DataSource">
+
+ </Resource>
+</tomee>
diff --git a/examples/mp-config-source-database/src/main/tomee/lib/import-config-source-database.sql b/examples/mp-config-source-database/src/main/tomee/lib/import-config-source-database.sql
new file mode 100644
index 0000000..0fe45ef
--- /dev/null
+++ b/examples/mp-config-source-database/src/main/tomee/lib/import-config-source-database.sql
@@ -0,0 +1,19 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You 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.
+--
+CREATE TABLE CONFIGURATIONS (NAME VARCHAR (255) NOT NULL PRIMARY KEY, VALUE VARCHAR(255) NOT NULL);
+INSERT INTO CONFIGURATIONS(NAME, VALUE) VALUES('application.currency', 'Euro');
+INSERT INTO CONFIGURATIONS(NAME, VALUE) VALUES('application.country', 'PT');
diff --git a/examples/mp-config-source-database/src/test/java/org/superbiz/microprofile/config/source/database/DatabaseConfigSourceTest.java b/examples/mp-config-source-database/src/test/java/org/superbiz/microprofile/config/source/database/DatabaseConfigSourceTest.java
new file mode 100644
index 0000000..b22edd8
--- /dev/null
+++ b/examples/mp-config-source-database/src/test/java/org/superbiz/microprofile/config/source/database/DatabaseConfigSourceTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.microprofile.config.source.database;
+
+import org.apache.ziplock.maven.Mvn;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.inject.Inject;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Arquillian.class)
+public class DatabaseConfigSourceTest {
+ @Deployment
+ public static WebArchive createDeployment() {
+ return (WebArchive) Mvn.war();
+ }
+
+ @Inject
+ private Config config;
+ @Inject
+ private ApplicationBean applicationBean;
+
+ @Test
+ public void testConfigSourceStatic() throws Exception {
+ assertEquals(config.getValue("application.currency", String.class), "Euro");
+ assertEquals(config.getValue("application.country", String.class), "PT");
+
+ assertEquals(applicationBean.getApplicationCurrrency(), "Euro");
+ assertEquals(applicationBean.getApplicationCountry(), "PT");
+
+ assertEquals(ConfigProvider.getConfig().getValue("application.currency", String.class), "Euro");
+ assertEquals(ConfigProvider.getConfig().getValue("application.country", String.class), "PT");
+ }
+}
diff --git a/examples/mp-config-source-database/src/test/resources/arquillian.xml b/examples/mp-config-source-database/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..a90e56e
--- /dev/null
+++ b/examples/mp-config-source-database/src/test/resources/arquillian.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ <!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You 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.
+ -->
+<arquillian xmlns="http://jboss.org/schema/arquillian"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://jboss.org/schema/arquillian
+ http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
+<container qualifier="tomee-remote" default="true">
+ <configuration>
+ <property name="debug">false</property>
+ <property name="httpPort">-1</property>
+ <property name="ajpPort">-1</property>
+ <property name="stopPort">-1</property>
+ <property name="classifier">microprofile</property>
+ <property name="conf">src/main/tomee/conf</property>
+ <property name="lib">src/main/tomee/lib</property>
+ <property name="dir">target/tomee</property>
+ <property name="appWorkingDir">target/workdir</property>
+ <property name="cleanOnStartUp">true</property>
+ </configuration>
+</container>
+</arquillian>
diff --git a/examples/mp-faulttolerance-fallback/README.adoc b/examples/mp-faulttolerance-fallback/README.adoc
new file mode 100644
index 0000000..b4c6cc8
--- /dev/null
+++ b/examples/mp-faulttolerance-fallback/README.adoc
@@ -0,0 +1,125 @@
+= MicroProfile Fault Tolerance - Fallback
+:index-group: MicroProfile
+:jbake-type: page
+:jbake-status: published
+
+This is an example of how to use Microprofile @Fallback in TomEE.
+
+== Fallback Feature
+Fault Tolerance Fallback provides an alternative execution in case of failure. This alternative will be called when
+`Retry` or `CircuitBreaker` has failed.
+
+To use this feature you need to annotate the method with `@Fallback`.
+
+The Fallback policy allows to configure :
+
+* **value**: A class which implements `FallbackHandler`
+* **fallbackMethod**: a method which will be executed.
+
+The parameters `value` and `fallbackMethod` cannot be specified at the same time.
+
+Check the http://download.eclipse.org/microprofile/microprofile-fault-tolerance-1.1/microprofile-fault-tolerance-spec.html[specification] for more details.
+
+== Examples
+
+=== Run the application
+
+ mvn clean install tomee:run
+
+=== Example 1
+
+The method `statusOfDay` will always fail throwing a `WeatherException` and as the
+`@CircuitBreaker` annotation is configured to `failOn` in case of that exception, the fallback,
+`WeatherDayStatusFallbackHandler#handle` will be invoked.
+
+```java
+@RequestScoped
+public class WeatherService {
+ ...
+ @GET
+ @Path("/day/status")
+ @CircuitBreaker(failOn = WeatherException.class)
+ @Fallback(WeatherDayStatusFallbackHandler.class)
+ public String dayStatus() {
+ throw new WeatherException();
+ }
+ ...
+ }
+
+public class WeatherDayStatusFallbackHandler implements FallbackHandler<String> {
+
+ @Override
+ public String handle(ExecutionContext executionContext) {
+ return "Hi, today is a sunny day!";
+ }
+}
+```
+
+Day status call
+
+ GET http://localhost:8080/mp-faulttolerance-fallback/weather/day/status
+
+Server log
+```
+SEVERE [http-nio-8080-exec-2] org.superbiz.rest.WeatherDayStatusFallbackHandler.handle WeatherDayStatusFallbackHandler was triggered due a fail
+```
+
+Response
+```
+Hi, today is a sunny day!
+```
+
+=== Example 2
+
+The method `statusOfDay` will always fail throwing a `WeatherException` and as the
+`@Retry` annotation is configured to `maxRetries = 1` in case of fail, the fallback method,
+`fallbackForWeekStatus` will be invoked after retrying once.
+
+```java
+@RequestScoped
+public class WeatherService {
+ ...
+ @GET
+ @Path("/week/status")
+ @Retry(maxRetries = 1)
+ @Fallback(fallbackMethod = "fallbackForWeekStatus")
+ public String weekStatus() {
+ throw new WeatherException();
+ }
+
+ public String fallbackForWeekStatus() {
+ return "Hi, week will be mostly sunny!";
+ }
+ ...
+}
+```
+
+Week status call
+
+ GET http://localhost:8080/mp-faulttolerance-fallback/weather/week/status
+
+Server log
+
+```
+SEVERE [http-nio-8080-exec-2] org.superbiz.rest.WeatherService.fallbackForWeekStatus Fallback was triggered due a fail
+
+```
+
+Response
+```
+Hi, week will be mostly sunny!
+```
+
+
+=== Run the tests
+
+You can also try it out using the link:src/test/java/org/superbiz/rest/WeatherServiceTest.java[WeatherServiceTest.java] available in the project.
+
+ mvn clean test
+
+```
+[INFO] Results:
+[INFO]
+[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
+```
+
diff --git a/examples/mp-faulttolerance-fallback/README_es.adoc b/examples/mp-faulttolerance-fallback/README_es.adoc
new file mode 100644
index 0000000..8f587ce
--- /dev/null
+++ b/examples/mp-faulttolerance-fallback/README_es.adoc
@@ -0,0 +1,125 @@
+= MicroProfile Fault Tolerance - Fallback
+:index-group: MicroProfile
+:jbake-type: page
+:jbake-status: published
+
+Este es un ejemplo de como usar Microprofile @Fallback en TomEE.
+
+== Fallback Feature
+Fault Tolerance Fallback provee una alternativa en caso de fallo de una ejecución. Esta alternativa será llamada cuando
+un `Retry` o `CircuitBreaker` ha fallado.
+
+Para usar esta funcionalidad es necesario anotar el método con `@Fallback`.
+
+Las politicas del Fallback permiten configurar :
+
+* **value**: Una clase que implementa `FallbackHandler`
+* **fallbackMethod**: El método que será ejecutado.
+
+Los parámetros `value` and `fallbackMethod` no pueden ser especificados a la vez.
+
+Para más detalles revisar http://download.eclipse.org/microprofile/microprofile-fault-tolerance-1.1/microprofile-fault-tolerance-spec.html[Especificación]
+
+== Ejemplos
+
+=== Ejecutar la aplicación
+
+ mvn clean install tomee:run
+
+=== Ejemplo 1
+
+El método `statusOfDay` siempre fallará lanzando `WeatherException` y como la anotación
+`@CircuitBreaker` esta configurada con `failOn` en caso de una excepción, el fallback,
+`WeatherDayStatusFallbackHandler#handle` será invocado.
+
+```java
+@RequestScoped
+public class WeatherService {
+ ...
+ @GET
+ @Path("/day/status")
+ @CircuitBreaker(failOn = WeatherException.class)
+ @Fallback(WeatherDayStatusFallbackHandler.class)
+ public String dayStatus() {
+ throw new WeatherException();
+ }
+ ...
+ }
+
+public class WeatherDayStatusFallbackHandler implements FallbackHandler<String> {
+
+ @Override
+ public String handle(ExecutionContext executionContext) {
+ return "Hi, today is a sunny day!";
+ }
+}
+```
+
+Llama el estado del tiempo del dia
+
+ GET http://localhost:8080/mp-faulttolerance-fallback/weather/day/status
+
+Bitácora del servidor
+```
+SEVERE [http-nio-8080-exec-2] org.superbiz.rest.WeatherDayStatusFallbackHandler.handle WeatherDayStatusFallbackHandler was triggered due a fail
+```
+
+Respuesta
+```
+Hi, today is a sunny day!
+```
+
+=== Ejemplo 2
+
+El método `statusOfDay` siempre fallará lanzando `WeatherException` y como la anotación
+`@Retry` está configurada con `maxRetries = 1` en caso de fallo, el método fallback,
+`fallbackForWeekStatus` se invocará después de reintentar una vez.
+
+```java
+@RequestScoped
+public class WeatherService {
+ ...
+ @GET
+ @Path("/week/status")
+ @Retry(maxRetries = 1)
+ @Fallback(fallbackMethod = "fallbackForWeekStatus")
+ public String weekStatus() {
+ throw new WeatherException();
+ }
+
+ public String fallbackForWeekStatus() {
+ return "Hi, week will be mostly sunny!";
+ }
+ ...
+}
+```
+
+Llamada del estado del tiempo de la semana
+
+ GET http://localhost:8080/mp-faulttolerance-fallback/weather/week/status
+
+Bitácora del servidor
+
+```
+SEVERE [http-nio-8080-exec-2] org.superbiz.rest.WeatherService.fallbackForWeekStatus Fallback was triggered due a fail
+
+```
+
+Respuesta
+```
+Hi, week will be mostly sunny!
+```
+
+
+=== Ejecución de las pruebas
+
+Puede además usar la prueba link:src/test/java/org/superbiz/rest/WeatherServiceTest.java[WeatherServiceTest.java] disponible en este proyecto.
+
+ mvn clean test
+
+```
+[INFO] Results:
+[INFO]
+[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
+```
+
diff --git a/examples/mp-faulttolerance-fallback/pom.xml b/examples/mp-faulttolerance-fallback/pom.xml
new file mode 100644
index 0000000..e3c451f
--- /dev/null
+++ b/examples/mp-faulttolerance-fallback/pom.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.superbiz</groupId>
+ <artifactId>mp-faulttolerance-fallback</artifactId>
+ <version>7.1.2-SNAPSHOT</version>
+ <packaging>war</packaging>
+ <name>OpenEJB :: Examples :: Microprofile Fault Tolerance :: Fallback</name>
+
+ <properties>
+ <microprofile-fault-tolerance-api.version>1.0</microprofile-fault-tolerance-api.version>
+ <arquillian-junit-container.version>1.4.0.Final</arquillian-junit-container.version>
+ <maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
+ <maven-war-plugin.version>3.1.0</maven-war-plugin.version>
+ <javaee-api.version>7.0</javaee-api.version>
+ <junit.version>4.12</junit.version>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ <tomee.version>7.1.2-SNAPSHOT</tomee.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>javaee-api</artifactId>
+ <version>${javaee-api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.microprofile.fault-tolerance</groupId>
+ <artifactId>microprofile-fault-tolerance-api</artifactId>
+ <version>${microprofile-fault-tolerance-api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>openejb-cxf-rs</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.junit</groupId>
+ <artifactId>arquillian-junit-container</artifactId>
+ <version>${arquillian-junit-container.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>arquillian-tomee-remote</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>apache-tomee</artifactId>
+ <version>${tomee.version}</version>
+ <type>zip</type>
+ <classifier>microprofile</classifier>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.tomee.maven</groupId>
+ <artifactId>tomee-maven-plugin</artifactId>
+ <version>${tomee.version}</version>
+ <configuration>
+ <tomeeClassifier>microprofile</tomeeClassifier>
+ <context>${project.artifactId}</context>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>${maven-war-plugin.version}</version>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <!-- This section allows you to configure where to publish libraries for
+ sharing. It is not required and may be deleted. For more information see:
+ http://maven.apache.org/plugins/maven-deploy-plugin/ -->
+ <distributionManagement>
+ <repository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/repo/</url>
+ </repository>
+ <snapshotRepository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/snapshot-repo/</url>
+ </snapshotRepository>
+ </distributionManagement>
+</project>
diff --git a/examples/mp-faulttolerance-fallback/src/main/java/org/superbiz/rest/WeatherDayStatusFallbackHandler.java b/examples/mp-faulttolerance-fallback/src/main/java/org/superbiz/rest/WeatherDayStatusFallbackHandler.java
new file mode 100644
index 0000000..bf856dd
--- /dev/null
+++ b/examples/mp-faulttolerance-fallback/src/main/java/org/superbiz/rest/WeatherDayStatusFallbackHandler.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+import org.eclipse.microprofile.faulttolerance.ExecutionContext;
+import org.eclipse.microprofile.faulttolerance.FallbackHandler;
+
+import javax.enterprise.context.Dependent;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+@Dependent
+public class WeatherDayStatusFallbackHandler implements FallbackHandler<String> {
+
+ private static final Logger LOGGER = Logger.getLogger(WeatherDayStatusFallbackHandler.class.getName());
+
+ @Override
+ public String handle(ExecutionContext executionContext) {
+ LOGGER.log(Level.SEVERE, "Fallback was triggered due a fail");
+ return "Hi, today is a sunny day!";
+ }
+}
diff --git a/examples/mp-faulttolerance-fallback/src/main/java/org/superbiz/rest/WeatherException.java b/examples/mp-faulttolerance-fallback/src/main/java/org/superbiz/rest/WeatherException.java
new file mode 100644
index 0000000..85cfac3
--- /dev/null
+++ b/examples/mp-faulttolerance-fallback/src/main/java/org/superbiz/rest/WeatherException.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+public class WeatherException extends RuntimeException {
+}
\ No newline at end of file
diff --git a/examples/mp-faulttolerance-fallback/src/main/java/org/superbiz/rest/WeatherService.java b/examples/mp-faulttolerance-fallback/src/main/java/org/superbiz/rest/WeatherService.java
new file mode 100644
index 0000000..c941eca
--- /dev/null
+++ b/examples/mp-faulttolerance-fallback/src/main/java/org/superbiz/rest/WeatherService.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
+import org.eclipse.microprofile.faulttolerance.Fallback;
+import org.eclipse.microprofile.faulttolerance.Retry;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.enterprise.context.RequestScoped;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+
+@Path("/weather")
+@Produces(MediaType.TEXT_PLAIN)
+@RequestScoped
+public class WeatherService {
+
+ private static final Logger LOGGER = Logger.getLogger(WeatherService.class.getName());
+
+ @GET
+ @Path("/day/status")
+ @CircuitBreaker(failOn = WeatherException.class)
+ @Fallback(WeatherDayStatusFallbackHandler.class)
+ public String dayStatus() {
+ throw new WeatherException();
+ }
+
+ @GET
+ @Path("/week/status")
+ @Retry(maxRetries = 1)
+ @Fallback(fallbackMethod = "fallbackForWeekStatus")
+ public String weekStatus() {
+ throw new WeatherException();
+ }
+
+ public String fallbackForWeekStatus() {
+ LOGGER.log(Level.SEVERE, "Fallback was triggered due a fail");
+ return "Hi, week will be mostly sunny!";
+ }
+}
diff --git a/examples/mp-faulttolerance-fallback/src/test/java/org/superbiz/rest/WeatherServiceTest.java b/examples/mp-faulttolerance-fallback/src/test/java/org/superbiz/rest/WeatherServiceTest.java
new file mode 100644
index 0000000..766e2de
--- /dev/null
+++ b/examples/mp-faulttolerance-fallback/src/test/java/org/superbiz/rest/WeatherServiceTest.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.junit.InSequence;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.URL;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Arquillian.class)
+public class WeatherServiceTest {
+
+ @ArquillianResource
+ private URL base;
+
+ private Client client;
+
+ @Deployment(testable = false)
+ public static WebArchive createDeployment() {
+ return ShrinkWrap.create(WebArchive.class, "test.war").addPackage(WeatherService.class.getPackage());
+ }
+
+ @Before
+ public void before() {
+ this.client = ClientBuilder.newClient();
+ }
+
+ @Test
+ public void testStatusOfDay() {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ Response response = webTarget.path("/weather/day/status").request().get();
+ assertEquals("Hi, today is a sunny day!", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testStatusOfWeek() {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ Response response = webTarget.path("/weather/week/status").request().get();
+ assertEquals("Hi, week will be mostly sunny!", response.readEntity(String.class));
+ }
+
+ @After
+ public void after() {
+ this.client.close();
+ }
+}
diff --git a/examples/mp-faulttolerance-fallback/src/test/resources/arquillian.xml b/examples/mp-faulttolerance-fallback/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..3029d48
--- /dev/null
+++ b/examples/mp-faulttolerance-fallback/src/test/resources/arquillian.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <container qualifier="tomee" default="true">
+ <configuration>
+ <property name="httpPort">-1</property>
+ <property name="stopPort">-1</property>
+ <property name="classifier">microprofile</property>
+ <property name="dir">target/apache-tomee-remote</property>
+ <property name="appWorkingDir">target/arquillian-test-working-dir</property>
+ </configuration>
+ </container>
+</arquillian>
\ No newline at end of file
diff --git a/examples/mp-faulttolerance-fallback/src/test/resources/beans.xml b/examples/mp-faulttolerance-fallback/src/test/resources/beans.xml
new file mode 100644
index 0000000..d942d7a
--- /dev/null
+++ b/examples/mp-faulttolerance-fallback/src/test/resources/beans.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+</beans>
\ No newline at end of file
diff --git a/examples/mp-faulttolerance-retry/README.adoc b/examples/mp-faulttolerance-retry/README.adoc
new file mode 100644
index 0000000..b259179
--- /dev/null
+++ b/examples/mp-faulttolerance-retry/README.adoc
@@ -0,0 +1,255 @@
+= MicroProfile Fault Tolerance - Retry Policy
+:index-group: MicroProfile
+:jbake-type: page
+:jbake-status: published
+
+This is an example of how to use
+Microprofile @Retry in TomEE.
+
+== Retry Feature
+
+Microprofile Fault Tolerance has a feature called Retry that can be used
+to recover an operation from failure, invoking the same operation again
+until it reaches its stopping criteria.
+
+The Retry policy allows to configure :
+
+* *maxRetries*: the maximum retries
+* *delay*: delays between each retry
+* *delayUnit*: the delay unit
+* *maxDuration*: maximum duration to perform the retry for.
+* *durationUnit*: duration unit
+* *jitter:* the random vary of retry delays
+* *jitterDelayUnit:* the jitter unit
+* *retryOn:* specify the failures to retry on
+* *abortOn:* specify the failures to abort on
+
+To use this feature you can annotate a class and/or a method with the
+@Retry annotation. Check the
+http://download.eclipse.org/microprofile/microprofile-fault-tolerance-1.1/microprofile-fault-tolerance-spec.html[specification]
+for more details.
+
+== Examples
+
+=== Run the application
+
+....
+mvn clean install tomee:run
+....
+
+=== Example 1
+
+The method statusOfDay will fail three times, each time, throwing a
+`WeatherGatewayTimeoutException` and as the @Retry annotation is
+configured to `retryOn` in case of failure, the FailSafe library will
+take the `maxRetry` value and retry the same operation until it reaches
+the number maximum of attempts, which is 3 (default value).
+
+[source,java]
+----
+@RequestScoped
+public class WeatherGateway{
+ ...
+ @Retry(maxRetry=3, retryOn = WeatherGatewayTimeoutException.class)
+ public String statusOfDay(){
+ if(counterStatusOfDay.addAndGet(1) <= DEFAULT_MAX_RETRY){
+ LOGGER.warning(String.format(FORECAST_TIMEOUT_MESSAGE, DEFAULT_MAX_RETRY, counterStatusOfDay.get()));
+ throw new WeatherGatewayTimeoutException();
+ }
+ return "Today is a sunny day!";
+ }
+ ...
+ }
+----
+
+Day status call
+
+....
+GET http://localhost:8080/mp-faulttolerance-retry/weather/day/status
+....
+
+Server log
+
+....
+WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (1)
+WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (2)
+WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (3)
+....
+
+Response
+
+....
+Today is a sunny day!
+....
+
+=== Example 2
+
+The method weekStatus will fail two times, each time, throwing a
+`WeatherGatewayTimeoutException` because `retryOn` is configured and
+instead of returning a response to the caller, the logic states that at
+the third attempt, a `WeatherGatewayBusyServiceException` will be
+thrown. As the `@Retry` annotation is configured to `abortOn` in case of
+`WeatherGatewayTimeoutException` happens, the remaining attempt won’t be
+executed and the caller must handle the exception.
+
+[source,java]
+----
+@Retry(maxRetries = 3, retryOn = WeatherGatewayTimeoutException.class, abortOn = WeatherGatewayBusyServiceException.class)
+public String statusOfWeek(){
+ if(counterStatusOfWeek.addAndGet(1) <= DEFAULT_MAX_RETRY){
+ LOGGER.warning(String.format(FORECAST_TIMEOUT_MESSAGE_ATTEMPTS, DEFAULT_MAX_RETRY, counterStatusOfWeek.get()));
+ throw new WeatherGatewayTimeoutException();
+ }
+ LOGGER.log(Level.SEVERE, String.format(FORECAST_BUSY_MESSAGE, counterStatusOfWeek.get()));
+ throw new WeatherGatewayBusyServiceException();
+}
+----
+
+Week status call
+
+....
+GET http://localhost:8080/mp-faulttolerance-retry/weather/week/status
+....
+
+Server log
+
+....
+WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (1)
+WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (2)
+WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (3)
+SEVERE - Error AccuWeather Forecast Service is busy. Number of Attempts: (4)
+....
+
+Response
+
+....
+WeatherGateway Service is Busy. Retry later
+....
+
+=== Example 3
+
+The `@Retry` annotation allows to configure a delay for each new attempt
+be executed giving a chance to service requested to recover itself and
+answerer the request properly. For each new retry follow the delay
+configure, is needed to set `jitter` to zero (0). Otherwise the delay of
+each new attempt will be randomized.
+
+Analysing the logged messages, is possible to see that all attempts took
+the pretty much the same time to execute.
+
+[source,java]
+----
+@Retry(retryOn = WeatherGatewayTimeoutException.class, maxRetries = 5, delay = 500, jitter = 0)
+public String statusOfWeekend() {
+ if (counterStatusOfWeekend.addAndGet(1) <= 5) {
+ logTimeoutMessage(statusOfWeekendInstant);
+ statusOfWeekendInstant = Instant.now();
+ throw new WeatherGatewayTimeoutException();
+ }
+ return "The Forecast for the Weekend is Scattered Showers.";
+}
+----
+
+Weekend status call
+
+....
+GET http://localhost:8080/mp-faulttolerance-retry/weather/weekend/status
+....
+
+Server log
+
+....
+WARNING - Timeout when accessing AccuWeather Forecast Service.
+WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (501) millis
+WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (501) millis
+WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (501) millis
+WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (500) millis
+....
+
+=== Example 4
+
+Basically with the same behaviour of the `Example 3`, this example sets
+the `delay` and `jitter` with 500 millis to randomly create a new delay
+for each new attempt after the first failure.
+https://github.com/jhalterman/failsafe/blob/master/src/main/java/net/jodah/failsafe/AbstractExecution.java[AbstractExecution#randomDelay(delay,jitter,random)]
+can give a hit of how the new delay is calculated.
+
+Analysing the logged messages, is possible to see how long each attempt
+had to wait until its execution.
+
+[source,java]
+----
+@Retry(retryOn = WeatherGatewayTimeoutException.class, delay = 500, jitter = 500)
+public String statusOfMonth() {
+ if (counterStatusOfWeekend.addAndGet(1) <= DEFAULT_MAX_RETRY) {
+ logTimeoutMessage(statusOfMonthInstant);
+ statusOfMonthInstant = Instant.now();
+ throw new WeatherGatewayTimeoutException();
+ }
+ return "The Forecast for the Weekend is Scattered Showers.";
+}
+----
+
+Month status call
+
+....
+GET http://localhost:8080/mp-faulttolerance-retry/weather/month/status
+....
+
+Server log
+
+....
+WARNING - Timeout when accessing AccuWeather Forecast Service.
+WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (417) millis
+WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (90) millis
+....
+
+=== Example 5
+
+If a condition for an operation be re-executed is not set as in the
+previous examples using the parameter `retryOn`, the operation is
+executed again for _any_ exception that is thrown.
+
+[source,java]
+----
+@Retry(maxDuration = 1000)
+public String statusOfYear(){
+ if (counterStatusOfWeekend.addAndGet(1) <= 5) {
+ logTimeoutMessage(statusOfYearInstant);
+ statusOfYearInstant = Instant.now();
+ throw new RuntimeException();
+ }
+ return "WeatherGateway Service Error";
+}
+----
+
+Year status call
+
+....
+GET http://localhost:8080/mp-faulttolerance-retry/weather/year/statusk
+....
+
+Server log
+
+....
+WARNING - Timeout when accessing AccuWeather Forecast Service.
+WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (666) millis
+WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (266) millis
+WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (66) millis
+....
+
+=== Run the tests
+
+You can also try it out using the
+link:src/test/java/org/superbiz/rest/WeatherServiceTest.java[WeatherServiceTest.java]
+available in the project.
+
+....
+mvn clean test
+....
+
+....
+[INFO] Results:
+[INFO]
+[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
+....
diff --git a/examples/mp-faulttolerance-retry/pom.xml b/examples/mp-faulttolerance-retry/pom.xml
new file mode 100644
index 0000000..81c1590
--- /dev/null
+++ b/examples/mp-faulttolerance-retry/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.superbiz</groupId>
+ <artifactId>mp-faulttolerance-retry</artifactId>
+ <version>7.1.2-SNAPSHOT</version>
+ <packaging>war</packaging>
+ <name>OpenEJB :: Examples :: Microprofile Fault Tolerance :: Retry</name>
+
+ <properties>
+ <microprofile-fault-tolerance-api.version>1.0</microprofile-fault-tolerance-api.version>
+ <arquillian-junit-container.version>1.4.0.Final</arquillian-junit-container.version>
+ <maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
+ <maven-war-plugin.version>3.1.0</maven-war-plugin.version>
+ <javaee-api.version>7.0</javaee-api.version>
+ <junit.version>4.12</junit.version>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ <tomee.version>7.1.2-SNAPSHOT</tomee.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>javaee-api</artifactId>
+ <version>${javaee-api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.microprofile.fault-tolerance</groupId>
+ <artifactId>microprofile-fault-tolerance-api</artifactId>
+ <version>${microprofile-fault-tolerance-api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>openejb-cxf-rs</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.junit</groupId>
+ <artifactId>arquillian-junit-container</artifactId>
+ <version>${arquillian-junit-container.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>arquillian-tomee-remote</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>apache-tomee</artifactId>
+ <version>${tomee.version}</version>
+ <type>zip</type>
+ <classifier>microprofile</classifier>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.tomee.maven</groupId>
+ <artifactId>tomee-maven-plugin</artifactId>
+ <version>${tomee.version}</version>
+ <configuration>
+ <tomeeClassifier>microprofile</tomeeClassifier>
+ <context>${project.artifactId}</context>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>${maven-war-plugin.version}</version>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <!-- This section allows you to configure where to publish libraries for
+ sharing. It is not required and may be deleted. For more information see:
+ http://maven.apache.org/plugins/maven-deploy-plugin/ -->
+ <distributionManagement>
+ <repository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/repo/</url>
+ </repository>
+ <snapshotRepository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/snapshot-repo/</url>
+ </snapshotRepository>
+ </distributionManagement>
+</project>
diff --git a/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherGateway.java b/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherGateway.java
new file mode 100644
index 0000000..611ef84
--- /dev/null
+++ b/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherGateway.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.enterprise.context.RequestScoped;
+import org.eclipse.microprofile.faulttolerance.Retry;
+
+
+@RequestScoped
+public class WeatherGateway {
+
+ private static Logger LOGGER = Logger.getLogger(WeatherGateway.class.getName());
+
+ private static final String FORECAST_TIMEOUT_MESSAGE_ATTEMPTS =
+ "Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (%d), Attempts: (%d)";
+
+ private static final String FORECAST_TIMEOUT_MESSAGE =
+ "Timeout when accessing AccuWeather Forecast Service.";
+
+ private static final String FORECAST_TIMEOUT_MESSAGE_DELAY =
+ "Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (%d)";
+
+ private static final String FORECAST_BUSY_MESSAGE =
+ "Error AccuWeather Forecast Service is busy. Number of Attempts: (%d) \n";
+
+ /**
+ * {@link Retry#maxRetries()}
+ */
+ private static final int DEFAULT_MAX_RETRY = 3;
+
+ private final AtomicInteger counterStatusOfDay = new AtomicInteger();
+ private final AtomicInteger counterStatusOfWeek = new AtomicInteger();
+ private final AtomicInteger counterStatusOfWeekend = new AtomicInteger();
+
+ private Instant statusOfWeekendInstant = null;
+ private Instant statusOfMonthInstant = null;
+ private Instant statusOfYearInstant = null;
+
+ @Retry(maxRetries = 3, retryOn = WeatherGatewayTimeoutException.class)
+ public String statusOfDay(){
+ if(counterStatusOfDay.addAndGet(1) <= DEFAULT_MAX_RETRY){
+ LOGGER.warning(String.format(FORECAST_TIMEOUT_MESSAGE_ATTEMPTS, DEFAULT_MAX_RETRY, counterStatusOfDay.get()));
+ throw new WeatherGatewayTimeoutException();
+ }
+ return "Hi, today is a sunny day!";
+ }
+
+ @Retry(maxRetries = 3, retryOn = WeatherGatewayTimeoutException.class, abortOn = WeatherGatewayBusyServiceException.class)
+ public String statusOfWeek(){
+ if(counterStatusOfWeek.addAndGet(1) <= DEFAULT_MAX_RETRY){
+ LOGGER.warning(String.format(FORECAST_TIMEOUT_MESSAGE_ATTEMPTS, DEFAULT_MAX_RETRY, counterStatusOfWeek.get()));
+ throw new WeatherGatewayTimeoutException();
+ }
+ LOGGER.log(Level.SEVERE, String.format(FORECAST_BUSY_MESSAGE, counterStatusOfWeek.get()));
+ throw new WeatherGatewayBusyServiceException();
+ }
+
+ @Retry(retryOn = WeatherGatewayTimeoutException.class, maxRetries = 5, delay = 500, jitter = 0)
+ public String statusOfWeekend() {
+ if (counterStatusOfWeekend.addAndGet(1) <= 5) {
+ logTimeoutMessage(statusOfWeekendInstant);
+ statusOfWeekendInstant = Instant.now();
+ throw new WeatherGatewayTimeoutException();
+ }
+ return "The Forecast for the Weekend is Scattered Showers.";
+ }
+
+ @Retry(retryOn = WeatherGatewayTimeoutException.class, delay = 500, jitter = 500)
+ public String statusOfMonth() {
+ if (counterStatusOfWeekend.addAndGet(1) <= DEFAULT_MAX_RETRY) {
+ logTimeoutMessage(statusOfMonthInstant);
+ statusOfMonthInstant = Instant.now();
+ throw new WeatherGatewayTimeoutException();
+ }
+ return "The Forecast for the Month is Sunny for most of the days";
+ }
+
+ @Retry(maxDuration = 1000)
+ public String statusOfYear(){
+ if (counterStatusOfWeekend.addAndGet(1) <= 5) {
+ logTimeoutMessage(statusOfYearInstant);
+ statusOfYearInstant = Instant.now();
+ throw new RuntimeException();
+ }
+ return "WeatherGateway Service Error";
+ }
+
+ private void logTimeoutMessage(Instant instant) {
+ if(instant == null){
+ LOGGER.warning(FORECAST_TIMEOUT_MESSAGE);
+ }else{
+ LOGGER.warning(String.format(FORECAST_TIMEOUT_MESSAGE_DELAY,
+ Duration.between(instant, Instant.now()).toMillis()));
+ }
+ }
+}
diff --git a/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherGatewayBusyServiceException.java b/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherGatewayBusyServiceException.java
new file mode 100644
index 0000000..996fd7b
--- /dev/null
+++ b/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherGatewayBusyServiceException.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+public class WeatherGatewayBusyServiceException extends RuntimeException {
+}
diff --git a/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherGatewayTimeoutException.java b/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherGatewayTimeoutException.java
new file mode 100644
index 0000000..098010c
--- /dev/null
+++ b/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherGatewayTimeoutException.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+
+public class WeatherGatewayTimeoutException extends RuntimeException {
+}
diff --git a/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherService.java b/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherService.java
new file mode 100644
index 0000000..8cb17ce
--- /dev/null
+++ b/examples/mp-faulttolerance-retry/src/main/java/org/superbiz/rest/WeatherService.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+import javax.enterprise.context.RequestScoped;
+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 javax.ws.rs.core.Response;
+
+
+@Path("/weather")
+@Produces(MediaType.TEXT_PLAIN)
+@RequestScoped
+public class WeatherService {
+
+ @Inject
+ private WeatherGateway weatherService;
+
+ @GET
+ @Path("/day/status")
+ public String dayStatus() {
+ return weatherService.statusOfDay();
+ }
+
+ @GET
+ @Path("/week/status")
+ public Response weekStatus() {
+ try {
+ return Response.ok().entity(weatherService.statusOfWeek()).build();
+ } catch (WeatherGatewayBusyServiceException e) {
+ return Response.serverError().entity("WeatherGateway Service is Busy. Retry later").build();
+ }
+ }
+
+ @GET
+ @Path("/weekend/status")
+ public Response weekendStatus() {
+ return Response.ok().entity(weatherService.statusOfWeekend()).build();
+ }
+
+ @GET
+ @Path("/month/status")
+ public Response monthStatus() {
+ return Response.ok().entity(weatherService.statusOfMonth()).build();
+ }
+
+ @GET
+ @Path("/year/status")
+ public Response yearStatus() {
+ try {
+ return Response.ok().entity(weatherService.statusOfYear()).build();
+ } catch (RuntimeException e) {
+ return Response.serverError().entity("WeatherGateway Service Timeout").build();
+ }
+ }
+}
diff --git a/examples/mp-faulttolerance-retry/src/test/java/org/superbiz/rest/WeatherServiceTest.java b/examples/mp-faulttolerance-retry/src/test/java/org/superbiz/rest/WeatherServiceTest.java
new file mode 100644
index 0000000..d8a12e2
--- /dev/null
+++ b/examples/mp-faulttolerance-retry/src/test/java/org/superbiz/rest/WeatherServiceTest.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.URL;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Arquillian.class)
+public class WeatherServiceTest {
+
+ @ArquillianResource
+ private URL base;
+
+ private Client client;
+
+ @Deployment(testable = false)
+ public static WebArchive createDeployment() {
+ return ShrinkWrap.create(WebArchive.class, "test.war").addPackage(WeatherService.class.getPackage());
+ }
+
+ @Before
+ public void before() {
+ this.client = ClientBuilder.newClient();
+ }
+
+ @Test
+ public void testStatusOfDay() {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ Response response = webTarget.path("/weather/day/status").request().get();
+ assertEquals("Hi, today is a sunny day!", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testStatusOfWeek() {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ Response response = webTarget.path("/weather/week/status").request().get();
+ assertEquals("WeatherGateway Service is Busy. Retry later", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testStatusOfWeekend() {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ Response response = webTarget.path("/weather/weekend/status").request().get();
+ assertEquals("The Forecast for the Weekend is Scattered Showers.", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testStatusOfMonth() {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ Response response = webTarget.path("/weather/month/status").request().get();
+ assertEquals("The Forecast for the Month is Sunny for most of the days", response.readEntity(String.class));
+ }
+
+ @Test
+ public void testStatusOfYear() {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ Response response = webTarget.path("/weather/year/status").request().get();
+ assertEquals("WeatherGateway Service Timeout", response.readEntity(String.class));
+ }
+
+ @After
+ public void after() {
+ this.client.close();
+ }
+}
diff --git a/examples/mp-faulttolerance-retry/src/test/resources/arquillian.xml b/examples/mp-faulttolerance-retry/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..3029d48
--- /dev/null
+++ b/examples/mp-faulttolerance-retry/src/test/resources/arquillian.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <container qualifier="tomee" default="true">
+ <configuration>
+ <property name="httpPort">-1</property>
+ <property name="stopPort">-1</property>
+ <property name="classifier">microprofile</property>
+ <property name="dir">target/apache-tomee-remote</property>
+ <property name="appWorkingDir">target/arquillian-test-working-dir</property>
+ </configuration>
+ </container>
+</arquillian>
\ No newline at end of file
diff --git a/examples/mp-faulttolerance-retry/src/test/resources/beans.xml b/examples/mp-faulttolerance-retry/src/test/resources/beans.xml
new file mode 100644
index 0000000..d942d7a
--- /dev/null
+++ b/examples/mp-faulttolerance-retry/src/test/resources/beans.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+</beans>
\ No newline at end of file
diff --git a/examples/mp-faulttolerance-timeout/README.adoc b/examples/mp-faulttolerance-timeout/README.adoc
new file mode 100644
index 0000000..7916229
--- /dev/null
+++ b/examples/mp-faulttolerance-timeout/README.adoc
@@ -0,0 +1,108 @@
+= MicroProfile Fault Tolerance - Timeout
+:index-group: MicroProfile
+:jbake-type: page
+:jbake-status: published
+
+This is an example of how to use Microprofile @Timeout in TomEE.
+
+[discrete]
+== Timeout Feature
+
+Fault Tolerance Timeout allow to specify how long a task can take to complete its execution and aborting it
+in case of timeout. Timeout feature can be used along with other annotations to guide the execution and result of a task. +
+Check the
+https://download.eclipse.org/microprofile/microprofile-fault-tolerance-1.1/microprofile-fault-tolerance-spec.html#_timeout_usage[specification]
+for more details.
+
+Timeout annotation allows to configure :
+
+* *value:* the timeout value
+* *unit:* the timeout unit
+
+[discrete]
+== Example
+
+[discrete]
+=== Run the application
+
+[source,text]
+----
+mvn clean install tomee:run
+----
+
+[discrete]
+=== How does it work?
+
+The method `statusOfDayByAccuWeather` fails when the threshold of `@Timeout` annotation is reached due to a long execution of
+`longProcessingTask` method. To respond to the request nicely, a fallback method will take place to complete the request
+successfully. The fallback method is determined by @Fallback annotation.
+
+[source,java]
+----
+@RequestScoped
+public class WeatherGateway {
+
+ private static final Logger LOGGER = Logger.getLogger(WeatherGateway.class.getName());
+
+ @Timeout(50)
+ @Fallback(fallbackMethod = "statusOfWeekByMetEireann")
+ public String statusOfDayByAccuWeather(){
+ return longProcessingTask();
+ }
+
+ public String statusOfWeekByMetEireann(){
+ LOGGER.log(Level.WARNING, "MetEireann backup service has been requested due to AccuWeather timeout");
+ return "Beautiful day";
+ }
+
+ private String longProcessingTask(){
+ try {
+ Thread.sleep(80);
+ } catch (InterruptedException e) {
+ LOGGER.log(Level.WARNING,"AccuWeather task has been interrupted.");
+ }
+ return null;
+ }
+ ...
+}
+----
+
+Day status call
+
+[source,text]
+----
+GET http://localhost:8080/mp-faulttolerance-timeout/weather/day/status
+----
+
+Server log
+
+[source,text]
+----
+WARNING AccuWeather task has been interrupted.
+WARNING MetEireann fallback service has been requested due to AccuWeather timeout.
+----
+
+Response
+
+[source,text]
+----
+Beautiful day!
+----
+
+[discrete]
+=== Running the test
+
+You can also try it out using the
+link:src/test/java/org/superbiz/rest/WeatherServiceTest.java[WeatherServiceTest.java]
+available in the project.
+
+[source,text]
+----
+mvn clean test
+----
+
+----
+[INFO] Results:
+[INFO]
+[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
diff --git a/examples/mp-faulttolerance-timeout/pom.xml b/examples/mp-faulttolerance-timeout/pom.xml
new file mode 100644
index 0000000..3b5583c
--- /dev/null
+++ b/examples/mp-faulttolerance-timeout/pom.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.superbiz</groupId>
+ <artifactId>mp-faulttolerance-timeout</artifactId>
+ <version>7.1.2-SNAPSHOT</version>
+ <packaging>war</packaging>
+ <name>OpenEJB :: Examples :: Microprofile Fault Tolerance :: Timeout</name>
+
+ <properties>
+ <microprofile-fault-tolerance-api.version>1.0</microprofile-fault-tolerance-api.version>
+ <arquillian-junit-container.version>1.4.0.Final</arquillian-junit-container.version>
+ <maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
+ <maven-war-plugin.version>3.1.0</maven-war-plugin.version>
+ <tomee.version>7.1.2-SNAPSHOT</tomee.version>
+ <javaee-api.version>7.0</javaee-api.version>
+ <junit.version>4.12</junit.version>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>javaee-api</artifactId>
+ <version>${javaee-api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.microprofile.fault-tolerance</groupId>
+ <artifactId>microprofile-fault-tolerance-api</artifactId>
+ <version>${microprofile-fault-tolerance-api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>openejb-cxf-rs</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.junit</groupId>
+ <artifactId>arquillian-junit-container</artifactId>
+ <version>${arquillian-junit-container.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>arquillian-tomee-remote</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>apache-tomee</artifactId>
+ <version>${tomee.version}</version>
+ <type>zip</type>
+ <classifier>microprofile</classifier>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.tomee.maven</groupId>
+ <artifactId>tomee-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <configuration>
+ <tomeeClassifier>microprofile</tomeeClassifier>
+ <context>${project.artifactId}</context>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>${maven-war-plugin.version}</version>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <!--
+ This section allows you to configure where to publish libraries for sharing.
+ It is not required and may be deleted. For more information see:
+ http://maven.apache.org/plugins/maven-deploy-plugin/
+ -->
+ <distributionManagement>
+ <repository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/repo/</url>
+ </repository>
+ <snapshotRepository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/snapshot-repo/</url>
+ </snapshotRepository>
+ </distributionManagement>
+
+</project>
diff --git a/examples/mp-faulttolerance-timeout/src/main/java/org/superbiz/rest/WeatherGateway.java b/examples/mp-faulttolerance-timeout/src/main/java/org/superbiz/rest/WeatherGateway.java
new file mode 100644
index 0000000..ad7d27a
--- /dev/null
+++ b/examples/mp-faulttolerance-timeout/src/main/java/org/superbiz/rest/WeatherGateway.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.enterprise.context.RequestScoped;
+import org.eclipse.microprofile.faulttolerance.Fallback;
+import org.eclipse.microprofile.faulttolerance.Timeout;
+
+@RequestScoped
+public class WeatherGateway {
+
+ private static final Logger LOGGER = Logger.getLogger(WeatherGateway.class.getName());
+
+ @Timeout(50)
+ @Fallback(fallbackMethod = "statusOfWeekByMetEireann")
+ public String statusOfDayByAccuWeather(){
+ return longProcessingTask();
+ }
+
+ public String statusOfWeekByMetEireann(){
+ LOGGER.log(Level.WARNING, "MetEireann backup service has been requested due to AccuWeather timeout");
+ return "Beautiful day";
+ }
+
+ private String longProcessingTask(){
+ try {
+ Thread.sleep(80);
+ } catch (InterruptedException e) {
+ LOGGER.log(Level.WARNING,"AccuWeather task has been interrupted.");
+ }
+ return null;
+ }
+}
diff --git a/examples/mp-faulttolerance-timeout/src/main/java/org/superbiz/rest/WeatherService.java b/examples/mp-faulttolerance-timeout/src/main/java/org/superbiz/rest/WeatherService.java
new file mode 100644
index 0000000..9ecb1f8
--- /dev/null
+++ b/examples/mp-faulttolerance-timeout/src/main/java/org/superbiz/rest/WeatherService.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+import javax.enterprise.context.RequestScoped;
+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;
+
+@Path("/weather")
+@RequestScoped
+public class WeatherService {
+
+ @Inject
+ private WeatherGateway weatherService;
+
+ @GET
+ @Path("/day/status")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String dayStatus() {
+ return weatherService.statusOfDayByAccuWeather();
+ }
+}
diff --git a/examples/mp-faulttolerance-timeout/src/test/java/org/superbiz/rest/WeatherServiceTest.java b/examples/mp-faulttolerance-timeout/src/test/java/org/superbiz/rest/WeatherServiceTest.java
new file mode 100644
index 0000000..b626a70
--- /dev/null
+++ b/examples/mp-faulttolerance-timeout/src/test/java/org/superbiz/rest/WeatherServiceTest.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.superbiz.rest;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.URL;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Arquillian.class)
+public class WeatherServiceTest {
+
+ @ArquillianResource
+ private URL base;
+
+ private Client client;
+
+ @Deployment(testable = false)
+ public static WebArchive createDeployment() {
+ return ShrinkWrap.create(WebArchive.class, "test.war").addPackage(WeatherService.class.getPackage());
+ }
+
+ @Before
+ public void before() {
+ this.client = ClientBuilder.newClient();
+ }
+
+ @Test
+ public void testStatusOfDay() {
+ WebTarget webTarget = this.client.target(this.base.toExternalForm());
+ Response response = webTarget.path("/weather/day/status").request().get();
+ assertEquals("Beautiful day", response.readEntity(String.class));
+ }
+
+ @After
+ public void after() {
+ this.client.close();
+ }
+}
diff --git a/examples/mp-faulttolerance-timeout/src/test/resources/arquillian.xml b/examples/mp-faulttolerance-timeout/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..3029d48
--- /dev/null
+++ b/examples/mp-faulttolerance-timeout/src/test/resources/arquillian.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <container qualifier="tomee" default="true">
+ <configuration>
+ <property name="httpPort">-1</property>
+ <property name="stopPort">-1</property>
+ <property name="classifier">microprofile</property>
+ <property name="dir">target/apache-tomee-remote</property>
+ <property name="appWorkingDir">target/arquillian-test-working-dir</property>
+ </configuration>
+ </container>
+</arquillian>
\ No newline at end of file
diff --git a/examples/mp-faulttolerance-timeout/src/test/resources/beans.xml b/examples/mp-faulttolerance-timeout/src/test/resources/beans.xml
new file mode 100644
index 0000000..d942d7a
--- /dev/null
+++ b/examples/mp-faulttolerance-timeout/src/test/resources/beans.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+</beans>
\ No newline at end of file
diff --git a/examples/mp-opentracing-traced/README.adoc b/examples/mp-opentracing-traced/README.adoc
new file mode 100644
index 0000000..b1ae708
--- /dev/null
+++ b/examples/mp-opentracing-traced/README.adoc
@@ -0,0 +1,63 @@
+= MicroProfile OpenTracing @Traced
+:index-group: MicroProfile
+:jbake-type: page
+:jbake-status: published
+
+
+This is an example on how to use the @Traced annotation in TomEE.
+
+NOTE: This example is a work in progress.
+
+===== Run the application:
+
+ mvn clean install tomee:run
+
+
+NOTE: Add text here for information about the endpoint.
+
+===== Request:
+
+ curl -X GET http://localhost:8080/mp-opentracing-traced/...
+
+NOTE: Complete the URL for the above `curl` command.
+
+===== Response:
+
+NOTE: Add the response from the example application
+
+==== @Traced Feature
+
+NOTE: Add text here to include how to implement and some source code.
+
+===== For the traced status:
+
+ GET http://localhost:8080/mp-opentracing-traced/...
+
+NOTE: Complete the URL for the above `curl` command.
+
+===== Reponse:
+
+
+===== Expected Prometheus format:
+
+===== Request:
+
+ curl -X GET http://localhost:8080/mp-opentracing-traced/...
+
+NOTE: Complete the URL for the above `curl` command.
+
+===== Response:
+
+==== Metric Metadata:
+
+===== Request:
+
+ curl -X OPTIONS http://localhost:8080/mp-opentracing/traced/...
+
+NOTE: Complete the URL for the above `curl` command.
+
+===== Response:
+
+===== Test the application:
+
+ mvn test
diff --git a/examples/mp-opentracing-traced/pom.xml b/examples/mp-opentracing-traced/pom.xml
new file mode 100644
index 0000000..dd6e68c
--- /dev/null
+++ b/examples/mp-opentracing-traced/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.superbiz</groupId>
+ <artifactId>mp-opentracing.traced</artifactId>
+ <version>7.1.2-SNAPSHOT</version>
+ <packaging>war</packaging>
+
+ <properties>
+ <version.javaee-api>7.0</version.javaee-api>
+ <tomee.version>7.1.2-SNAPSHOT</tomee.version>
+ <version.arquillian.bom>1.1.13.Final</version.arquillian.bom>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>javaee-api</artifactId>
+ <version>${version.javaee-api}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>openejb-cxf-rs</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.junit</groupId>
+ <artifactId>arquillian-junit-container</artifactId>
+ <version>${version.arquillian.bom}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>arquillian-tomee-remote</artifactId>
+ <version>${tomee.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomee</groupId>
+ <artifactId>apache-tomee</artifactId>
+ <version>${tomee.version}</version>
+ <type>zip</type>
+ <classifier>microprofile</classifier>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.tomee.maven</groupId>
+ <artifactId>tomee-maven-plugin</artifactId>
+ <version>${tomee.version}</version>
+ <configuration>
+ <tomeeClassifier>microprofile</tomeeClassifier>
+ <context>${project.artifactId}</context>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>3.1.0</version>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <!-- This section allows you to configure where to publish libraries for
+ sharing. It is not required and may be deleted. For more information see:
+ http://maven.apache.org/plugins/maven-deploy-plugin/ -->
+ <distributionManagement>
+ <repository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/repo/</url>
+ </repository>
+ <snapshotRepository>
+ <id>localhost</id>
+ <url>file://${basedir}/target/snapshot-repo/</url>
+ </snapshotRepository>
+ </distributionManagement>
+</project>
diff --git a/examples/mp-opentracing-traced/src/test/resources/arquillian.xml b/examples/mp-opentracing-traced/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..3029d48
--- /dev/null
+++ b/examples/mp-opentracing-traced/src/test/resources/arquillian.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <container qualifier="tomee" default="true">
+ <configuration>
+ <property name="httpPort">-1</property>
+ <property name="stopPort">-1</property>
+ <property name="classifier">microprofile</property>
+ <property name="dir">target/apache-tomee-remote</property>
+ <property name="appWorkingDir">target/arquillian-test-working-dir</property>
+ </configuration>
+ </container>
+</arquillian>
\ No newline at end of file
diff --git a/examples/pom.xml b/examples/pom.xml
index c241835..620b729 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -98,6 +98,11 @@
<module>mbean-auto-registration</module>
<module>movies-complete-meta</module>
<module>movies-complete</module>
+ <module>mp-config-example</module>
+ <module>mp-config-source-database</module>
+ <module>mp-faulttolerance-fallback</module>
+ <module>mp-faulttolerance-retry</module>
+ <module>mp-opentracing-traced</module>
<module>mtom</module>
<module>multi-jpa-provider-testing</module>
<module>multiple-arquillian-adapters</module>