optionalApplicationProperty;
78 |
79 | @Override
80 | public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
81 | response.setContentType("text/plain");
82 | response.getWriter().write(
83 | "default.property : " + defaultProperty + "\n" +
84 | "file.property : " + fileProperty + "\n" +
85 | "application.property : " + applicationProperty + "\n" +
86 | "application.optionalProperty : " + optionalApplicationProperty.orElse("Not defined") + "\n"
87 | );
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/config/basic-injection/src/main/resources/META-INF/microprofile-config.properties:
--------------------------------------------------------------------------------
1 | # Example application properties file
2 | file.property=File Property
3 | date.property=2000-01-01
4 | application.property=Some value
5 |
--------------------------------------------------------------------------------
/config/basic-injection/src/test/java/org/eclipse/microprofile12/config/basicinjection/BasicInjectionTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.config.basicinjection;
2 |
3 | import static javax.ws.rs.client.ClientBuilder.newClient;
4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
5 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
6 | import static org.junit.Assert.assertTrue;
7 |
8 | import java.io.IOException;
9 | import java.net.URI;
10 | import java.net.URL;
11 |
12 | import org.jboss.arquillian.container.test.api.Deployment;
13 | import org.jboss.arquillian.container.test.api.RunAsClient;
14 | import org.jboss.arquillian.junit.Arquillian;
15 | import org.jboss.arquillian.test.api.ArquillianResource;
16 | import org.jboss.shrinkwrap.api.spec.WebArchive;
17 | import org.junit.Test;
18 | import org.junit.runner.RunWith;
19 |
20 | /**
21 | * @author Arjan Tijms
22 | */
23 | @RunWith(Arquillian.class)
24 | public class BasicInjectionTest {
25 |
26 | @ArquillianResource
27 | private URL base;
28 |
29 | @Deployment(testable = false)
30 | public static WebArchive createDeployment() {
31 | WebArchive archive =
32 | create(WebArchive.class, "BasicInjectionTest.war")
33 | .addClasses(
34 | ApplicationInit.class,
35 | Servlet.class
36 | ).addAsResource(
37 | "META-INF/microprofile-config.properties"
38 | )
39 | ;
40 |
41 | System.out.println("************************************************************");
42 | System.out.println(archive.toString(true));
43 | System.out.println("************************************************************");
44 |
45 | return archive;
46 | }
47 |
48 | @Test
49 | @RunAsClient
50 | public void testBasicInjection() throws IOException {
51 |
52 | String response =
53 | newClient()
54 | .target(
55 | URI.create(new URL(base, "servlet").toExternalForm()))
56 | .request(TEXT_PLAIN)
57 | .get(String.class);
58 |
59 | System.out.println("-------------------------------------------------------------------------");
60 | System.out.println("Response: " + response);
61 | System.out.println("-------------------------------------------------------------------------");
62 |
63 | assertTrue(
64 | response.contains("default.property : Default Value")
65 | );
66 |
67 | assertTrue(
68 | response.contains("file.property : File Property")
69 | );
70 |
71 | assertTrue(
72 | response.contains("application.property : Some value")
73 | );
74 |
75 | }
76 |
77 | @Test
78 | @RunAsClient
79 | public void testOptional() throws IOException {
80 |
81 | String response =
82 | newClient()
83 | .target(
84 | URI.create(new URL(base, "servlet").toExternalForm()))
85 | .request(TEXT_PLAIN)
86 | .get(String.class);
87 |
88 | System.out.println("-------------------------------------------------------------------------");
89 | System.out.println("Response: " + response);
90 | System.out.println("-------------------------------------------------------------------------");
91 |
92 | assertTrue(
93 | // Liberty
94 | response.contains("application.optionalProperty : Not defined") ||
95 |
96 | // Payara and WildFly
97 | response.contains("application.optionalProperty : org.eclipse.microprofile.config.configproperty.unconfigureddvalue")
98 | );
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/config/config-source/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | org.eclipse.microprofile.samples12
6 | config
7 | 1.0-SNAPSHOT
8 |
9 |
10 | config-source
11 | war
12 | MicroProfile 1.2: Config - Config Source
13 |
14 |
15 |
--------------------------------------------------------------------------------
/config/config-source/src/main/java/org/eclipse/microprofile12/config/configsource/ApplicationInit.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.config.configsource;
2 |
3 | import javax.enterprise.context.ApplicationScoped;
4 |
5 | @ApplicationScoped
6 | public class ApplicationInit {
7 |
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/config/config-source/src/main/java/org/eclipse/microprofile12/config/configsource/EchoConfigSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 | *
4 | * Copyright (c) 2017-2018 Payara Foundation and/or its affiliates. All rights reserved.
5 | *
6 | * The contents of this file are subject to the terms of either the GNU
7 | * General Public License Version 2 only ("GPL") or the Common Development
8 | * and Distribution License("CDDL") (collectively, the "License"). You
9 | * may not use this file except in compliance with the License. You can
10 | * obtain a copy of the License at
11 | * https://github.com/payara/Payara/blob/master/LICENSE.txt
12 | * See the License for the specific
13 | * language governing permissions and limitations under the License.
14 | *
15 | * When distributing the software, include this License Header Notice in each
16 | * file and include the License file at glassfish/legal/LICENSE.txt.
17 | *
18 | * GPL Classpath Exception:
19 | * The Payara Foundation designates this particular file as subject to the "Classpath"
20 | * exception as provided by the Payara Foundation in the GPL Version 2 section of the License
21 | * file that accompanied this code.
22 | *
23 | * Modifications:
24 | * If applicable, add the following below the License Header, with the fields
25 | * enclosed by brackets [] replaced by your own identifying information:
26 | * "Portions Copyright [year] [name of copyright owner]"
27 | *
28 | * Contributor(s):
29 | * If you wish your version of this file to be governed by only the CDDL or
30 | * only the GPL Version 2, indicate your decision by adding "[Contributor]
31 | * elects to include this software in this distribution under the [CDDL or GPL
32 | * Version 2] license." If you don't indicate a single choice of license, a
33 | * recipient has the option to distribute your version of this file under
34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to
35 | * its licensees as provided above. However, if you add GPL Version 2 code
36 | * and therefore, elected the GPL Version 2 license, then the option applies
37 | * only if the new code is made subject to such option by the copyright
38 | * holder.
39 | */
40 | package org.eclipse.microprofile12.config.configsource;
41 |
42 | import java.util.HashMap;
43 | import java.util.Map;
44 |
45 | import org.eclipse.microprofile.config.spi.ConfigSource;
46 |
47 | /**
48 | *
49 | * Example config source that echos back the input prepending the string "ECHO: " This config source
50 | * will resolve only property names that start with "echo." prefix, otherwise returns null.
51 | *
52 | *
53 | * Note: On Payara and WildFly this will function as a dynamic source, but on Liberty the protection
54 | * mandated by the spec to only handle declared property names is enforced.
55 | *
56 | * @author Steve Millidge (Payara Foundation)
57 | */
58 | public class EchoConfigSource implements ConfigSource {
59 |
60 | @Override
61 | public Map getProperties() {
62 | Map properties = new HashMap<>();
63 | properties.put("echo.property", getValue("echo.property"));
64 | return properties;
65 | }
66 |
67 | @Override
68 | public int getOrdinal() {
69 | return 10;
70 | }
71 |
72 | @Override
73 | public String getValue(String propertyName) {
74 | if (propertyName.startsWith("echo.")) {
75 | return "ECHO: " + propertyName;
76 | }
77 |
78 | return null;
79 | }
80 |
81 | @Override
82 | public String getName() {
83 | return "Echo";
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/config/config-source/src/main/java/org/eclipse/microprofile12/config/configsource/Servlet.java:
--------------------------------------------------------------------------------
1 | /*
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 | *
4 | * Copyright (c) 2017-2018 Payara Foundation and/or its affiliates. All rights reserved.
5 | *
6 | * The contents of this file are subject to the terms of either the GNU
7 | * General Public License Version 2 only ("GPL") or the Common Development
8 | * and Distribution License("CDDL") (collectively, the "License"). You
9 | * may not use this file except in compliance with the License. You can
10 | * obtain a copy of the License at
11 | * https://github.com/payara/Payara/blob/master/LICENSE.txt
12 | * See the License for the specific
13 | * language governing permissions and limitations under the License.
14 | *
15 | * When distributing the software, include this License Header Notice in each
16 | * file and include the License file at glassfish/legal/LICENSE.txt.
17 | *
18 | * GPL Classpath Exception:
19 | * The Payara Foundation designates this particular file as subject to the "Classpath"
20 | * exception as provided by the Payara Foundation in the GPL Version 2 section of the License
21 | * file that accompanied this code.
22 | *
23 | * Modifications:
24 | * If applicable, add the following below the License Header, with the fields
25 | * enclosed by brackets [] replaced by your own identifying information:
26 | * "Portions Copyright [year] [name of copyright owner]"
27 | *
28 | * Contributor(s):
29 | * If you wish your version of this file to be governed by only the CDDL or
30 | * only the GPL Version 2, indicate your decision by adding "[Contributor]
31 | * elects to include this software in this distribution under the [CDDL or GPL
32 | * Version 2] license." If you don't indicate a single choice of license, a
33 | * recipient has the option to distribute your version of this file under
34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to
35 | * its licensees as provided above. However, if you add GPL Version 2 code
36 | * and therefore, elected the GPL Version 2 license, then the option applies
37 | * only if the new code is made subject to such option by the copyright
38 | * holder.
39 | */
40 | package org.eclipse.microprofile12.config.configsource;
41 |
42 | import java.io.IOException;
43 |
44 | import javax.inject.Inject;
45 | import javax.servlet.ServletException;
46 | import javax.servlet.annotation.WebServlet;
47 | import javax.servlet.http.HttpServlet;
48 | import javax.servlet.http.HttpServletRequest;
49 | import javax.servlet.http.HttpServletResponse;
50 |
51 | import org.eclipse.microprofile.config.inject.ConfigProperty;
52 |
53 |
54 | @WebServlet("/servlet")
55 | public class Servlet extends HttpServlet {
56 |
57 | private static final long serialVersionUID = 1L;
58 |
59 | @Inject
60 | @ConfigProperty(name = "echo.property", defaultValue = "Provided if EchoConfigSource disabled")
61 | private String propertyFromEchoConfigSource;
62 |
63 | @Override
64 | public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
65 |
66 | response.setContentType("text/plain");
67 |
68 | response.getWriter().write(
69 |
70 | "echo.property : " + propertyFromEchoConfigSource);
71 |
72 |
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/config/config-source/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource:
--------------------------------------------------------------------------------
1 | org.eclipse.microprofile12.config.configsource.EchoConfigSource
2 |
--------------------------------------------------------------------------------
/config/config-source/src/test/java/org/eclipse/microprofile12/config/configsource/ConfigSourceNotPresentTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.config.configsource;
2 |
3 | import static javax.ws.rs.client.ClientBuilder.newClient;
4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
5 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
6 | import static org.junit.Assert.assertTrue;
7 | import static org.junit.Assert.assertFalse;
8 |
9 | import java.io.IOException;
10 | import java.net.URI;
11 | import java.net.URL;
12 |
13 | import org.jboss.arquillian.container.test.api.Deployment;
14 | import org.jboss.arquillian.container.test.api.RunAsClient;
15 | import org.jboss.arquillian.junit.Arquillian;
16 | import org.jboss.arquillian.test.api.ArquillianResource;
17 | import org.jboss.shrinkwrap.api.spec.WebArchive;
18 | import org.junit.Test;
19 | import org.junit.runner.RunWith;
20 |
21 | /**
22 | * @author Arjan Tijms
23 | */
24 | @RunWith(Arquillian.class)
25 | public class ConfigSourceNotPresentTest {
26 |
27 | @ArquillianResource
28 | private URL base;
29 |
30 | @Deployment(testable = false)
31 | public static WebArchive createDeployment() {
32 | WebArchive archive =
33 | create(WebArchive.class, "ConfigSourceNotPresentTest.war")
34 | .addClasses(
35 | ApplicationInit.class,
36 | Servlet.class
37 | )
38 | ;
39 |
40 | System.out.println("************************************************************");
41 | System.out.println(archive.toString(true));
42 | System.out.println("************************************************************");
43 |
44 | return archive;
45 | }
46 |
47 | @Test
48 | @RunAsClient
49 | public void testConfigNotSourcePresent() throws IOException {
50 |
51 | String response =
52 | newClient()
53 | .target(
54 | URI.create(new URL(base, "servlet").toExternalForm()))
55 | .request(TEXT_PLAIN)
56 | .get(String.class);
57 |
58 | System.out.println("-------------------------------------------------------------------------");
59 | System.out.println("Response: " + response);
60 | System.out.println("-------------------------------------------------------------------------");
61 |
62 | assertFalse(
63 | response.contains("echo.property : ECHO: echo.property")
64 | );
65 |
66 | assertTrue(
67 | response.contains("echo.property : Provided if EchoConfigSource disabled")
68 | );
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/config/config-source/src/test/java/org/eclipse/microprofile12/config/configsource/ConfigSourcePresentTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.config.configsource;
2 |
3 | import static javax.ws.rs.client.ClientBuilder.newClient;
4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
5 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
6 | import static org.junit.Assert.assertTrue;
7 |
8 | import java.io.IOException;
9 | import java.net.URI;
10 | import java.net.URL;
11 |
12 | import org.jboss.arquillian.container.test.api.Deployment;
13 | import org.jboss.arquillian.container.test.api.RunAsClient;
14 | import org.jboss.arquillian.junit.Arquillian;
15 | import org.jboss.arquillian.test.api.ArquillianResource;
16 | import org.jboss.shrinkwrap.api.spec.WebArchive;
17 | import org.junit.Test;
18 | import org.junit.runner.RunWith;
19 |
20 | /**
21 | * @author Arjan Tijms
22 | */
23 | @RunWith(Arquillian.class)
24 | public class ConfigSourcePresentTest {
25 |
26 | @ArquillianResource
27 | private URL base;
28 |
29 | @Deployment(testable = false)
30 | public static WebArchive createDeployment() {
31 | WebArchive archive =
32 | create(WebArchive.class, "ConfigSourcePresentTest.war")
33 | .addClasses(
34 | ApplicationInit.class,
35 | EchoConfigSource.class,
36 | Servlet.class
37 | ).addAsResource(
38 | "META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource"
39 | )
40 | ;
41 |
42 | System.out.println("************************************************************");
43 | System.out.println(archive.toString(true));
44 | System.out.println("************************************************************");
45 |
46 | return archive;
47 | }
48 |
49 | @Test
50 | @RunAsClient
51 | public void testConfigSourcePresent() throws IOException {
52 |
53 | String response =
54 | newClient()
55 | .target(
56 | URI.create(new URL(base, "servlet").toExternalForm()))
57 | .request(TEXT_PLAIN)
58 | .get(String.class);
59 |
60 | System.out.println("-------------------------------------------------------------------------");
61 | System.out.println("Response: " + response);
62 | System.out.println("-------------------------------------------------------------------------");
63 |
64 | assertTrue(
65 | response.contains("echo.property : ECHO: echo.property")
66 | );
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/config/converter/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | org.eclipse.microprofile.samples12
6 | config
7 | 1.0-SNAPSHOT
8 |
9 |
10 | converter
11 | war
12 | MicroProfile 1.2: Config - Converter
13 |
14 |
15 |
--------------------------------------------------------------------------------
/config/converter/src/main/java/org/eclipse/microprofile12/config/converter/ApplicationInit.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.config.converter;
2 |
3 | import javax.enterprise.context.ApplicationScoped;
4 |
5 | @ApplicationScoped
6 | public class ApplicationInit {
7 |
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/config/converter/src/main/java/org/eclipse/microprofile12/config/converter/CustomConverter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 | *
4 | * Copyright (c) 2017-2018 Payara Foundation and/or its affiliates. All rights reserved.
5 | *
6 | * The contents of this file are subject to the terms of either the GNU
7 | * General Public License Version 2 only ("GPL") or the Common Development
8 | * and Distribution License("CDDL") (collectively, the "License"). You
9 | * may not use this file except in compliance with the License. You can
10 | * obtain a copy of the License at
11 | * https://github.com/payara/Payara/blob/master/LICENSE.txt
12 | * See the License for the specific
13 | * language governing permissions and limitations under the License.
14 | *
15 | * When distributing the software, include this License Header Notice in each
16 | * file and include the License file at glassfish/legal/LICENSE.txt.
17 | *
18 | * GPL Classpath Exception:
19 | * The Payara Foundation designates this particular file as subject to the "Classpath"
20 | * exception as provided by the Payara Foundation in the GPL Version 2 section of the License
21 | * file that accompanied this code.
22 | *
23 | * Modifications:
24 | * If applicable, add the following below the License Header, with the fields
25 | * enclosed by brackets [] replaced by your own identifying information:
26 | * "Portions Copyright [year] [name of copyright owner]"
27 | *
28 | * Contributor(s):
29 | * If you wish your version of this file to be governed by only the CDDL or
30 | * only the GPL Version 2, indicate your decision by adding "[Contributor]
31 | * elects to include this software in this distribution under the [CDDL or GPL
32 | * Version 2] license." If you don't indicate a single choice of license, a
33 | * recipient has the option to distribute your version of this file under
34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to
35 | * its licensees as provided above. However, if you add GPL Version 2 code
36 | * and therefore, elected the GPL Version 2 license, then the option applies
37 | * only if the new code is made subject to such option by the copyright
38 | * holder.
39 | */
40 | package org.eclipse.microprofile12.config.converter;
41 |
42 | import org.eclipse.microprofile.config.spi.Converter;
43 |
44 | /**
45 | * Example Custom Converter that wraps the value in a TestPojo object
46 | *
47 | * @author Steve Millidge (Payara Foundation)
48 | */
49 | public class CustomConverter implements Converter {
50 |
51 | @Override
52 | public TestPojo convert(String value) {
53 | TestPojo result = new TestPojo();
54 | result.value = value;
55 | return result;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/config/converter/src/main/java/org/eclipse/microprofile12/config/converter/Servlet.java:
--------------------------------------------------------------------------------
1 | /*
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 | *
4 | * Copyright (c) 2017-2018 Payara Foundation and/or its affiliates. All rights reserved.
5 | *
6 | * The contents of this file are subject to the terms of either the GNU
7 | * General Public License Version 2 only ("GPL") or the Common Development
8 | * and Distribution License("CDDL") (collectively, the "License"). You
9 | * may not use this file except in compliance with the License. You can
10 | * obtain a copy of the License at
11 | * https://github.com/payara/Payara/blob/master/LICENSE.txt
12 | * See the License for the specific
13 | * language governing permissions and limitations under the License.
14 | *
15 | * When distributing the software, include this License Header Notice in each
16 | * file and include the License file at glassfish/legal/LICENSE.txt.
17 | *
18 | * GPL Classpath Exception:
19 | * The Payara Foundation designates this particular file as subject to the "Classpath"
20 | * exception as provided by the Payara Foundation in the GPL Version 2 section of the License
21 | * file that accompanied this code.
22 | *
23 | * Modifications:
24 | * If applicable, add the following below the License Header, with the fields
25 | * enclosed by brackets [] replaced by your own identifying information:
26 | * "Portions Copyright [year] [name of copyright owner]"
27 | *
28 | * Contributor(s):
29 | * If you wish your version of this file to be governed by only the CDDL or
30 | * only the GPL Version 2, indicate your decision by adding "[Contributor]
31 | * elects to include this software in this distribution under the [CDDL or GPL
32 | * Version 2] license." If you don't indicate a single choice of license, a
33 | * recipient has the option to distribute your version of this file under
34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to
35 | * its licensees as provided above. However, if you add GPL Version 2 code
36 | * and therefore, elected the GPL Version 2 license, then the option applies
37 | * only if the new code is made subject to such option by the copyright
38 | * holder.
39 | */
40 | package org.eclipse.microprofile12.config.converter;
41 |
42 | import java.io.IOException;
43 |
44 | import javax.inject.Inject;
45 | import javax.servlet.ServletException;
46 | import javax.servlet.annotation.WebServlet;
47 | import javax.servlet.http.HttpServlet;
48 | import javax.servlet.http.HttpServletRequest;
49 | import javax.servlet.http.HttpServletResponse;
50 |
51 | import org.eclipse.microprofile.config.inject.ConfigProperty;
52 |
53 | @WebServlet("/servlet")
54 | public class Servlet extends HttpServlet {
55 |
56 | private static final long serialVersionUID = 1L;
57 |
58 | /*
59 | * Example of injecting a value of an arbitrary type using a custom converter. TestPojo types are
60 | * converted using CustomConverter,java, which is registered via a service locator file
61 | */
62 | @Inject
63 | @ConfigProperty(name = "pojo.value")
64 | private TestPojo pojo;
65 |
66 | @Override
67 | public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
68 | response.setContentType("text/plain");
69 | response.getWriter().write("pojo.value : " + pojo);
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/config/converter/src/main/java/org/eclipse/microprofile12/config/converter/TestPojo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 | *
4 | * Copyright (c) 2017-2018 Payara Foundation and/or its affiliates. All rights reserved.
5 | *
6 | * The contents of this file are subject to the terms of either the GNU
7 | * General Public License Version 2 only ("GPL") or the Common Development
8 | * and Distribution License("CDDL") (collectively, the "License"). You
9 | * may not use this file except in compliance with the License. You can
10 | * obtain a copy of the License at
11 | * https://github.com/payara/Payara/blob/master/LICENSE.txt
12 | * See the License for the specific
13 | * language governing permissions and limitations under the License.
14 | *
15 | * When distributing the software, include this License Header Notice in each
16 | * file and include the License file at glassfish/legal/LICENSE.txt.
17 | *
18 | * GPL Classpath Exception:
19 | * The Payara Foundation designates this particular file as subject to the "Classpath"
20 | * exception as provided by the Payara Foundation in the GPL Version 2 section of the License
21 | * file that accompanied this code.
22 | *
23 | * Modifications:
24 | * If applicable, add the following below the License Header, with the fields
25 | * enclosed by brackets [] replaced by your own identifying information:
26 | * "Portions Copyright [year] [name of copyright owner]"
27 | *
28 | * Contributor(s):
29 | * If you wish your version of this file to be governed by only the CDDL or
30 | * only the GPL Version 2, indicate your decision by adding "[Contributor]
31 | * elects to include this software in this distribution under the [CDDL or GPL
32 | * Version 2] license." If you don't indicate a single choice of license, a
33 | * recipient has the option to distribute your version of this file under
34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to
35 | * its licensees as provided above. However, if you add GPL Version 2 code
36 | * and therefore, elected the GPL Version 2 license, then the option applies
37 | * only if the new code is made subject to such option by the copyright
38 | * holder.
39 | */
40 | package org.eclipse.microprofile12.config.converter;
41 |
42 | /**
43 | *
44 | * @author Steve Millidge (Payara Foundation)
45 | */
46 | public class TestPojo {
47 |
48 | public String value;
49 |
50 | @Override
51 | public String toString() {
52 | return "TestPojo{" + "value=" + value + '}';
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/config/converter/src/main/resources/META-INF/microprofile-config.properties:
--------------------------------------------------------------------------------
1 | # Example application properties file
2 | pojo.value=Value for Test Pojo
3 |
--------------------------------------------------------------------------------
/config/converter/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter:
--------------------------------------------------------------------------------
1 | org.eclipse.microprofile12.config.converter.CustomConverter
2 |
--------------------------------------------------------------------------------
/config/converter/src/test/java/org/eclipse/microprofile12/config/converter/ConverterTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.config.converter;
2 |
3 | import static javax.ws.rs.client.ClientBuilder.newClient;
4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
5 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
6 | import static org.junit.Assert.assertTrue;
7 |
8 | import java.io.IOException;
9 | import java.net.URI;
10 | import java.net.URL;
11 |
12 | import org.jboss.arquillian.container.test.api.Deployment;
13 | import org.jboss.arquillian.container.test.api.RunAsClient;
14 | import org.jboss.arquillian.junit.Arquillian;
15 | import org.jboss.arquillian.test.api.ArquillianResource;
16 | import org.jboss.shrinkwrap.api.spec.WebArchive;
17 | import org.junit.Test;
18 | import org.junit.runner.RunWith;
19 |
20 | /**
21 | * @author Arjan Tijms
22 | */
23 | @RunWith(Arquillian.class)
24 | public class ConverterTest {
25 |
26 | @ArquillianResource
27 | private URL base;
28 |
29 | @Deployment(testable = false)
30 | public static WebArchive createDeployment() {
31 | WebArchive archive =
32 | create(WebArchive.class)
33 | .addClasses(
34 | ApplicationInit.class,
35 | CustomConverter.class,
36 | Servlet.class,
37 | TestPojo.class
38 | ).addAsResource(
39 | "META-INF/services/org.eclipse.microprofile.config.spi.Converter"
40 | ).addAsResource(
41 | "META-INF/microprofile-config.properties"
42 | )
43 | ;
44 |
45 | System.out.println("************************************************************");
46 | System.out.println(archive.toString(true));
47 | System.out.println("************************************************************");
48 |
49 | return archive;
50 | }
51 |
52 | @Test
53 | @RunAsClient
54 | public void testConverter() throws IOException {
55 |
56 | String response =
57 | newClient()
58 | .target(
59 | URI.create(new URL(base, "servlet").toExternalForm()))
60 | .request(TEXT_PLAIN)
61 | .get(String.class);
62 |
63 | System.out.println("-------------------------------------------------------------------------");
64 | System.out.println("Response: " + response);
65 | System.out.println("-------------------------------------------------------------------------");
66 |
67 | assertTrue(
68 | response.contains("pojo.value : TestPojo{value=Value for Test Pojo}")
69 | );
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/config/default-conversion/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | org.eclipse.microprofile.samples12
6 | config
7 | 1.0-SNAPSHOT
8 |
9 |
10 | default-conversion
11 | war
12 | MicroProfile 1.2: Config - Default Conversion
13 |
14 |
15 |
--------------------------------------------------------------------------------
/config/default-conversion/src/main/java/org/eclipse/microprofile12/config/defaultconversion/ApplicationInit.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.config.defaultconversion;
2 |
3 | import javax.enterprise.context.ApplicationScoped;
4 |
5 | @ApplicationScoped
6 | public class ApplicationInit {
7 |
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/config/default-conversion/src/main/java/org/eclipse/microprofile12/config/defaultconversion/Servlet.java:
--------------------------------------------------------------------------------
1 | /*
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 | *
4 | * Copyright (c) 2017-2018 Payara Foundation and/or its affiliates. All rights reserved.
5 | *
6 | * The contents of this file are subject to the terms of either the GNU
7 | * General Public License Version 2 only ("GPL") or the Common Development
8 | * and Distribution License("CDDL") (collectively, the "License"). You
9 | * may not use this file except in compliance with the License. You can
10 | * obtain a copy of the License at
11 | * https://github.com/payara/Payara/blob/master/LICENSE.txt
12 | * See the License for the specific
13 | * language governing permissions and limitations under the License.
14 | *
15 | * When distributing the software, include this License Header Notice in each
16 | * file and include the License file at glassfish/legal/LICENSE.txt.
17 | *
18 | * GPL Classpath Exception:
19 | * The Payara Foundation designates this particular file as subject to the "Classpath"
20 | * exception as provided by the Payara Foundation in the GPL Version 2 section of the License
21 | * file that accompanied this code.
22 | *
23 | * Modifications:
24 | * If applicable, add the following below the License Header, with the fields
25 | * enclosed by brackets [] replaced by your own identifying information:
26 | * "Portions Copyright [year] [name of copyright owner]"
27 | *
28 | * Contributor(s):
29 | * If you wish your version of this file to be governed by only the CDDL or
30 | * only the GPL Version 2, indicate your decision by adding "[Contributor]
31 | * elects to include this software in this distribution under the [CDDL or GPL
32 | * Version 2] license." If you don't indicate a single choice of license, a
33 | * recipient has the option to distribute your version of this file under
34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to
35 | * its licensees as provided above. However, if you add GPL Version 2 code
36 | * and therefore, elected the GPL Version 2 license, then the option applies
37 | * only if the new code is made subject to such option by the copyright
38 | * holder.
39 | */
40 | package org.eclipse.microprofile12.config.defaultconversion;
41 |
42 | import java.io.IOException;
43 | import java.time.LocalDate;
44 |
45 | import javax.inject.Inject;
46 | import javax.servlet.ServletException;
47 | import javax.servlet.annotation.WebServlet;
48 | import javax.servlet.http.HttpServlet;
49 | import javax.servlet.http.HttpServletRequest;
50 | import javax.servlet.http.HttpServletResponse;
51 |
52 | import org.eclipse.microprofile.config.inject.ConfigProperty;
53 |
54 | @WebServlet("/servlet")
55 | public class Servlet extends HttpServlet {
56 |
57 | private static final long serialVersionUID = 1L;
58 |
59 | // Example config property that uses a default converter to LocalDate
60 | @Inject
61 | @ConfigProperty(name = "date.property")
62 | private LocalDate date;
63 |
64 | @Override
65 | public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
66 | response.setContentType("text/plain");
67 | response.getWriter().write("date.property : " + date + "\n");
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/config/default-conversion/src/main/resources/META-INF/microprofile-config.properties:
--------------------------------------------------------------------------------
1 | # Example application properties file
2 | date.property=2000-01-01
3 |
--------------------------------------------------------------------------------
/config/default-conversion/src/test/java/org/eclipse/microprofile12/config/defaultconversion/DefaultConversionTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.config.defaultconversion;
2 |
3 | import static javax.ws.rs.client.ClientBuilder.newClient;
4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
5 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
6 | import static org.junit.Assert.assertTrue;
7 |
8 | import java.io.IOException;
9 | import java.net.URI;
10 | import java.net.URL;
11 |
12 | import org.eclipse.microprofile12.config.defaultconversion.ApplicationInit;
13 | import org.eclipse.microprofile12.config.defaultconversion.Servlet;
14 | import org.jboss.arquillian.container.test.api.Deployment;
15 | import org.jboss.arquillian.container.test.api.RunAsClient;
16 | import org.jboss.arquillian.junit.Arquillian;
17 | import org.jboss.arquillian.test.api.ArquillianResource;
18 | import org.jboss.shrinkwrap.api.spec.WebArchive;
19 | import org.junit.Test;
20 | import org.junit.runner.RunWith;
21 |
22 | /**
23 | * @author Arjan Tijms
24 | */
25 | @RunWith(Arquillian.class)
26 | public class DefaultConversionTest {
27 |
28 | @ArquillianResource
29 | private URL base;
30 |
31 | @Deployment(testable = false)
32 | public static WebArchive createDeployment() {
33 | WebArchive archive =
34 | create(WebArchive.class)
35 | .addClasses(
36 | ApplicationInit.class,
37 | Servlet.class
38 | ).addAsResource(
39 | "META-INF/microprofile-config.properties"
40 | )
41 | ;
42 |
43 | System.out.println("************************************************************");
44 | System.out.println(archive.toString(true));
45 | System.out.println("************************************************************");
46 |
47 | return archive;
48 | }
49 |
50 | @Test
51 | @RunAsClient
52 | public void testDefaultConversion() throws IOException {
53 |
54 | String response =
55 | newClient()
56 | .target(
57 | URI.create(new URL(base, "servlet").toExternalForm()))
58 | .request(TEXT_PLAIN)
59 | .get(String.class);
60 |
61 | System.out.println("-------------------------------------------------------------------------");
62 | System.out.println("Response: " + response);
63 | System.out.println("-------------------------------------------------------------------------");
64 |
65 | assertTrue(
66 | response.contains("date.property : 2000-01-01")
67 | );
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/config/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | org.eclipse.microprofile.samples12
6 | samples-parent
7 | 1.0-SNAPSHOT
8 |
9 |
10 | config
11 | pom
12 |
13 | MicroProfile 1.2: Config
14 |
15 |
16 | basic-injection
17 | config-source
18 | converter
19 | default-conversion
20 |
21 |
22 |
23 |
24 | org.eclipse.microprofile.samples12
25 | test-utils
26 | ${project.version}
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/fault-tolerance/README.md:
--------------------------------------------------------------------------------
1 | # Eclipse MicroProfile 1.2 Samples - Fault Tolerance
2 |
3 | - [Wiki project page](https://wiki.eclipse.org/MicroProfile/Fault_Tolerance)
4 | - [Spec, API, TCK GitHub repo](https://github.com/eclipse/microprofile-fault-tolerance)
5 |
6 | ## Samples ##
7 |
8 | - **asynchronous** Demonstrates a CDI version of the EJB @Asynchronous annotation
9 | - **bulkhead**
10 | - **fallback**
11 | - **retry**
12 | - **timeout**
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/fault-tolerance/asynchronous/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | org.eclipse.microprofile.samples12
6 | fault-tolerance
7 | 1.0-SNAPSHOT
8 |
9 |
10 | asynchronous
11 | war
12 | MicroProfile 1.2: Fault Tolerance - Asynchronous
13 |
14 |
15 |
--------------------------------------------------------------------------------
/fault-tolerance/asynchronous/src/main/java/org/eclipse/microprofile12/faulttolerance/asynchronous/MyAsyncBeanClassLevel.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.faulttolerance.asynchronous;
2 |
3 | import static java.lang.Thread.sleep;
4 | import static java.util.concurrent.CompletableFuture.completedFuture;
5 |
6 | import java.util.concurrent.Future;
7 | import java.util.logging.Level;
8 | import java.util.logging.Logger;
9 |
10 | import javax.enterprise.context.ApplicationScoped;
11 |
12 | import org.eclipse.microprofile.faulttolerance.Asynchronous;
13 |
14 | /**
15 | * @author Arun Gupta
16 | * @author Arjan Tijms
17 | */
18 | @Asynchronous
19 | @ApplicationScoped
20 | public class MyAsyncBeanClassLevel {
21 |
22 | public static final long AWAIT = 3000;
23 |
24 | public Future addNumbers(int n1, int n2) {
25 | try {
26 | // simulating a long running query
27 | sleep(AWAIT);
28 | } catch (InterruptedException ex) {
29 | Logger.getLogger(MyAsyncBeanClassLevel.class.getName()).log(Level.SEVERE, null, ex);
30 | }
31 |
32 | return completedFuture(n1 + n2);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/fault-tolerance/asynchronous/src/main/java/org/eclipse/microprofile12/faulttolerance/asynchronous/MyAsyncBeanMethodLevel.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.faulttolerance.asynchronous;
2 |
3 | import static java.lang.Thread.sleep;
4 | import static java.util.concurrent.CompletableFuture.completedFuture;
5 | import static java.util.logging.Level.SEVERE;
6 |
7 | import java.util.concurrent.Future;
8 | import java.util.logging.Logger;
9 |
10 | import javax.enterprise.context.ApplicationScoped;
11 |
12 | import org.eclipse.microprofile.faulttolerance.Asynchronous;
13 |
14 | /**
15 | * @author Arun Gupta
16 | * @author Arjan Tijms
17 | */
18 | @ApplicationScoped
19 | public class MyAsyncBeanMethodLevel {
20 |
21 | public static final long AWAIT = 3000;
22 |
23 | @Asynchronous
24 | public Future addNumbers(int n1, int n2) {
25 | try {
26 | // Simulating a long running query
27 | sleep(AWAIT);
28 | } catch (InterruptedException ex) {
29 | Logger.getLogger(MyAsyncBeanMethodLevel.class.getName()).log(SEVERE, null, ex);
30 | }
31 |
32 | return completedFuture(n1 + n2);
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/fault-tolerance/asynchronous/src/main/resources/project-defaults.yml:
--------------------------------------------------------------------------------
1 | swarm:
2 | hystrix:
3 | command:
4 | default:
5 | execution:
6 | isolation:
7 | thread:
8 | timeoutInMilliseconds: 3500 #MORE THAN MyAsyncBean*Level.AWAIT CONFIGURED IN TESTS
9 |
--------------------------------------------------------------------------------
/fault-tolerance/asynchronous/src/test/java/org/eclipse/microprofile12/faulttolerance/asynchronous/AsyncClassBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.faulttolerance.asynchronous;
2 |
3 | import static com.jayway.awaitility.Awaitility.await;
4 | import static java.lang.System.currentTimeMillis;
5 | import static org.eclipse.microprofile12.Libraries.awaitability;
6 | import static org.hamcrest.MatcherAssert.assertThat;
7 | import static org.hamcrest.Matchers.equalTo;
8 | import static org.hamcrest.Matchers.is;
9 | import static org.hamcrest.Matchers.lessThan;
10 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
11 |
12 | import java.util.concurrent.ExecutionException;
13 | import java.util.concurrent.Future;
14 |
15 | import javax.inject.Inject;
16 |
17 | import org.jboss.arquillian.container.test.api.Deployment;
18 | import org.jboss.arquillian.junit.Arquillian;
19 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
20 | import org.jboss.shrinkwrap.api.spec.WebArchive;
21 | import org.junit.Test;
22 | import org.junit.runner.RunWith;
23 |
24 | /**
25 | * @author Jakub Marchwicki
26 | * @author Arjan Tijms
27 | */
28 | @RunWith(Arquillian.class)
29 | public class AsyncClassBeanTest {
30 |
31 | @Inject
32 | private MyAsyncBeanClassLevel bean;
33 |
34 | @Deployment
35 | public static WebArchive createDeployment() {
36 | return create(WebArchive.class)
37 | .addAsLibraries(awaitability())
38 | .addClasses(MyAsyncBeanClassLevel.class)
39 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
40 | .addAsResource("project-defaults.yml");
41 | }
42 |
43 | @Test
44 | public void shouldReturnAsyncSum() throws ExecutionException, InterruptedException {
45 | Integer numberOne = 5;
46 | Integer numberTwo = 10;
47 |
48 | long start = currentTimeMillis();
49 | Future resultFuture = bean.addNumbers(numberOne, numberTwo);
50 |
51 | assertThat(resultFuture.isDone(), is(equalTo(false)));
52 | assertThat(currentTimeMillis() - start, is(lessThan(MyAsyncBeanMethodLevel.AWAIT)));
53 |
54 | await().until(() -> resultFuture.isDone());
55 |
56 | assertThat(resultFuture.get(), is(equalTo(numberOne + numberTwo)));
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/fault-tolerance/asynchronous/src/test/java/org/eclipse/microprofile12/faulttolerance/asynchronous/AsyncMethodBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.faulttolerance.asynchronous;
2 |
3 | import static com.jayway.awaitility.Awaitility.await;
4 | import static java.lang.System.currentTimeMillis;
5 | import static org.eclipse.microprofile12.Libraries.awaitability;
6 | import static org.hamcrest.MatcherAssert.assertThat;
7 | import static org.hamcrest.Matchers.equalTo;
8 | import static org.hamcrest.Matchers.is;
9 | import static org.hamcrest.Matchers.lessThan;
10 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
11 |
12 | import java.util.concurrent.ExecutionException;
13 | import java.util.concurrent.Future;
14 |
15 | import javax.inject.Inject;
16 |
17 | import org.jboss.arquillian.container.test.api.Deployment;
18 | import org.jboss.arquillian.junit.Arquillian;
19 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
20 | import org.jboss.shrinkwrap.api.spec.WebArchive;
21 | import org.junit.Test;
22 | import org.junit.runner.RunWith;
23 |
24 | /**
25 | * @author Jakub Marchwicki
26 | * @author Arjan Tijms
27 | */
28 | @RunWith(Arquillian.class)
29 | public class AsyncMethodBeanTest {
30 |
31 | @Inject
32 | private MyAsyncBeanMethodLevel bean;
33 |
34 | @Deployment
35 | public static WebArchive createDeployment() {
36 | return create(WebArchive.class)
37 | .addAsLibraries(awaitability())
38 | .addClasses(MyAsyncBeanMethodLevel.class)
39 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
40 | .addAsResource("project-defaults.yml");
41 | }
42 |
43 | @Test // Runs on Server
44 | public void shouldReturnAsyncSum() throws ExecutionException, InterruptedException {
45 | Integer numberOne = 5;
46 | Integer numberTwo = 10;
47 |
48 | long start = currentTimeMillis();
49 | Future resultFuture = bean.addNumbers(numberOne, numberTwo);
50 |
51 | assertThat(resultFuture.isDone(), is(equalTo(false)));
52 | assertThat(currentTimeMillis() - start, is(lessThan(MyAsyncBeanMethodLevel.AWAIT)));
53 |
54 | await().until(() -> resultFuture.isDone());
55 |
56 | assertThat(resultFuture.get(), is(equalTo(numberOne + numberTwo)));
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/fault-tolerance/bulkhead/micro-pre-boot-commands.txt:
--------------------------------------------------------------------------------
1 | set resources.managed-executor-service.concurrent/__defaultManagedExecutorService.core-pool-size=0
2 | set resources.managed-executor-service.concurrent/__defaultManagedExecutorService.hung-after-seconds=0
3 | set resources.managed-executor-service.concurrent/__defaultManagedExecutorService.keep-alive-seconds=60
4 | set resources.managed-executor-service.concurrent/__defaultManagedExecutorService.long-running-tasks=false
5 | set resources.managed-executor-service.concurrent/__defaultManagedExecutorService.task-queue-capacity=2147483647
6 | set resources.managed-executor-service.concurrent/__defaultManagedExecutorService.maximum-pool-size=2147483647
7 | set resources.managed-scheduled-executor-service.concurrent/__defaultManagedScheduledExecutorService.core-pool-size=0
8 | set resources.managed-scheduled-executor-service.concurrent/__defaultManagedScheduledExecutorService.long-running-tasks=false
9 | set resources.managed-scheduled-executor-service.concurrent/__defaultManagedScheduledExecutorService.keep-alive-seconds=60
10 | set resources.managed-scheduled-executor-service.concurrent/__defaultManagedScheduledExecutorService.hung-after-seconds=0
11 |
12 |
--------------------------------------------------------------------------------
/fault-tolerance/bulkhead/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.eclipse.microprofile.samples12
6 | fault-tolerance
7 | 1.0-SNAPSHOT
8 |
9 |
10 | bulkhead
11 | war
12 |
13 | MicroProfile 1.2: Fault Tolerance - Bulkhead
14 |
15 |
16 |
17 |
18 | org.apache.maven.plugins
19 | maven-surefire-plugin
20 |
21 |
22 | --prebootcommandfile ${basedir}/micro-pre-boot-commands.txt
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/fault-tolerance/bulkhead/src/main/java/org/eclipse/microprofile/samples12/bulkhead/AsynchronousBulkheadBean.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.bulkhead;
2 |
3 | import java.util.concurrent.CompletableFuture;
4 | import java.util.concurrent.Future;
5 | import java.util.logging.Level;
6 | import java.util.logging.Logger;
7 | import javax.enterprise.context.ApplicationScoped;
8 | import org.eclipse.microprofile.faulttolerance.Asynchronous;
9 | import org.eclipse.microprofile.faulttolerance.Bulkhead;
10 |
11 | /**
12 | * A Bean with both a Bulkhead and Asynchronous annotation applied. This combination means that the Bulkhead will allow
13 | * a specified number of tasks to queue for execution.
14 | * @author Andrew Pielage
15 | */
16 | @Asynchronous
17 | @Bulkhead(value = 3, waitingTaskQueue = 5)
18 | @ApplicationScoped
19 | public class AsynchronousBulkheadBean {
20 |
21 | public static final long AWAIT = 3000;
22 |
23 | /**
24 | * Example method that simulates a long running task.
25 | * @return
26 | */
27 | public Future method1() {
28 | try {
29 | // Simulate a long running query
30 | Thread.sleep(AWAIT);
31 | } catch (InterruptedException ex) {
32 | Logger.getLogger(AsynchronousBulkheadBean.class.getName()).log(Level.SEVERE, null, ex);
33 | }
34 |
35 | return CompletableFuture.completedFuture("Wibbles");
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/fault-tolerance/bulkhead/src/main/java/org/eclipse/microprofile/samples12/bulkhead/ClassLevelBulkheadBean.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.bulkhead;
2 |
3 | import java.util.logging.Level;
4 | import java.util.logging.Logger;
5 | import javax.enterprise.context.ApplicationScoped;
6 | import org.eclipse.microprofile.faulttolerance.Bulkhead;
7 |
8 | /**
9 | * A Bean with a Bulkhead applied at the class level with default values. The Bulkhead will be applied to
10 | * every method in this class, only allowing 10 threads to access them (individually - they do not share
11 | * bulkhead tokens) concurrently, with no queueing allowed.
12 | * @author Andrew Pielage
13 | */
14 | @Bulkhead
15 | @ApplicationScoped
16 | public class ClassLevelBulkheadBean {
17 |
18 | public static final long AWAIT = 3000;
19 |
20 | /**
21 | * Example method that simulates a long running query
22 | */
23 | public void method1() {
24 | try {
25 | // Simulate a long running query
26 | Thread.sleep(AWAIT);
27 | } catch (InterruptedException ex) {
28 | Logger.getLogger(ClassLevelBulkheadBean.class.getName()).log(Level.SEVERE, null, ex);
29 | }
30 | }
31 |
32 | /**
33 | * Example method that simulates a long running query
34 | */
35 | public void method2() {
36 | try {
37 | // Simulate a long running query
38 | Thread.sleep(AWAIT);
39 | } catch (InterruptedException ex) {
40 | Logger.getLogger(ClassLevelBulkheadBean.class.getName()).log(Level.SEVERE, null, ex);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/fault-tolerance/bulkhead/src/main/java/org/eclipse/microprofile/samples12/bulkhead/MethodLevelBulkheadBean.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.bulkhead;
2 |
3 | import java.util.logging.Level;
4 | import java.util.logging.Logger;
5 | import javax.enterprise.context.ApplicationScoped;
6 | import org.eclipse.microprofile.faulttolerance.Bulkhead;
7 |
8 | /**
9 | * A Bean with a Bulkhead applied at the method level, demonstrating how you can specify different bulkhead values for
10 | * each method.
11 | * @author Andrew Pielage
12 | */
13 | @ApplicationScoped
14 | public class MethodLevelBulkheadBean {
15 |
16 | public static final long AWAIT = 3000;
17 |
18 | /**
19 | * Example method that simulates a long running query
20 | */
21 | @Bulkhead(5)
22 | public void method1() {
23 | try {
24 | // Simulate a long running query
25 | Thread.sleep(AWAIT);
26 | } catch (InterruptedException ex) {
27 | Logger.getLogger(ClassLevelBulkheadBean.class.getName()).log(Level.SEVERE, null, ex);
28 | }
29 | }
30 |
31 | /**
32 | * Example method that simulates a long running query with its own bulkhead.
33 | */
34 | @Bulkhead(3)
35 | public void method2() {
36 | try {
37 | // Simulate a long running query
38 | Thread.sleep(AWAIT);
39 | } catch (InterruptedException ex) {
40 | Logger.getLogger(ClassLevelBulkheadBean.class.getName()).log(Level.SEVERE, null, ex);
41 | }
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/fault-tolerance/bulkhead/src/main/resources/project-defaults.yml:
--------------------------------------------------------------------------------
1 | swarm:
2 | hystrix:
3 | threadpool:
4 | default:
5 | maximumSize: 10 #SHOULD BE >= AsynchronousBulkheadBean @Bulkead value + @Bulkhead waitingTaskQueue
6 | allowMaximumSizeToDivergeFromCoreSize: true
7 | command:
8 | default:
9 | execution:
10 | isolation:
11 | thread:
12 | timeoutInMilliseconds: 21500 #MORE THAN (AsynchronousBulkheadBean @Bulkead value + @Bulkhead waitingTaskQueue -1) * AsynchronousBulkheadBean.AWAIT
13 |
--------------------------------------------------------------------------------
/fault-tolerance/bulkhead/src/test/java/org/eclipse/microprofile12/faulttolerance/bulkhead/AsynchronousBulkheadBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.faulttolerance.bulkhead;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.concurrent.ExecutionException;
6 | import java.util.concurrent.Future;
7 | import java.util.logging.Level;
8 | import java.util.logging.Logger;
9 | import javax.inject.Inject;
10 | import org.eclipse.microprofile.faulttolerance.Bulkhead;
11 | import org.eclipse.microprofile.faulttolerance.exceptions.BulkheadException;
12 | import org.eclipse.microprofile.samples12.bulkhead.AsynchronousBulkheadBean;
13 | import org.jboss.arquillian.container.test.api.Deployment;
14 | import org.jboss.arquillian.junit.Arquillian;
15 | import org.jboss.shrinkwrap.api.ShrinkWrap;
16 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
17 | import org.jboss.shrinkwrap.api.spec.WebArchive;
18 | import org.junit.Assert;
19 | import org.junit.Test;
20 | import org.junit.runner.RunWith;
21 |
22 | /**
23 | * Test class for the AsynchronousBulkheadBean class.
24 | * @author Andrew Pielage
25 | */
26 | @RunWith(Arquillian.class)
27 | public class AsynchronousBulkheadBeanTest {
28 |
29 | @Inject
30 | AsynchronousBulkheadBean asynchronousBulkheadBean;
31 |
32 | @Deployment
33 | public static WebArchive createDeployment() {
34 | return ShrinkWrap.create(WebArchive.class)
35 | .addClasses(AsynchronousBulkheadBean.class)
36 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
37 | .addAsResource("project-defaults.yml");
38 | }
39 |
40 | /**
41 | * Test that the bulkhead begins queueing task if more than the maximum number of threads are executing concurrently.
42 | * @throws NoSuchMethodException
43 | */
44 | @Test
45 | public void bulkheadQueueTest() throws NoSuchMethodException {
46 | int numberOfExpectedFailures = 0;
47 |
48 | // Kick off more tasks than the bulkhead value, but less than the combined total, causing the bulkhead to block
49 | // and start queuing
50 | int numberOfTasks = AsynchronousBulkheadBean.class.getAnnotation(Bulkhead.class).value()
51 | + AsynchronousBulkheadBean.class.getAnnotation(Bulkhead.class).waitingTaskQueue()
52 | - 1;
53 |
54 | List> futures = new ArrayList<>();
55 | for (int i = 0; i < numberOfTasks; i++) {
56 | futures.add(asynchronousBulkheadBean.method1());
57 | }
58 |
59 | // Await and collect results to make sure everything has completed or thrown an exception
60 | int failures = 0;
61 | for (Future future : futures) {
62 | try {
63 | future.get();
64 | } catch (InterruptedException ie) {
65 | Logger.getLogger(AsynchronousBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ie);
66 | Assert.fail("Got an unexpected InterruptedException");
67 | } catch (ExecutionException ex) {
68 | Logger.getLogger(AsynchronousBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ex);
69 | Assert.fail("Got an unexpected ExecutionException");
70 | } catch (BulkheadException be) {
71 | failures ++;
72 | }
73 | }
74 |
75 | // numberOfExpectedFailures tasks should fail
76 | Assert.assertTrue("Did not get " + numberOfExpectedFailures + ": " + failures,
77 | failures == numberOfExpectedFailures);
78 | }
79 |
80 | /**
81 | * Test that when the bulkhead queue is full, errors start to get thrown.
82 | * @throws NoSuchMethodException
83 | */
84 | @Test
85 | public void bulkheadLimitTest() throws NoSuchMethodException {
86 | int numberOfExpectedFailures = 2;
87 |
88 | // Kick off more tasks than the bulkhead value and queue combined, causing the bulkhead to block
89 | // and start queuing, before throwing an exception
90 | int numberOfTasks = AsynchronousBulkheadBean.class.getAnnotation(Bulkhead.class).value()
91 | + AsynchronousBulkheadBean.class.getAnnotation(Bulkhead.class).waitingTaskQueue()
92 | + numberOfExpectedFailures;
93 |
94 | List> futures = new ArrayList<>();
95 | for (int i = 0; i < numberOfTasks; i++) {
96 | futures.add(asynchronousBulkheadBean.method1());
97 | }
98 |
99 | // Await and collect results to make sure everything has completed or thrown an exception
100 | int failures = 0;
101 | for (Future future : futures) {
102 | try {
103 | future.get();
104 | } catch (InterruptedException ie) {
105 | Logger.getLogger(AsynchronousBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ie);
106 | Assert.fail("Got an unexpected InterruptedException");
107 | } catch (ExecutionException ex) {
108 | if (ex.getCause() instanceof BulkheadException) {
109 | failures ++;
110 | } else {
111 | Logger.getLogger(AsynchronousBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ex);
112 | Assert.fail("Got an unexpected ExecutionException");
113 | }
114 | } catch (BulkheadException be) {
115 | failures ++;
116 | }
117 | }
118 |
119 | // numberOfExpectedFailures tasks should fail
120 | Assert.assertTrue("Did not get " + numberOfExpectedFailures + ": " + failures,
121 | failures == numberOfExpectedFailures);
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/fault-tolerance/bulkhead/src/test/java/org/eclipse/microprofile12/faulttolerance/bulkhead/ClassLevelBulkheadBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.faulttolerance.bulkhead;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.concurrent.Callable;
6 | import java.util.concurrent.ExecutionException;
7 | import java.util.concurrent.ExecutorService;
8 | import java.util.concurrent.Executors;
9 | import java.util.concurrent.Future;
10 | import java.util.logging.Level;
11 | import java.util.logging.Logger;
12 | import javax.inject.Inject;
13 | import org.eclipse.microprofile.faulttolerance.Bulkhead;
14 | import org.eclipse.microprofile.faulttolerance.exceptions.BulkheadException;
15 | import org.eclipse.microprofile.samples12.bulkhead.ClassLevelBulkheadBean;
16 | import org.jboss.arquillian.container.test.api.Deployment;
17 | import org.jboss.arquillian.junit.Arquillian;
18 | import org.jboss.shrinkwrap.api.ShrinkWrap;
19 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
20 | import org.jboss.shrinkwrap.api.spec.WebArchive;
21 | import org.junit.Assert;
22 | import org.junit.Test;
23 | import org.junit.runner.RunWith;
24 |
25 | /**
26 | * Test class for the ClassLevelBulkheadBean class.
27 | * @author Andrew Pielage
28 | */
29 | @RunWith(Arquillian.class)
30 | public class ClassLevelBulkheadBeanTest {
31 |
32 | @Inject
33 | private ClassLevelBulkheadBean classLevelBulkheadBean;
34 |
35 | @Deployment
36 | public static WebArchive createDeployment() {
37 | return ShrinkWrap.create(WebArchive.class)
38 | .addClasses(ClassLevelBulkheadBean.class)
39 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
40 | }
41 |
42 | /**
43 | * Test that the bulkhead prevents more than the configured number of threads to execute on the method concurrently.
44 | * @throws NoSuchMethodException
45 | */
46 | @Test
47 | public void bulkheadLimitTest() throws NoSuchMethodException {
48 | int numberOfExpectedFailures = 2;
49 |
50 | // Kick off more tasks than the bulkhead value, causing the bulkhead to block
51 | int numberOfTasks = ClassLevelBulkheadBean.class.getAnnotation(Bulkhead.class).value()
52 | + numberOfExpectedFailures;
53 | List> method1Futures = executeMethod1Asynchronously(numberOfTasks);
54 |
55 | // Await and collect results to make sure everything has completed or thrown an exception
56 | int failures = 0;
57 | for (Future future : method1Futures) {
58 | try {
59 | future.get();
60 | } catch (InterruptedException ie) {
61 | Logger.getLogger(ClassLevelBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ie);
62 | Assert.fail("Got an unexpected InterruptedException");
63 | } catch (ExecutionException ex) {
64 | if (ex.getCause() instanceof BulkheadException) {
65 | failures ++;
66 | } else {
67 | Logger.getLogger(ClassLevelBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ex);
68 | Assert.fail("Got an unexpected ExecutionException");
69 | }
70 | }
71 | }
72 |
73 | // numberOfExpectedFailures tasks should fail
74 | Assert.assertTrue("Did not get " + numberOfExpectedFailures + ": " + failures,
75 | failures == numberOfExpectedFailures);
76 | }
77 |
78 | /**
79 | * Test that the two methods do not share bulkhead tokens, even though the share the same class level annotation.
80 | * @throws NoSuchMethodException
81 | */
82 | @Test
83 | public void methodsDoNotShareClassLevelBulkheadPermitsTest() throws NoSuchMethodException {
84 | int numberOfExpectedFailures = 2;
85 |
86 | // Kick off more tasks than the bulkhead value for both methods simultaneously, causing the bulkhead to block
87 | int numberOfTasks = ClassLevelBulkheadBean.class.getAnnotation(Bulkhead.class).value()
88 | + numberOfExpectedFailures;
89 | List> method1Futures = executeMethod1Asynchronously(numberOfTasks);
90 | List> method2Futures = executeMethod2Asynchronously(numberOfTasks);
91 |
92 | // Await and collect results to make sure everything has completed or thrown an exception
93 | int failures = 0;
94 | for (Future future : method1Futures) {
95 | try {
96 | future.get();
97 | } catch (InterruptedException ie) {
98 | Logger.getLogger(ClassLevelBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ie);
99 | Assert.fail("Got an unexpected InterruptedException");
100 | } catch (ExecutionException ex) {
101 | if (ex.getCause() instanceof BulkheadException) {
102 | failures ++;
103 | } else {
104 | Logger.getLogger(ClassLevelBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ex);
105 | Assert.fail("Got an unexpected ExecutionException");
106 | }
107 | }
108 | }
109 |
110 | for (Future future : method2Futures) {
111 | try {
112 | future.get();
113 | } catch (InterruptedException ie) {
114 | Logger.getLogger(ClassLevelBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ie);
115 | Assert.fail("Got an unexpected InterruptedException");
116 | } catch (ExecutionException ex) {
117 | if (ex.getCause() instanceof BulkheadException) {
118 | failures ++;
119 | } else {
120 | Logger.getLogger(ClassLevelBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ex);
121 | Assert.fail("Got an unexpected ExecutionException");
122 | }
123 | }
124 | }
125 |
126 | // Since we're doing this against two methods with separate bulkheads, they should not share bulkhead tokens,
127 | // meaning we should get numberOfExpectedFailures x 2
128 | numberOfExpectedFailures = numberOfExpectedFailures * 2;
129 | Assert.assertTrue("Did not get " + numberOfExpectedFailures + ": " + failures,
130 | failures == numberOfExpectedFailures);
131 | }
132 |
133 | /**
134 | * Helper method that kicks off a number of threads to concurrently execute the method1 method
135 | * @param iterations
136 | * @return A list of Future results
137 | */
138 | private List> executeMethod1Asynchronously(int iterations) {
139 | List> futures = new ArrayList<>();
140 |
141 | ExecutorService executorService = Executors.newFixedThreadPool(iterations);
142 |
143 | Callable task = () -> {
144 | classLevelBulkheadBean.method1();
145 | return "Wibbles";
146 | };
147 |
148 | for (int i = 0; i < iterations; i++) {
149 | futures.add(executorService.submit(task));
150 | }
151 |
152 | return futures;
153 | }
154 |
155 | /**
156 | * Helper method that kicks off a number of threads to concurrently execute the method2 method
157 | * @param iterations
158 | * @return A list of Future results
159 | */
160 | private List> executeMethod2Asynchronously(int iterations) {
161 | List> futures = new ArrayList<>();
162 |
163 | ExecutorService executorService = Executors.newFixedThreadPool(iterations);
164 |
165 | Callable task = () -> {
166 | classLevelBulkheadBean.method2();
167 | return "Wobbles";
168 | };
169 |
170 | for (int i = 0; i < iterations; i++) {
171 | futures.add(executorService.submit(task));
172 | }
173 |
174 | return futures;
175 | }
176 |
177 | }
178 |
--------------------------------------------------------------------------------
/fault-tolerance/bulkhead/src/test/java/org/eclipse/microprofile12/faulttolerance/bulkhead/MethodLevelBulkheadBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.faulttolerance.bulkhead;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.concurrent.Callable;
6 | import java.util.concurrent.ExecutionException;
7 | import java.util.concurrent.ExecutorService;
8 | import java.util.concurrent.Executors;
9 | import java.util.concurrent.Future;
10 | import java.util.logging.Level;
11 | import java.util.logging.Logger;
12 | import javax.inject.Inject;
13 | import org.eclipse.microprofile.faulttolerance.Bulkhead;
14 | import org.eclipse.microprofile.faulttolerance.exceptions.BulkheadException;
15 | import org.eclipse.microprofile.samples12.bulkhead.MethodLevelBulkheadBean;
16 | import org.jboss.arquillian.container.test.api.Deployment;
17 | import org.jboss.arquillian.junit.Arquillian;
18 | import org.jboss.shrinkwrap.api.ShrinkWrap;
19 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
20 | import org.jboss.shrinkwrap.api.spec.WebArchive;
21 | import org.junit.Assert;
22 | import org.junit.Test;
23 | import org.junit.runner.RunWith;
24 |
25 | /**
26 | * Test class for the MethodLevelBulkheadBean class.
27 | * @author Andrew Pielage
28 | */
29 | @RunWith(Arquillian.class)
30 | public class MethodLevelBulkheadBeanTest {
31 |
32 | @Inject
33 | MethodLevelBulkheadBean methodLevelBulkheadBean;
34 |
35 | @Deployment
36 | public static WebArchive createDeployment() {
37 | return ShrinkWrap.create(WebArchive.class)
38 | .addClasses(MethodLevelBulkheadBean.class)
39 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
40 | }
41 |
42 | /**
43 | * Test that the bulkhead for method1 prevents more than the configured number of tasks to execute concurrently.
44 | * @throws NoSuchMethodException
45 | */
46 | @Test
47 | public void method1BulkheadLimitTest() throws NoSuchMethodException {
48 | int numberOfExpectedFailures = 2;
49 |
50 | // Kick off more tasks than the bulkhead value, causing the bulkhead to block
51 | int numberOfTasks = MethodLevelBulkheadBean.class.getMethod("method1").getAnnotation(Bulkhead.class).value()
52 | + numberOfExpectedFailures;
53 | List> method1Futures = executeMethod1Asynchronously(numberOfTasks);
54 |
55 | // Await and collect results to make sure everything has completed or thrown an exception
56 | int failures = 0;
57 | for (Future future : method1Futures) {
58 | try {
59 | future.get();
60 | } catch (InterruptedException ie) {
61 | Logger.getLogger(MethodLevelBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ie);
62 | Assert.fail("Got an unexpected InterruptedException");
63 | } catch (ExecutionException ex) {
64 | if (ex.getCause() instanceof BulkheadException) {
65 | failures ++;
66 | } else {
67 | Logger.getLogger(MethodLevelBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ex);
68 | Assert.fail("Got an unexpected ExecutionException");
69 | }
70 | }
71 | }
72 |
73 | // numberOfExpectedFailures tasks should fail
74 | Assert.assertTrue("Did not get " + numberOfExpectedFailures + ": " + failures,
75 | failures == numberOfExpectedFailures);
76 | }
77 |
78 | /**
79 | * Test that the bulkhead for method2 prevents more than the configured number of tasks to execute concurrently.
80 | * @throws NoSuchMethodException
81 | */
82 | @Test
83 | public void method2BulkheadLimitTest() throws NoSuchMethodException {
84 | int numberOfExpectedFailures = 2;
85 |
86 | // Kick off more tasks than the bulkhead value, causing the bulkhead to block
87 | int numberOfTasks = MethodLevelBulkheadBean.class.getMethod("method2").getAnnotation(Bulkhead.class).value()
88 | + numberOfExpectedFailures;
89 | List> method2Futures = executeMethod2Asynchronously(numberOfTasks);
90 |
91 | // Await and collect results to make sure everything has completed or thrown an exception
92 | int failures = 0;
93 | for (Future future : method2Futures) {
94 | try {
95 | future.get();
96 | } catch (InterruptedException ie) {
97 | Logger.getLogger(MethodLevelBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ie);
98 | Assert.fail("Got an unexpected InterruptedException");
99 | } catch (ExecutionException ex) {
100 | if (ex.getCause() instanceof BulkheadException) {
101 | failures ++;
102 | } else {
103 | Logger.getLogger(MethodLevelBulkheadBeanTest.class.getName()).log(Level.SEVERE, null, ex);
104 | Assert.fail("Got an unexpected ExecutionException");
105 | }
106 | }
107 | }
108 |
109 | // numberOfExpectedFailures tasks should fail
110 | Assert.assertTrue("Did not get " + numberOfExpectedFailures + ": " + failures,
111 | failures == numberOfExpectedFailures);
112 | }
113 |
114 | /**
115 | * Helper method that kicks off a number of threads to concurrently executes method1.
116 | * @param iterations
117 | * @return A list of Futures.
118 | */
119 | private List> executeMethod1Asynchronously(int iterations) {
120 | List> futures = new ArrayList<>();
121 |
122 | ExecutorService executorService = Executors.newFixedThreadPool(iterations);
123 |
124 | Callable task = () -> {
125 | methodLevelBulkheadBean.method1();
126 | return "Wibbles";
127 | };
128 |
129 | for (int i = 0; i < iterations; i++) {
130 | futures.add(executorService.submit(task));
131 | }
132 |
133 | return futures;
134 | }
135 |
136 | /**
137 | * Helper method that kicks off a number of threads to concurrently executes method2.
138 | * @param iterations
139 | * @return A list of Futures.
140 | */
141 | private List> executeMethod2Asynchronously(int iterations) {
142 | List> futures = new ArrayList<>();
143 |
144 | ExecutorService executorService = Executors.newFixedThreadPool(iterations);
145 |
146 | Callable task = () -> {
147 | methodLevelBulkheadBean.method2();
148 | return "Wobbles";
149 | };
150 |
151 | for (int i = 0; i < iterations; i++) {
152 | futures.add(executorService.submit(task));
153 | }
154 |
155 | return futures;
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/fault-tolerance/circuitbreaker/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.eclipse.microprofile.samples12
6 | fault-tolerance
7 | 1.0-SNAPSHOT
8 |
9 |
10 | circuitbreaker
11 | war
12 |
13 | MicroProfile 1.2: Fault Tolerance - CircuitBreaker
14 |
15 |
16 |
--------------------------------------------------------------------------------
/fault-tolerance/circuitbreaker/src/main/java/org/eclipse/microprofile/samples12/circuitbreaker/ClassLevelCircuitBreakerBean.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.circuitbreaker;
2 |
3 | import javax.enterprise.context.ApplicationScoped;
4 | import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
5 |
6 | /**
7 | * A bean with a Circuitbreaker applied at the class level.
8 | * @author Andrew Pielage
9 | */
10 | @CircuitBreaker(requestVolumeThreshold = 4)
11 | @ApplicationScoped
12 | public class ClassLevelCircuitBreakerBean {
13 |
14 | public static final String EXPECTED_ERROR_MESSAGE = "Method failed to execute";
15 |
16 | /**
17 | * Example method that can be made to throw an exception.
18 | * @param shouldThrowException Whether an exception should be thrown or not
19 | */
20 | public void throwException(boolean shouldThrowException) {
21 | if (shouldThrowException) {
22 | throw new RuntimeException(EXPECTED_ERROR_MESSAGE);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/fault-tolerance/circuitbreaker/src/main/java/org/eclipse/microprofile/samples12/circuitbreaker/MethodLevelCircuitBreakerBean.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.circuitbreaker;
2 |
3 | import javax.enterprise.context.ApplicationScoped;
4 | import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
5 |
6 | /**
7 | * A bean with a Circuitbreaker applied at the method level.
8 | * @author Andrew Pielage
9 | */
10 | @ApplicationScoped
11 | public class MethodLevelCircuitBreakerBean {
12 | public static final String EXPECTED_ERROR_MESSAGE = "Method failed to execute";
13 |
14 | /**
15 | * Example method that can be made to throw an exception.
16 | * @param shouldThrowException
17 | */
18 | @CircuitBreaker(requestVolumeThreshold = 6)
19 | public void throwException(boolean shouldThrowException) {
20 | if (shouldThrowException) {
21 | throw new RuntimeException(EXPECTED_ERROR_MESSAGE);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/fault-tolerance/circuitbreaker/src/test/java/org/eclipse/microprofile12/faulttolerance/circuitbreaker/ClassLevelCircuitBreakerBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.faulttolerance.circuitbreaker;
2 |
3 | import java.time.Duration;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.concurrent.Callable;
7 | import java.util.concurrent.ExecutionException;
8 | import java.util.concurrent.ExecutorService;
9 | import java.util.concurrent.Executors;
10 | import java.util.concurrent.Future;
11 | import java.util.logging.Level;
12 | import java.util.logging.Logger;
13 | import javax.inject.Inject;
14 | import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
15 | import org.eclipse.microprofile.faulttolerance.exceptions.CircuitBreakerOpenException;
16 | import org.eclipse.microprofile.samples12.circuitbreaker.ClassLevelCircuitBreakerBean;
17 | import org.jboss.arquillian.container.test.api.Deployment;
18 | import org.jboss.arquillian.junit.Arquillian;
19 | import org.jboss.shrinkwrap.api.ShrinkWrap;
20 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
21 | import org.jboss.shrinkwrap.api.spec.WebArchive;
22 | import org.junit.Assert;
23 | import org.junit.Before;
24 | import org.junit.Test;
25 | import org.junit.runner.RunWith;
26 |
27 | /**
28 | * Test class for ClassLevelCircuitBreakerBean.
29 | * @author Andrew Pielage
30 | */
31 | @RunWith(Arquillian.class)
32 | public class ClassLevelCircuitBreakerBeanTest {
33 |
34 | @Inject
35 | private ClassLevelCircuitBreakerBean classLevelCircuitBreakerBean;
36 |
37 | @Deployment
38 | public static WebArchive createDeployment() {
39 | return ShrinkWrap.create(WebArchive.class)
40 | .addClasses(ClassLevelCircuitBreakerBean.class)
41 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
42 | }
43 |
44 | /**
45 | * When running against a remote profile, we need to wait for the circuitbreaker to reset between each test.
46 | * @throws NoSuchMethodException
47 | * @throws InterruptedException
48 | */
49 | @Before
50 | public void resetCircuitBreaker() throws NoSuchMethodException, InterruptedException {
51 | // Wait to half-open the circuit breaker - previous tests may have run and left it in a sorry state
52 | long addedWaitTimeMillis = 3000;
53 | long timeToWaitMillis = Duration.of(
54 | ClassLevelCircuitBreakerBean.class.getAnnotation(CircuitBreaker.class).delay(),
55 | ClassLevelCircuitBreakerBean.class.getAnnotation(CircuitBreaker.class).delayUnit()).toMillis()
56 | + addedWaitTimeMillis;
57 | Thread.sleep(timeToWaitMillis);
58 |
59 | // Fill it with goodness
60 | int numberOfTasks = ((Double) (
61 | ClassLevelCircuitBreakerBean.class.getAnnotation(CircuitBreaker.class).requestVolumeThreshold()
62 | * ClassLevelCircuitBreakerBean.class.getAnnotation(CircuitBreaker.class).failureRatio())).intValue()
63 | + ClassLevelCircuitBreakerBean.class.getAnnotation(CircuitBreaker.class).successThreshold();
64 | executeThrowExceptionMethodAsynchronously(numberOfTasks, false);
65 |
66 | }
67 |
68 | /**
69 | * Test that the Circuitbreaker opens once enough failures have been thrown.
70 | */
71 | @Test
72 | public void circuitBreakerOpensTest() {
73 | int numberOfExpectedFailures = 2;
74 |
75 | int numberOfTasks = ((Double) (
76 | ClassLevelCircuitBreakerBean.class.getAnnotation(CircuitBreaker.class).requestVolumeThreshold()
77 | * ClassLevelCircuitBreakerBean.class.getAnnotation(CircuitBreaker.class).failureRatio()))
78 | .intValue() + numberOfExpectedFailures;
79 |
80 | // Throw errors to to open the circuit
81 | List> futures = executeThrowExceptionMethodAsynchronously(numberOfTasks, true);
82 |
83 | // Await and collect results to make sure everything has completed or thrown an exception
84 | int failures = 0;
85 | for (Future future : futures) {
86 | try {
87 | future.get();
88 | } catch (InterruptedException ie) {
89 | Logger.getLogger(ClassLevelCircuitBreakerBeanTest.class.getName()).log(Level.SEVERE, null, ie);
90 | Assert.fail("Got an unexpected InterruptedException");
91 | } catch (ExecutionException ex) {
92 | if (ex.getCause() instanceof CircuitBreakerOpenException) {
93 | failures ++;
94 | } else if (ex.getCause() instanceof RuntimeException
95 | && ex.getCause().getMessage().equals(ClassLevelCircuitBreakerBean.EXPECTED_ERROR_MESSAGE)) {
96 | // Om nom nom
97 | } else {
98 | Logger.getLogger(ClassLevelCircuitBreakerBeanTest.class.getName()).log(Level.SEVERE, null, ex);
99 | Assert.fail("Got an unexpected ExecutionException");
100 | }
101 | }
102 | }
103 |
104 | // numberOfExpectedFailures tasks should fail
105 | Assert.assertTrue("Did not get " + numberOfExpectedFailures + ": " + failures,
106 | failures == numberOfExpectedFailures);
107 | }
108 |
109 | /**
110 | * Helper method that spawns a number of threads to execute against the throwException method concurrently.
111 | * @param iterations
112 | * @param shouldThrowException
113 | * @return
114 | */
115 | private List> executeThrowExceptionMethodAsynchronously(int iterations,
116 | boolean shouldThrowException) {
117 | List> futures = new ArrayList<>();
118 |
119 | ExecutorService executorService = Executors.newSingleThreadExecutor();
120 |
121 | Callable task = () -> {
122 | classLevelCircuitBreakerBean.throwException(shouldThrowException);
123 | return null;
124 | };
125 |
126 | for (int i = 0; i < iterations; i++) {
127 | futures.add(executorService.submit(task));
128 | }
129 |
130 | return futures;
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/fault-tolerance/circuitbreaker/src/test/java/org/eclipse/microprofile12/faulttolerance/circuitbreaker/MethodLevelCircuitBreakerBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.faulttolerance.circuitbreaker;
2 |
3 | import java.time.Duration;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.concurrent.Callable;
7 | import java.util.concurrent.ExecutionException;
8 | import java.util.concurrent.ExecutorService;
9 | import java.util.concurrent.Executors;
10 | import java.util.concurrent.Future;
11 | import java.util.logging.Level;
12 | import java.util.logging.Logger;
13 | import javax.inject.Inject;
14 | import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
15 | import org.eclipse.microprofile.faulttolerance.exceptions.CircuitBreakerOpenException;
16 | import org.eclipse.microprofile.samples12.circuitbreaker.MethodLevelCircuitBreakerBean;
17 | import org.jboss.arquillian.container.test.api.Deployment;
18 | import org.jboss.arquillian.junit.Arquillian;
19 | import org.jboss.shrinkwrap.api.ShrinkWrap;
20 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
21 | import org.jboss.shrinkwrap.api.spec.WebArchive;
22 | import org.junit.Assert;
23 | import org.junit.Before;
24 | import org.junit.Test;
25 | import org.junit.runner.RunWith;
26 |
27 | /**
28 | * Test class for MethodLevelCircuitBreakerBean.
29 | * @author Andrew Pielage
30 | */
31 | @RunWith(Arquillian.class)
32 | public class MethodLevelCircuitBreakerBeanTest {
33 |
34 | @Inject
35 | private MethodLevelCircuitBreakerBean methodLevelCircuitBreakerBean;
36 |
37 | @Deployment
38 | public static WebArchive createDeployment() {
39 | return ShrinkWrap.create(WebArchive.class)
40 | .addClasses(MethodLevelCircuitBreakerBean.class)
41 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
42 | }
43 |
44 | /**
45 | * When running against a remote profile, we need to wait for the circuitbreaker to reset between each test.
46 | * @throws NoSuchMethodException
47 | * @throws InterruptedException
48 | */
49 | @Before
50 | public void resetCircuitBreaker() throws NoSuchMethodException, InterruptedException {
51 | // Wait to half-open the circuit breaker - previous tests may have run and left it in a sorry state
52 | long addedWaitTimeMillis = 3000;
53 | long timeToWaitMillis = Duration.of(
54 | MethodLevelCircuitBreakerBean.class.getMethod("throwException", boolean.class)
55 | .getAnnotation(CircuitBreaker.class).delay(),
56 | MethodLevelCircuitBreakerBean.class.getMethod("throwException", boolean.class)
57 | .getAnnotation(CircuitBreaker.class).delayUnit()).toMillis() + addedWaitTimeMillis;
58 | Thread.sleep(timeToWaitMillis);
59 |
60 | // Fill it with goodness
61 | int numberOfTasks = ((Double) (
62 | MethodLevelCircuitBreakerBean.class.getMethod("throwException", boolean.class)
63 | .getAnnotation(CircuitBreaker.class).requestVolumeThreshold()
64 | * MethodLevelCircuitBreakerBean.class.getMethod("throwException", boolean.class)
65 | .getAnnotation(CircuitBreaker.class).failureRatio())).intValue()
66 | + MethodLevelCircuitBreakerBean.class.getMethod("throwException", boolean.class)
67 | .getAnnotation(CircuitBreaker.class).successThreshold();
68 | executeThrowExceptionMethodAsynchronously(numberOfTasks, false);
69 | }
70 |
71 | /**
72 | * Test that once a circuitbreaker has opened, that it recloses itself and allows executions again.
73 | * @throws NoSuchMethodException
74 | * @throws InterruptedException
75 | */
76 | @Test
77 | public void circuitBreakerReclosesTest() throws NoSuchMethodException, InterruptedException {
78 | int numberOfExpectedFailures = 2;
79 |
80 | int numberOfTasks = ((Double) (
81 | MethodLevelCircuitBreakerBean.class.getMethod("throwException", boolean.class)
82 | .getAnnotation(CircuitBreaker.class).requestVolumeThreshold()
83 | * MethodLevelCircuitBreakerBean.class.getMethod("throwException", boolean.class)
84 | .getAnnotation(CircuitBreaker.class).failureRatio()))
85 | .intValue() + numberOfExpectedFailures;
86 |
87 | // Force the method to throw errors to open the circuit
88 | List> futures = executeThrowExceptionMethodAsynchronously(numberOfTasks, true);
89 |
90 | // Await and collect results to make sure everything has completed or thrown an exception
91 | int failures = 0;
92 | for (Future future : futures) {
93 | try {
94 | future.get();
95 | } catch (InterruptedException ie) {
96 | Logger.getLogger(MethodLevelCircuitBreakerBeanTest.class.getName()).log(Level.SEVERE, null, ie);
97 | Assert.fail("Got an unexpected InterruptedException");
98 | } catch (ExecutionException ex) {
99 | if (ex.getCause() instanceof CircuitBreakerOpenException) {
100 | failures ++;
101 | } else if (ex.getCause() instanceof RuntimeException
102 | && ex.getCause().getMessage().equals(MethodLevelCircuitBreakerBean.EXPECTED_ERROR_MESSAGE)) {
103 | // Om nom nom
104 | } else {
105 | Logger.getLogger(MethodLevelCircuitBreakerBeanTest.class.getName()).log(Level.SEVERE, null, ex);
106 | Assert.fail("Got an unexpected ExecutionException");
107 | }
108 | }
109 | }
110 |
111 | // numberOfExpectedFailures tasks should fail
112 | Assert.assertTrue("Did not get " + numberOfExpectedFailures + ": " + failures,
113 | failures == numberOfExpectedFailures);
114 |
115 | // Now we wait...
116 | long addedWaitTimeMillis = 3000;
117 | long timeToWaitMillis = Duration.of(
118 | MethodLevelCircuitBreakerBean.class.getMethod("throwException", boolean.class)
119 | .getAnnotation(CircuitBreaker.class).delay(),
120 | MethodLevelCircuitBreakerBean.class.getMethod("throwException", boolean.class)
121 | .getAnnotation(CircuitBreaker.class).delayUnit()).toMillis() + addedWaitTimeMillis;
122 | Thread.sleep(timeToWaitMillis);
123 |
124 | // We should now be able to send a message though as the circuitbreaker should be half-open
125 | try {
126 | methodLevelCircuitBreakerBean.throwException(false);
127 | Assert.assertTrue(true);
128 | } catch (Exception ex) {
129 | Logger.getLogger(MethodLevelCircuitBreakerBeanTest.class.getName()).log(Level.SEVERE, null, ex);
130 | Assert.fail("Got an unexpected Exception");
131 | }
132 | }
133 |
134 | /**
135 | * Helper method that spawns a number of threads to execute against the throwException method concurrently.
136 | * @param iterations
137 | * @param shouldThrowException
138 | * @return
139 | */
140 | private List> executeThrowExceptionMethodAsynchronously(int iterations,
141 | boolean shouldThrowException) {
142 | List> futures = new ArrayList<>();
143 |
144 | ExecutorService executorService = Executors.newSingleThreadExecutor();
145 |
146 | Callable task = () -> {
147 | methodLevelCircuitBreakerBean.throwException(shouldThrowException);
148 | return null;
149 | };
150 |
151 | for (int i = 0; i < iterations; i++) {
152 | futures.add(executorService.submit(task));
153 | }
154 |
155 | return futures;
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/fault-tolerance/fallback/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | fault-tolerance
6 | org.eclipse.microprofile.samples12
7 | 1.0-SNAPSHOT
8 |
9 |
10 | fallback
11 | war
12 |
13 | MicroProfile 1.2: Fault Tolerance - Fallback
14 |
15 |
16 |
--------------------------------------------------------------------------------
/fault-tolerance/fallback/src/main/java/org/eclipse/microprofile/samples12/fallback/FallbackBean.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.fallback;
2 |
3 | import javax.enterprise.context.ApplicationScoped;
4 | import org.eclipse.microprofile.faulttolerance.Fallback;
5 | import org.eclipse.microprofile.faulttolerance.Retry;
6 |
7 | /**
8 | * A bean demonstrating a simple use case of utilising a fallback handler or a fallback method with the Retry annotation.
9 | * @author Andrew Pielage
10 | */
11 | @ApplicationScoped
12 | public class FallbackBean {
13 |
14 | public static final String defaultResponse = "I didn't fail!";
15 | public static final String expectedResponse = "I fell back! Thank you MicroProfile!";
16 |
17 | /**
18 | * Example method that can be made to throw an exception, kicking off the fallbackHandler after it has retried once.
19 | * @param fallback
20 | * @return
21 | */
22 | @Retry(maxRetries = 1)
23 | @Fallback(StringFallbackHandler.class)
24 | public String demonstrateFallbackHandler(boolean fallback) {
25 | if (fallback) {
26 | throw new RuntimeException("I failed somehow! Save me MicroProfile!");
27 | } else {
28 | return defaultResponse;
29 | }
30 | }
31 |
32 | /**
33 | * Example method that can be made to throw an exception, kicking off the fallback method after it has retried once.
34 | * @param fallback
35 | * @return
36 | */
37 | @Retry(maxRetries = 1)
38 | @Fallback(fallbackMethod = "fallbackMethodExample")
39 | public String demonstrateFallbackMethod(boolean fallback) {
40 | if (fallback) {
41 | throw new RuntimeException("I failed somehow! Save me MicroProfile!");
42 | } else {
43 | return defaultResponse;
44 | }
45 | }
46 |
47 | /**
48 | * Very basic example of a fallback method.
49 | * @param fallback Unused in this example method, but necessary because a fallback method must share the same return
50 | * type and parameters as the method it is the fallback for
51 | * @return
52 | */
53 | public String fallbackMethodExample(boolean fallback) {
54 | return expectedResponse;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/fault-tolerance/fallback/src/main/java/org/eclipse/microprofile/samples12/fallback/StringFallbackHandler.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.fallback;
2 |
3 | import javax.enterprise.context.ApplicationScoped;
4 | import org.eclipse.microprofile.faulttolerance.ExecutionContext;
5 | import org.eclipse.microprofile.faulttolerance.FallbackHandler;
6 |
7 | /**
8 | * An example fallback handler for a method with a return type of String.
9 | * @author Andrew Pielage
10 | */
11 | @ApplicationScoped
12 | public class StringFallbackHandler implements FallbackHandler {
13 |
14 | @Override
15 | public String handle(ExecutionContext ec) {
16 | return FallbackBean.expectedResponse;
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/fault-tolerance/fallback/src/test/java/org/eclipse/microprofile/samples12/fallback/FallbackBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.fallback;
2 |
3 | import javax.inject.Inject;
4 | import org.jboss.arquillian.container.test.api.Deployment;
5 | import org.jboss.arquillian.junit.Arquillian;
6 | import org.jboss.shrinkwrap.api.ShrinkWrap;
7 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
8 | import org.jboss.shrinkwrap.api.spec.WebArchive;
9 | import org.junit.Assert;
10 | import org.junit.Test;
11 | import org.junit.runner.RunWith;
12 |
13 | /**
14 | * Tests for the FallbackBean class.
15 | * @author Andrew Pielage
16 | */
17 | @RunWith(Arquillian.class)
18 | public class FallbackBeanTest {
19 |
20 | @Inject
21 | private FallbackBean fallbackBean;
22 |
23 | @Deployment
24 | public static WebArchive createDeployment() {
25 | return ShrinkWrap.create(WebArchive.class)
26 | .addClasses(FallbackBean.class, StringFallbackHandler.class)
27 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
28 | }
29 |
30 | /**
31 | * Tests the operation of the fallback handler.
32 | */
33 | @Test
34 | public void fallbackHandlerTest() {
35 | String result = fallbackBean.demonstrateFallbackHandler(true);
36 | Assert.assertTrue("Did not get the expected result", result.equals(FallbackBean.expectedResponse));
37 | }
38 |
39 | /**
40 | * Tests the operation of the fallback method.
41 | */
42 | @Test
43 | public void fallbackMethodTest() {
44 | String result = fallbackBean.demonstrateFallbackMethod(true);
45 | Assert.assertTrue("Did not get the expected result", result.equals(FallbackBean.expectedResponse));
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/fault-tolerance/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.eclipse.microprofile.samples12
9 | samples-parent
10 | 1.0-SNAPSHOT
11 |
12 |
13 | fault-tolerance
14 | pom
15 |
16 | MicroProfile 1.2: Fault Tolerance
17 |
18 |
19 | asynchronous
20 | bulkhead
21 | circuitbreaker
22 | timeout
23 | retry
24 | fallback
25 |
26 |
27 |
28 |
29 | org.eclipse.microprofile.samples12
30 | test-utils
31 | ${project.version}
32 |
33 |
34 |
--------------------------------------------------------------------------------
/fault-tolerance/retry/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | fault-tolerance
6 | org.eclipse.microprofile.samples12
7 | 1.0-SNAPSHOT
8 |
9 |
10 | retry
11 | war
12 |
13 | MicroProfile 1.2: Fault Tolerance - Retry
14 |
15 |
16 |
--------------------------------------------------------------------------------
/fault-tolerance/retry/src/main/java/org/eclipse/microprofile/samples12/retry/RetryBean.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.retry;
2 |
3 | import javax.enterprise.context.ApplicationScoped;
4 | import org.eclipse.microprofile.faulttolerance.Retry;
5 |
6 | /**
7 | * A bean demonstrating the usage of the Retry annotation.
8 | * @author Andrew Pielage
9 | */
10 | @ApplicationScoped
11 | @Retry(maxRetries = 8, delay = 500, jitter = 250)
12 | public class RetryBean {
13 |
14 | public static final int expectedAttempts = 5;
15 |
16 | // Counters for each method, used to count the number of attempts - this is most definitely not thread safe!
17 | private int method1Counter = 0;
18 | private int method2Counter = 0;
19 |
20 | /**
21 | * Example method that demonstrates the retry annotation by only succeeded once the counter has reached a
22 | * certain point.
23 | * @return
24 | */
25 | public int demonstrateRetry() {
26 | if (method1Counter < expectedAttempts) {
27 | method1Counter++;
28 | throw new RuntimeException("Oh noes! Some exception! Method Counter is currently: " + method1Counter);
29 | }
30 |
31 | return method1Counter;
32 | }
33 |
34 | /**
35 | * An example method demonstrating how you can configure the retry annotation to abort on certain exceptions.
36 | * @param abort
37 | * @return
38 | * @throws InterruptedException Not actually interrupted, just used as an example
39 | */
40 | @Retry(maxRetries = 5, abortOn = InterruptedException.class)
41 | public int demonstrateAbort(boolean abort) throws InterruptedException {
42 | if (method2Counter < expectedAttempts) {
43 | method2Counter++;
44 |
45 | if (abort) {
46 | throw new InterruptedException("Oh noes! A more serious exception!");
47 | } else {
48 | throw new RuntimeException("Oh noes! Some exception! Method Counter is currently: " + method2Counter);
49 | }
50 | }
51 |
52 | return method2Counter;
53 | }
54 |
55 | /**
56 | * Helper method used to reset the counters.
57 | */
58 | public void resetCounters() {
59 | method1Counter = 0;
60 | method2Counter = 0;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/fault-tolerance/retry/src/test/java/org/eclipse/microprofile/samples12/retry/RetryBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.retry;
2 |
3 | import javax.inject.Inject;
4 | import org.jboss.arquillian.container.test.api.Deployment;
5 | import org.jboss.arquillian.junit.Arquillian;
6 | import org.jboss.shrinkwrap.api.ShrinkWrap;
7 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
8 | import org.jboss.shrinkwrap.api.spec.WebArchive;
9 | import org.junit.Assert;
10 | import org.junit.Test;
11 | import org.junit.runner.RunWith;
12 |
13 | /**
14 | * Tests for the RetryBean class.
15 | * @author Andrew Pielage
16 | */
17 | @RunWith(Arquillian.class)
18 | public class RetryBeanTest {
19 |
20 | @Inject
21 | private RetryBean retryBean;
22 |
23 | @Deployment
24 | public static WebArchive createDeployment() {
25 | return ShrinkWrap.create(WebArchive.class)
26 | .addClasses(RetryBean.class)
27 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
28 | }
29 |
30 | /**
31 | * Test that the method retries the expected number of times.
32 | */
33 | @Test
34 | public void retryTest() {
35 | int numberOfAttempts = 0;
36 | numberOfAttempts = retryBean.demonstrateRetry();
37 |
38 | Assert.assertTrue("Didn't get the expected number of attempts: " + numberOfAttempts,
39 | numberOfAttempts == RetryBean.expectedAttempts);
40 | }
41 |
42 | /**
43 | * Test that the method aborts on specific errors.
44 | */
45 | @Test
46 | public void abortOnTest() {
47 | // Prove that the method doesn't just exit anyway by making it retry on an allowed exception.
48 | int numberOfAttempts = 0;
49 | try {
50 | numberOfAttempts = retryBean.demonstrateAbort(false);
51 | } catch (InterruptedException ie) {
52 | Assert.fail("Got an unexpected InterruptedException");
53 | }
54 |
55 | Assert.assertTrue("Didn't get the expected number of attempts: " + numberOfAttempts,
56 | numberOfAttempts == RetryBean.expectedAttempts);
57 |
58 | // Reset the counters
59 | retryBean.resetCounters();
60 |
61 | // Test that it exists on the specified exception
62 | try {
63 | retryBean.demonstrateAbort(true);
64 | } catch (InterruptedException ex) {
65 | return;
66 | }
67 |
68 | Assert.fail("Didn't get an InterruptedException when expected");
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/fault-tolerance/timeout/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | fault-tolerance
6 | org.eclipse.microprofile.samples12
7 | 1.0-SNAPSHOT
8 |
9 |
10 | timeout
11 | war
12 |
13 | MicroProfile 1.2: Fault Tolerance - Timeout
14 |
15 |
16 |
--------------------------------------------------------------------------------
/fault-tolerance/timeout/src/main/java/org/eclipse/microprofile/samples12/timeout/AsynchronousTimeoutBean.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.timeout;
2 |
3 | import java.util.concurrent.CompletableFuture;
4 | import java.util.concurrent.Future;
5 | import javax.enterprise.context.ApplicationScoped;
6 | import org.eclipse.microprofile.faulttolerance.Asynchronous;
7 | import org.eclipse.microprofile.faulttolerance.Timeout;
8 |
9 | /**
10 | * A bean demonstrating how the Timeout and Asynchronous annotations can be used together.
11 | * @author Andrew Pielage
12 | */
13 | @ApplicationScoped
14 | @Timeout
15 | public class AsynchronousTimeoutBean {
16 |
17 | public static final long AWAIT = 3000;
18 |
19 | /**
20 | * Example method that simulates a long running query, running in a different thread.
21 | * @param shouldTimeout
22 | * @return
23 | */
24 | @Asynchronous
25 | public Future timeout(boolean shouldTimeout) {
26 | Boolean timedOut = false;
27 |
28 | if (shouldTimeout) {
29 | try {
30 | // Simulate a long running query
31 | Thread.sleep(AWAIT);
32 | } catch (InterruptedException ex) {
33 | timedOut = true;
34 | }
35 | }
36 |
37 | return CompletableFuture.completedFuture(timedOut);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/fault-tolerance/timeout/src/main/java/org/eclipse/microprofile/samples12/timeout/ClassLevelTimeoutBean.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.timeout;
2 |
3 | import javax.enterprise.context.ApplicationScoped;
4 | import org.eclipse.microprofile.faulttolerance.Timeout;
5 |
6 | /**
7 | * A bean demonstrating how to use the Timeout annotation.
8 | * @author Andrew Pielage
9 | */
10 | @ApplicationScoped
11 | @Timeout(1500)
12 | public class ClassLevelTimeoutBean {
13 |
14 | public static final long AWAIT = 3000;
15 |
16 | /**
17 | * Example method that simulates a long running query.
18 | * @param shouldTimeout
19 | */
20 | public void timeout(boolean shouldTimeout) {
21 | if (shouldTimeout) {
22 | try {
23 | // Simulate a long running query
24 | Thread.sleep(AWAIT);
25 | } catch (InterruptedException ex) {
26 | // Om nom nom
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/fault-tolerance/timeout/src/main/java/org/eclipse/microprofile/samples12/timeout/MethodLevelTimeoutBean.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.timeout;
2 |
3 | import java.time.temporal.ChronoUnit;
4 | import javax.enterprise.context.ApplicationScoped;
5 | import org.eclipse.microprofile.faulttolerance.Timeout;
6 |
7 | /**
8 | * A bean demonstrating how you can use the Timeout annotation on a specific method.
9 | * @author Andrew Pielage
10 | */
11 | @ApplicationScoped
12 | public class MethodLevelTimeoutBean {
13 |
14 | public static final long AWAIT = 5000;
15 |
16 | /**
17 | * Example method that simulates a long running query.
18 | * @param shouldTimeout
19 | */
20 | @Timeout(value = 2, unit = ChronoUnit.SECONDS)
21 | public void timeout(boolean shouldTimeout) {
22 | if (shouldTimeout) {
23 | try {
24 | // Simulate a long running query
25 | Thread.sleep(AWAIT);
26 | } catch (InterruptedException ex) {
27 | // Om nom nom
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/fault-tolerance/timeout/src/main/resources/project-defaults.yml:
--------------------------------------------------------------------------------
1 | swarm:
2 | hystrix:
3 | command:
4 | default:
5 | execution:
6 | isolation:
7 | thread:
8 | timeoutInMilliseconds: 3500 #MORE THAN AsynchronousTimeoutBean.AWAIT CONFIGURED IN TESTS
9 |
--------------------------------------------------------------------------------
/fault-tolerance/timeout/src/test/java/org/eclipse/microprofile/samples12/timeout/AsynchronousTimeoutBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.timeout;
2 |
3 | import java.util.concurrent.ExecutionException;
4 | import java.util.concurrent.Future;
5 | import javax.inject.Inject;
6 |
7 | import org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException;
8 | import org.jboss.arquillian.container.test.api.Deployment;
9 | import org.jboss.arquillian.junit.Arquillian;
10 | import org.jboss.shrinkwrap.api.ShrinkWrap;
11 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
12 | import org.jboss.shrinkwrap.api.spec.WebArchive;
13 | import org.junit.Assert;
14 | import org.junit.Test;
15 | import org.junit.runner.RunWith;
16 |
17 | /**
18 | * Test class for the AsynchronousTimeoutBean.
19 | * @author Andrew Pielage
20 | */
21 | @RunWith(Arquillian.class)
22 | public class AsynchronousTimeoutBeanTest {
23 |
24 | @Inject
25 | private AsynchronousTimeoutBean asynchronousTimeoutBean;
26 |
27 | @Deployment
28 | public static WebArchive createDeployment() {
29 | return ShrinkWrap.create(WebArchive.class)
30 | .addClasses(AsynchronousTimeoutBean.class)
31 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
32 | .addAsResource("project-defaults.yml");
33 | }
34 |
35 | /**
36 | * Tests that the timeout annotation interrupts a long running task and throws a TimeoutException upon calling
37 | * future.get().
38 | * @throws InterruptedException
39 | * @throws ExecutionException
40 | */
41 | @Test
42 | public void timeoutTest() throws InterruptedException, ExecutionException {
43 | Future future = asynchronousTimeoutBean.timeout(true);
44 | try {
45 | future.get();
46 | } catch (TimeoutException toe) {
47 | return;
48 | } catch (ExecutionException ex) {
49 | if (ex.getCause() instanceof TimeoutException) {
50 | return;
51 | }
52 | }
53 |
54 | Assert.fail();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/fault-tolerance/timeout/src/test/java/org/eclipse/microprofile/samples12/timeout/ClassLevelTimeoutBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.timeout;
2 |
3 | import javax.inject.Inject;
4 | import org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException;
5 | import org.jboss.arquillian.container.test.api.Deployment;
6 | import org.jboss.arquillian.junit.Arquillian;
7 | import org.jboss.shrinkwrap.api.ShrinkWrap;
8 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
9 | import org.jboss.shrinkwrap.api.spec.WebArchive;
10 | import org.junit.Assert;
11 | import org.junit.Test;
12 | import org.junit.runner.RunWith;
13 |
14 | /**
15 | * Test class for ClassLevelTimeoutBean.
16 | * @author Andrew Pielage
17 | */
18 | @RunWith(Arquillian.class)
19 | public class ClassLevelTimeoutBeanTest {
20 |
21 | @Inject
22 | private ClassLevelTimeoutBean classLevelTimeoutBean;
23 |
24 | @Deployment
25 | public static WebArchive createDeployment() {
26 | return ShrinkWrap.create(WebArchive.class)
27 | .addClasses(ClassLevelTimeoutBean.class)
28 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
29 | }
30 |
31 | /**
32 | * Tests that the timeout annotation interrupts a long running task and throws a TimeoutException.
33 | */
34 | @Test
35 | public void timeoutTest() {
36 | try {
37 | classLevelTimeoutBean.timeout(true);
38 | } catch (TimeoutException toe) {
39 | return;
40 | }
41 |
42 | Assert.fail();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/fault-tolerance/timeout/src/test/java/org/eclipse/microprofile/samples12/timeout/MethodLevelTimeoutBeanTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile.samples12.timeout;
2 |
3 | import javax.inject.Inject;
4 | import org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException;
5 | import org.jboss.arquillian.container.test.api.Deployment;
6 | import org.jboss.arquillian.junit.Arquillian;
7 | import org.jboss.shrinkwrap.api.ShrinkWrap;
8 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
9 | import org.jboss.shrinkwrap.api.spec.WebArchive;
10 | import org.junit.Assert;
11 | import org.junit.Test;
12 | import org.junit.runner.RunWith;
13 |
14 | /**
15 | * Test class for MethodLevelTimeoutBeanTest
16 | * @author Andrew Pielage
17 | */
18 | @RunWith(Arquillian.class)
19 | public class MethodLevelTimeoutBeanTest {
20 |
21 | @Inject
22 | private MethodLevelTimeoutBean methodLevelTimeoutBean;
23 |
24 | @Deployment
25 | public static WebArchive createDeployment() {
26 | return ShrinkWrap.create(WebArchive.class)
27 | .addClasses(MethodLevelTimeoutBean.class)
28 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
29 | }
30 |
31 | /**
32 | * Tests that the timeout annotation interrupts a long running task and throws a TimeoutException.
33 | */
34 | @Test
35 | public void timeoutTest() {
36 | try {
37 | methodLevelTimeoutBean.timeout(true);
38 | } catch (TimeoutException toe) {
39 | return;
40 | }
41 |
42 | Assert.fail();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/jwt-auth/README.md:
--------------------------------------------------------------------------------
1 | # Eclipse MicroProfile 1.2 Samples - JWT Auth 1.0
2 |
3 | - [Wiki project page](https://wiki.eclipse.org/MicroProfile/JWT_Auth)
4 | - [Spec, API, TCK GitHub repo](https://github.com/eclipse/microprofile-jwt-auth)
5 |
6 | **Note** for practical purposes these samples have been superseded by the ones at https://github.com/javaee-samples/microprofile1.4-samples/tree/master/jwt-auth
7 |
8 | ## Samples ##
9 |
10 | - **basic-authentication** The test sends a very basic signed JWT token to a protected servlet. The MP-JWT Auth implementation
11 | checks if the token is valid and sets the authenticated identity from the `upn` field and `groups` field
12 | **jaxrs ** Just like basic-authentication, but uses a JAX-RS endpoint. Specifically demonstrates the support of @RolesAllowed to secure and endpoint.
13 |
14 |
15 |
16 | ## Implementation config ##
17 |
18 | There's at least 2 items that need to be configured in an implementation specific way: the *issuer*, which represents the party that vended the token, and the *public key* which is used to verify the signature of a JWT token being sent to the server.
19 |
20 | - **Payara (tech preview)**
21 | - *issuer* - defined in "payara-mp-jwt.properties" which is placed in the classpath root of the application archive
22 | - *public key* - the file "publicKey.pem" which is also placed in the classpath root of the application archive
23 | - **Liberty**
24 | - *issuer* - defined in the "mpJwt" tag in "server.xml" which in the placed inside the installed Liberty: `[install dir]/wlp/usr/servers/defaultServer/server.xml`
25 | - *public key* - the file "key.jks" which in the placed inside the installed Liberty: `[install dir]/wlp/usr/servers/defaultServer/resources/security/key.jks`
26 | - **WildFly (Swarm)**
27 | - *issuer* - defined in "project-default.yml" which is placed in the classpath root of the application archive. This also configures the security system (security domain in JBoss terms) such that all artifacts to support MP-Auth JWT are installed
28 | - *public key* - the file "MP-JWT-SIGNER" which is placed in the classpath's META-INF of the application archive.
29 |
30 |
31 | ## TCK ##
32 |
33 | The public/private keys are taken from the MP-Auth TCK. The Liberty key is in a special format and has been taken from the Liberty TCK version. Config files for the various servers are inspired by those in the TCK and TCK extensions.
34 |
35 | See the following URLs:
36 |
37 | - [MP-Auth TCK](https://github.com/eclipse/microprofile-jwt-auth/tree/master/tck)
38 | - [Payara TCK Ext](https://github.com/payara/Payara/tree/Payara-5/appserver/payara-appserver-modules/microprofile/jwt-auth-tck)
39 | - [Liberty TCK](https://github.com/OpenLiberty/open-liberty/tree/master/dev/com.ibm.ws.security.mp.jwt_fat_tck)
40 | - [WildFly TCK Ext](https://github.com/MicroProfileJWT/wfswarm-jwt-auth-tck)
41 |
42 |
--------------------------------------------------------------------------------
/jwt-auth/basic-authentication/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | org.eclipse.microprofile.samples12
6 | jwt-auth
7 | 1.0-SNAPSHOT
8 |
9 |
10 | basic-authentication
11 | war
12 | MicroProfile 1.2: JWT-AUTH - Basic Authentication
13 |
14 |
15 |
--------------------------------------------------------------------------------
/jwt-auth/basic-authentication/src/main/java/org/eclipse/microprofile12/jwtauth/basic/ApplicationInit.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.jwtauth.basic;
2 |
3 | import javax.enterprise.context.ApplicationScoped;
4 |
5 | import org.eclipse.microprofile.auth.LoginConfig;
6 |
7 | @LoginConfig(
8 | authMethod = "MP-JWT",
9 | // Even though specified being only for HTTP Basic auth, JBoss/WildFly/Swarm mandates this
10 | // to refer to its proprietary "security domain" concept.
11 | realmName = "MP-JWT"
12 | )
13 | @ApplicationScoped
14 | public class ApplicationInit {
15 |
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/jwt-auth/basic-authentication/src/main/java/org/eclipse/microprofile12/jwtauth/basic/Servlet.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.jwtauth.basic;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.annotation.security.DeclareRoles;
6 | import javax.servlet.ServletException;
7 | import javax.servlet.annotation.HttpConstraint;
8 | import javax.servlet.annotation.ServletSecurity;
9 | import javax.servlet.annotation.WebServlet;
10 | import javax.servlet.http.HttpServlet;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 |
14 |
15 | @WebServlet("/servlet")
16 | @ServletSecurity(@HttpConstraint(rolesAllowed = "architect"))
17 | @DeclareRoles({"architect", "bar", "kaz"})
18 | public class Servlet extends HttpServlet {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | @Override
23 | public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
24 |
25 | String webName = null;
26 | if (request.getUserPrincipal() != null) {
27 | webName = request.getUserPrincipal().getName();
28 | }
29 |
30 | response.setContentType("text/plain");
31 |
32 | response.getWriter().write(
33 | "This is a protected servlet \n" +
34 |
35 | "web username: " + webName + "\n" +
36 |
37 | "web user has role \"architect\": " + request.isUserInRole("architect") + "\n" +
38 | "web user has role \"bar\": " + request.isUserInRole("bar") + "\n" +
39 | "web user has role \"kaz\": " + request.isUserInRole("kaz") + "\n"
40 | );
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/jwt-auth/basic-authentication/src/main/resources/META-INF/MP-JWT-SIGNER:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq
3 | Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR
4 | TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e
5 | UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9
6 | AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn
7 | sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x
8 | nQIDAQAB
9 | -----END RSA PUBLIC KEY-----
10 |
--------------------------------------------------------------------------------
/jwt-auth/basic-authentication/src/main/resources/jwt-roles.properties:
--------------------------------------------------------------------------------
1 | foo=bar
--------------------------------------------------------------------------------
/jwt-auth/basic-authentication/src/main/resources/payara-mp-jwt.properties:
--------------------------------------------------------------------------------
1 | accepted.issuer=org.eclipse.microprofile12
2 |
--------------------------------------------------------------------------------
/jwt-auth/basic-authentication/src/main/resources/project-defaults.yml:
--------------------------------------------------------------------------------
1 | # A project defaults for use with MP-JWT auth-method
2 | # Based on https://github.com/MicroProfileJWT/wfswarm-jwt-auth-tck/blob/master/src/main/resources/project-defaults.yml
3 | swarm:
4 | bind:
5 | address: localhost
6 | microprofile:
7 | jwtauth:
8 | token:
9 | issuedBy: "org.eclipse.microprofile12"
10 | logging:
11 | loggers:
12 | io.undertow.request.security:
13 | level: TRACE
14 | security:
15 | security-domains:
16 | MP-JWT:
17 | jaspi-authentication:
18 | login-module-stacks:
19 | roles-lm-stack:
20 | login-modules:
21 | # This stack performs the token verification and group to role mapping
22 | - login-module: rm
23 | code: org.wildfly.swarm.microprofile.jwtauth.deployment.auth.jaas.JWTLoginModule
24 | flag: required
25 | module-options:
26 | rolesProperties: jwt-roles.properties
27 | auth-modules:
28 | # This module integrates the MP-JWT custom authentication mechanism into the web container
29 | http:
30 | code: org.wildfly.extension.undertow.security.jaspi.modules.HTTPSchemeServerAuthModule
31 | module: org.wildfly.extension.undertow
32 | flag: required
33 | login-module-stack-ref: roles-lm-stack
--------------------------------------------------------------------------------
/jwt-auth/basic-authentication/src/main/resources/publicKey.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq
3 | Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR
4 | TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e
5 | UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9
6 | AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn
7 | sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x
8 | nQIDAQAB
9 | -----END RSA PUBLIC KEY-----
10 |
--------------------------------------------------------------------------------
/jwt-auth/basic-authentication/src/test/java/org/eclipse/microprofile12/jwtauth/basic/BasicAuthenticationTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.jwtauth.basic;
2 |
3 | import static javax.ws.rs.client.ClientBuilder.newClient;
4 | import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION;
5 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
6 | import static org.eclipse.microprofile12.JwtTokenGenerator.generateJWTString;
7 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
8 | import static org.junit.Assert.assertFalse;
9 | import static org.junit.Assert.assertTrue;
10 |
11 | import java.io.IOException;
12 | import java.net.URI;
13 | import java.net.URL;
14 |
15 | import javax.ws.rs.core.Response;
16 |
17 | import org.eclipse.microprofile12.jwtauth.basic.ApplicationInit;
18 | import org.eclipse.microprofile12.jwtauth.basic.Servlet;
19 | import org.jboss.arquillian.container.test.api.Deployment;
20 | import org.jboss.arquillian.container.test.api.RunAsClient;
21 | import org.jboss.arquillian.junit.Arquillian;
22 | import org.jboss.arquillian.test.api.ArquillianResource;
23 | import org.jboss.shrinkwrap.api.spec.WebArchive;
24 | import org.junit.Test;
25 | import org.junit.runner.RunWith;
26 |
27 | /**
28 | * @author Arjan Tijms
29 | */
30 | @RunWith(Arquillian.class)
31 | public class BasicAuthenticationTest {
32 |
33 | @ArquillianResource
34 | private URL base;
35 |
36 | @Deployment(testable = false)
37 | public static WebArchive createDeployment() {
38 | WebArchive archive =
39 | create(WebArchive.class)
40 | .addClasses(
41 | ApplicationInit.class,
42 | Servlet.class
43 | ).addAsResource(
44 | // Payara Properties file configuring that "org.eclipse.microprofile12" is the valid issuer
45 | "payara-mp-jwt.properties"
46 | ).addAsResource(
47 | // WildFly file configuring that "org.eclipse.microprofile12" is the valid issuer and setting up
48 | // the security system (domain) such that all artifacts to support MP-Auth JWT are installed
49 | "project-defaults.yml"
50 | ).addAsResource(
51 | // Payara public key to verify the incoming signed JWT's signature
52 | "publicKey.pem"
53 | ).addAsResource(
54 | // WildFly public key to verify the incoming signed JWT's signature
55 | "META-INF/MP-JWT-SIGNER"
56 | ).addAsResource(
57 | // WildFly public key to verify the incoming signed JWT's signature
58 | "jwt-roles.properties"
59 | )
60 | ;
61 |
62 | System.out.println("************************************************************");
63 | System.out.println(archive.toString(true));
64 | System.out.println("************************************************************");
65 |
66 | return archive;
67 |
68 | }
69 |
70 | @Test
71 | @RunAsClient
72 | public void testProtectedPageNotLoggedin() throws IOException {
73 |
74 | Response response =
75 | newClient()
76 | .target(
77 | URI.create(new URL(base, "servlet").toExternalForm()))
78 | .request(TEXT_PLAIN)
79 | .get();
80 |
81 | // Not logged-in thus should not be accessible.
82 | assertFalse(
83 | "Not authenticated, so should not have been able to access protected resource",
84 | response.readEntity(String.class).contains("This is a protected servlet")
85 | );
86 | }
87 |
88 | @Test
89 | @RunAsClient
90 | public void testProtectedPageLoggedin() throws Exception {
91 |
92 | String response =
93 | newClient()
94 | .target(
95 | URI.create(new URL(base, "servlet").toExternalForm()))
96 | .request(TEXT_PLAIN)
97 | .header(AUTHORIZATION, "Bearer " + generateJWTString("jwt-token.json"))
98 | .get(String.class);
99 |
100 | // Now has to be logged-in so page is accessible
101 | assertTrue(
102 | "Should have been authenticated, but could not access protected resource",
103 | response.contains("This is a protected servlet")
104 | );
105 |
106 | // Not only does the page needs to be accessible, the caller should have
107 | // the correct name and roles as well
108 |
109 | // Being able to access a page protected by a role but then seeing the un-authenticated
110 | // (anonymous) user would normally be impossible, but could happen if the authorization
111 | // system checks roles on the authenticated subject, but does not correctly expose
112 | // or propagate these to the HttpServletRequest
113 | assertFalse(
114 | "Protected resource could be accessed, but the user appears to be the unauthenticated user. " +
115 | "This should not be possible",
116 | response.contains("web username: null")
117 | );
118 |
119 | // An authenticated user should have the exact name "test" and nothing else.
120 | assertTrue(
121 | "Protected resource could be accessed, but the username is not correct.",
122 | response.contains("web username: test")
123 | );
124 |
125 | // Being able to access a page protected by role "architect" but failing
126 | // the test for this role would normally be impossible, but could happen if the
127 | // authorization system checks roles on the authenticated subject, but does not
128 | // correctly expose or propagate these to the HttpServletRequest
129 | assertTrue(
130 | "Resource protected by role \"architect\" could be accessed, but user fails test for this role." +
131 | "This should not be possible",
132 | response.contains("web user has role \"architect\": true")
133 | );
134 | }
135 |
136 | }
137 |
--------------------------------------------------------------------------------
/jwt-auth/basic-authentication/src/test/resources/jwt-token.json:
--------------------------------------------------------------------------------
1 | {
2 | "iss": "org.eclipse.microprofile12",
3 | "jti": "a-123",
4 | "sub": "24400320",
5 | "aud": "s6BhdRkqt3",
6 | "exp": 1311281970,
7 | "iat": 1311280970,
8 | "auth_time": 1311280969,
9 | "upn": "test",
10 | "groups": [
11 | "architect",
12 | "master",
13 | "leader",
14 | "dev"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/jwt-auth/basic-authentication/src/test/resources/privateKey.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCWK8UjyoHgPTLa
3 | PLQJ8SoXLLjpHSjtLxMqmzHnFscqhTVVaDpCRCb6e3Ii/WniQTWw8RA7vf4djz4H
4 | OzvlfBFNgvUGZHXDwnmGaNVaNzpHYFMEYBhE8VGGiveSkzqeLZI+Y02G6sQAfDtN
5 | qqzM/l5QX8X34oQFaTBW1r49nftvCpITiwJvWyhkWtXP9RP8sXi1im5Vi3dhupOh
6 | nelk5n0BfajUYIbfHA6ORzjHRbt7NtBl0L2J+0/FUdHyKs6KMlFGNw8O0Dq88qnM
7 | uXoLJiewhg9332W3DFMeOveel+//cvDnRsCRtPgd4sXFPHh+UShkso7+DRsChXa6
8 | oGGQD3GdAgMBAAECggEAAjfTSZwMHwvIXIDZB+yP+pemg4ryt84iMlbofclQV8hv
9 | 6TsI4UGwcbKxFOM5VSYxbNOisb80qasb929gixsyBjsQ8284bhPJR7r0q8h1C+jY
10 | URA6S4pk8d/LmFakXwG9Tz6YPo3pJziuh48lzkFTk0xW2Dp4SLwtAptZY/+ZXyJ6
11 | 96QXDrZKSSM99Jh9s7a0ST66WoxSS0UC51ak+Keb0KJ1jz4bIJ2C3r4rYlSu4hHB
12 | Y73GfkWORtQuyUDa9yDOem0/z0nr6pp+pBSXPLHADsqvZiIhxD/O0Xk5I6/zVHB3
13 | zuoQqLERk0WvA8FXz2o8AYwcQRY2g30eX9kU4uDQAQKBgQDmf7KGImUGitsEPepF
14 | KH5yLWYWqghHx6wfV+fdbBxoqn9WlwcQ7JbynIiVx8MX8/1lLCCe8v41ypu/eLtP
15 | iY1ev2IKdrUStvYRSsFigRkuPHUo1ajsGHQd+ucTDf58mn7kRLW1JGMeGxo/t32B
16 | m96Af6AiPWPEJuVfgGV0iwg+HQKBgQCmyPzL9M2rhYZn1AozRUguvlpmJHU2DpqS
17 | 34Q+7x2Ghf7MgBUhqE0t3FAOxEC7IYBwHmeYOvFR8ZkVRKNF4gbnF9RtLdz0DMEG
18 | 5qsMnvJUSQbNB1yVjUCnDAtElqiFRlQ/k0LgYkjKDY7LfciZl9uJRl0OSYeX/qG2
19 | tRW09tOpgQKBgBSGkpM3RN/MRayfBtmZvYjVWh3yjkI2GbHA1jj1g6IebLB9SnfL
20 | WbXJErCj1U+wvoPf5hfBc7m+jRgD3Eo86YXibQyZfY5pFIh9q7Ll5CQl5hj4zc4Y
21 | b16sFR+xQ1Q9Pcd+BuBWmSz5JOE/qcF869dthgkGhnfVLt/OQzqZluZRAoGAXQ09
22 | nT0TkmKIvlza5Af/YbTqEpq8mlBDhTYXPlWCD4+qvMWpBII1rSSBtftgcgca9XLB
23 | MXmRMbqtQeRtg4u7dishZVh1MeP7vbHsNLppUQT9Ol6lFPsd2xUpJDc6BkFat62d
24 | Xjr3iWNPC9E9nhPPdCNBv7reX7q81obpeXFMXgECgYEAmk2Qlus3OV0tfoNRqNpe
25 | Mb0teduf2+h3xaI1XDIzPVtZF35ELY/RkAHlmWRT4PCdR0zXDidE67L6XdJyecSt
26 | FdOUH8z5qUraVVebRFvJqf/oGsXc4+ex1ZKUTbY0wqY1y9E39yvB3MaTmZFuuqk8
27 | f3cg+fr8aou7pr9SHhJlZCU=
28 | -----END RSA PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/jwt-auth/jaxrs/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | org.eclipse.microprofile.samples12
6 | jwt-auth
7 | 1.0-SNAPSHOT
8 |
9 |
10 | jaxrs
11 | war
12 | MicroProfile 1.2: JWT-AUTH - JAX-RS
13 |
14 |
15 |
--------------------------------------------------------------------------------
/jwt-auth/jaxrs/src/main/java/org/eclipse/microprofile12/jwtauth/jaxrs/ApplicationInit.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.jwtauth.jaxrs;
2 |
3 | import javax.annotation.security.DeclareRoles;
4 | import javax.ws.rs.ApplicationPath;
5 | import javax.ws.rs.core.Application;
6 |
7 | import org.eclipse.microprofile.auth.LoginConfig;
8 |
9 | @LoginConfig(
10 | authMethod = "MP-JWT",
11 | // Even though specified being only for HTTP Basic auth, JBoss/WildFly/Swarm mandates this
12 | // to refer to its proprietary "security domain" concept.
13 | realmName = "MP-JWT"
14 | )
15 | @DeclareRoles({"architect", "bar", "kaz"})
16 | @ApplicationPath("/")
17 | public class ApplicationInit extends Application {
18 |
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/jwt-auth/jaxrs/src/main/java/org/eclipse/microprofile12/jwtauth/jaxrs/Resource.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.jwtauth.jaxrs;
2 |
3 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
4 |
5 | import java.security.Principal;
6 |
7 | import javax.annotation.security.RolesAllowed;
8 | import javax.enterprise.context.ApplicationScoped;
9 | import javax.inject.Inject;
10 | import javax.ws.rs.GET;
11 | import javax.ws.rs.Path;
12 | import javax.ws.rs.Produces;
13 |
14 | @ApplicationScoped
15 | @Path("/resource")
16 | @Produces(TEXT_PLAIN)
17 | public class Resource {
18 |
19 | @Inject
20 | private Principal principal;
21 |
22 | @GET
23 | @Path("/protected")
24 | @RolesAllowed("architect")
25 | public String protectedResource() {
26 | return
27 | "This is a protected resource \n" +
28 | "web username: " + principal.getName() + "\n";
29 | }
30 |
31 | @GET
32 | @Path("public")
33 | public String publicResource() {
34 | return
35 | "This is a public resource \n" +
36 | "web username: " + principal.getName() + "\n";
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/jwt-auth/jaxrs/src/main/resources/jwt-roles.properties:
--------------------------------------------------------------------------------
1 | foo=bar
--------------------------------------------------------------------------------
/jwt-auth/jaxrs/src/main/resources/payara-mp-jwt.properties:
--------------------------------------------------------------------------------
1 | accepted.issuer=org.eclipse.microprofile12
2 |
--------------------------------------------------------------------------------
/jwt-auth/jaxrs/src/main/resources/project-defaults.yml:
--------------------------------------------------------------------------------
1 | # A project defaults for use with MP-JWT auth-method
2 | # Based on https://github.com/MicroProfileJWT/wfswarm-jwt-auth-tck/blob/master/src/main/resources/project-defaults.yml
3 | swarm:
4 | bind:
5 | address: localhost
6 | microprofile:
7 | jwt:
8 | default-missing-method-permissions-deny-access: false
9 | token:
10 | issued-by: "org.eclipse.microprofile12"
11 | signer-pub-key: classpath:publicKey.pem
12 | logging:
13 | loggers:
14 | io.undertow.request.security:
15 | level: TRACE
16 | security:
17 | security-domains:
18 | MP-JWT:
19 | jaspi-authentication:
20 | login-module-stacks:
21 | roles-lm-stack:
22 | login-modules:
23 | # This stack performs the token verification and group to role mapping
24 | - login-module: rm
25 | code: org.wildfly.swarm.microprofile.jwtauth.deployment.auth.jaas.JWTLoginModule
26 | flag: required
27 | module-options:
28 | rolesProperties: jwt-roles.properties
29 | auth-modules:
30 | # This module integrates the MP-JWT custom authentication mechanism into the web container
31 | http:
32 | code: org.wildfly.extension.undertow.security.jaspi.modules.HTTPSchemeServerAuthModule
33 | module: org.wildfly.extension.undertow
34 | flag: required
35 | login-module-stack-ref: roles-lm-stack
36 |
--------------------------------------------------------------------------------
/jwt-auth/jaxrs/src/main/resources/publicKey.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq
3 | Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR
4 | TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e
5 | UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9
6 | AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn
7 | sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x
8 | nQIDAQAB
9 | -----END RSA PUBLIC KEY-----
10 |
--------------------------------------------------------------------------------
/jwt-auth/jaxrs/src/test/java/org/eclipse/microprofile12/jwtauth/jaxrs/JaxRsTest.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12.jwtauth.jaxrs;
2 |
3 | import static javax.ws.rs.client.ClientBuilder.newClient;
4 | import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION;
5 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
6 | import static org.eclipse.microprofile12.JwtTokenGenerator.generateJWTString;
7 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
8 | import static org.junit.Assert.assertFalse;
9 | import static org.junit.Assert.assertTrue;
10 |
11 | import java.io.IOException;
12 | import java.net.URI;
13 | import java.net.URL;
14 |
15 | import javax.ws.rs.core.Response;
16 |
17 | import org.jboss.arquillian.container.test.api.Deployment;
18 | import org.jboss.arquillian.container.test.api.RunAsClient;
19 | import org.jboss.arquillian.junit.Arquillian;
20 | import org.jboss.arquillian.test.api.ArquillianResource;
21 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
22 | import org.jboss.shrinkwrap.api.spec.WebArchive;
23 | import org.junit.Test;
24 | import org.junit.runner.RunWith;
25 |
26 | /**
27 | * @author Arjan Tijms
28 | */
29 | @RunWith(Arquillian.class)
30 | public class JaxRsTest {
31 |
32 | @ArquillianResource
33 | private URL base;
34 |
35 | @Deployment(testable = false)
36 | public static WebArchive createDeployment() {
37 | WebArchive archive =
38 | create(WebArchive.class)
39 | .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
40 | .addClasses(
41 | ApplicationInit.class,
42 | Resource.class
43 | ).addAsResource(
44 | // Payara Properties file configuring that "org.eclipse.microprofile12" is the valid issuer
45 | "payara-mp-jwt.properties"
46 | ).addAsResource(
47 | // Thorntail file configuring that "org.eclipse.microprofile12" is the valid issuer and setting up
48 | // the security system (domain) such that all artifacts to support MP-Auth JWT are installed
49 | "project-defaults.yml"
50 | ).addAsResource(
51 | // Payara/Thorntail public key to verify the incoming signed JWT's signature
52 | "publicKey.pem"
53 | ).addAsResource(
54 | // WildFly public key to verify the incoming signed JWT's signature
55 | "jwt-roles.properties"
56 | )
57 | ;
58 |
59 | System.out.println("************************************************************");
60 | System.out.println(archive.toString(true));
61 | System.out.println("************************************************************");
62 |
63 | return archive;
64 |
65 | }
66 |
67 | @Test
68 | @RunAsClient
69 | public void testProtectedResourceNotLoggedin() throws IOException {
70 |
71 | System.out.println("-------------------------------------------------------------------------");
72 | System.out.println("Base URL: " + base);
73 | System.out.println("-------------------------------------------------------------------------");
74 |
75 | Response response =
76 | newClient()
77 | .target(
78 | URI.create(new URL(base, "resource/protected").toExternalForm()))
79 | .request(TEXT_PLAIN)
80 | .get();
81 |
82 | // Not logged-in thus should not be accessible.
83 | assertFalse(
84 | "Not authenticated, so should not have been able to access protected resource",
85 | response.readEntity(String.class).contains("This is a protected resource")
86 | );
87 | }
88 |
89 | @Test
90 | @RunAsClient
91 | public void testPublicResourceNotLoggedin() throws IOException {
92 |
93 | Response response =
94 | newClient()
95 | .target(
96 | URI.create(new URL(base, "resource/public").toExternalForm()))
97 | .request(TEXT_PLAIN)
98 | .get();
99 |
100 | // Public resource, no log-in needed
101 | assertTrue(
102 | "Public resource is not constrained (protected) so should be accessible without sending the JWT token",
103 | response.readEntity(String.class).contains("This is a public resource")
104 | );
105 | }
106 |
107 | @Test
108 | @RunAsClient
109 | public void testProtectedResourceLoggedin() throws Exception {
110 |
111 | String response =
112 | newClient()
113 | .target(
114 | URI.create(new URL(base, "resource/protected").toExternalForm()))
115 | .request(TEXT_PLAIN)
116 | .header(AUTHORIZATION, "Bearer " + generateJWTString("jwt-token.json"))
117 | .get(String.class);
118 |
119 |
120 | System.out.println("-------------------------------------------------------------------------");
121 | System.out.println("Response: " + response);
122 | System.out.println("-------------------------------------------------------------------------");
123 |
124 | // Now has to be logged-in so page is accessible
125 | assertTrue(
126 | "Should have been authenticated, but could not access protected resource",
127 | response.contains("This is a protected resource")
128 | );
129 |
130 | // Not only does the resource needs to be accessible, the caller should have
131 | // the correct name
132 |
133 | // Being able to access a page protected by a role but then seeing the un-authenticated
134 | // (anonymous) user would normally be impossible, but could happen if the authorization
135 | // system checks roles on the authenticated subject, but does not correctly expose
136 | // or propagate these to the injected Principal
137 | assertFalse(
138 | "Protected resource could be accessed, but the user appears to be the unauthenticated user. " +
139 | "This should not be possible",
140 | response.contains("web username: null")
141 | );
142 |
143 | // An authenticated user should have the exact name "test" and nothing else.
144 | assertTrue(
145 | "Protected resource could be accessed, but the username is not correct.",
146 | response.contains("web username: test")
147 | );
148 |
149 | }
150 |
151 | }
152 |
--------------------------------------------------------------------------------
/jwt-auth/jaxrs/src/test/resources/jwt-token.json:
--------------------------------------------------------------------------------
1 | {
2 | "iss": "org.eclipse.microprofile12",
3 | "jti": "a-123",
4 | "sub": "24400320",
5 | "aud": "s6BhdRkqt3",
6 | "exp": 1311281970,
7 | "iat": 1311280970,
8 | "auth_time": 1311280969,
9 | "upn": "test",
10 | "groups": [
11 | "architect",
12 | "master",
13 | "leader",
14 | "dev"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/jwt-auth/jaxrs/src/test/resources/privateKey.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCWK8UjyoHgPTLa
3 | PLQJ8SoXLLjpHSjtLxMqmzHnFscqhTVVaDpCRCb6e3Ii/WniQTWw8RA7vf4djz4H
4 | OzvlfBFNgvUGZHXDwnmGaNVaNzpHYFMEYBhE8VGGiveSkzqeLZI+Y02G6sQAfDtN
5 | qqzM/l5QX8X34oQFaTBW1r49nftvCpITiwJvWyhkWtXP9RP8sXi1im5Vi3dhupOh
6 | nelk5n0BfajUYIbfHA6ORzjHRbt7NtBl0L2J+0/FUdHyKs6KMlFGNw8O0Dq88qnM
7 | uXoLJiewhg9332W3DFMeOveel+//cvDnRsCRtPgd4sXFPHh+UShkso7+DRsChXa6
8 | oGGQD3GdAgMBAAECggEAAjfTSZwMHwvIXIDZB+yP+pemg4ryt84iMlbofclQV8hv
9 | 6TsI4UGwcbKxFOM5VSYxbNOisb80qasb929gixsyBjsQ8284bhPJR7r0q8h1C+jY
10 | URA6S4pk8d/LmFakXwG9Tz6YPo3pJziuh48lzkFTk0xW2Dp4SLwtAptZY/+ZXyJ6
11 | 96QXDrZKSSM99Jh9s7a0ST66WoxSS0UC51ak+Keb0KJ1jz4bIJ2C3r4rYlSu4hHB
12 | Y73GfkWORtQuyUDa9yDOem0/z0nr6pp+pBSXPLHADsqvZiIhxD/O0Xk5I6/zVHB3
13 | zuoQqLERk0WvA8FXz2o8AYwcQRY2g30eX9kU4uDQAQKBgQDmf7KGImUGitsEPepF
14 | KH5yLWYWqghHx6wfV+fdbBxoqn9WlwcQ7JbynIiVx8MX8/1lLCCe8v41ypu/eLtP
15 | iY1ev2IKdrUStvYRSsFigRkuPHUo1ajsGHQd+ucTDf58mn7kRLW1JGMeGxo/t32B
16 | m96Af6AiPWPEJuVfgGV0iwg+HQKBgQCmyPzL9M2rhYZn1AozRUguvlpmJHU2DpqS
17 | 34Q+7x2Ghf7MgBUhqE0t3FAOxEC7IYBwHmeYOvFR8ZkVRKNF4gbnF9RtLdz0DMEG
18 | 5qsMnvJUSQbNB1yVjUCnDAtElqiFRlQ/k0LgYkjKDY7LfciZl9uJRl0OSYeX/qG2
19 | tRW09tOpgQKBgBSGkpM3RN/MRayfBtmZvYjVWh3yjkI2GbHA1jj1g6IebLB9SnfL
20 | WbXJErCj1U+wvoPf5hfBc7m+jRgD3Eo86YXibQyZfY5pFIh9q7Ll5CQl5hj4zc4Y
21 | b16sFR+xQ1Q9Pcd+BuBWmSz5JOE/qcF869dthgkGhnfVLt/OQzqZluZRAoGAXQ09
22 | nT0TkmKIvlza5Af/YbTqEpq8mlBDhTYXPlWCD4+qvMWpBII1rSSBtftgcgca9XLB
23 | MXmRMbqtQeRtg4u7dishZVh1MeP7vbHsNLppUQT9Ol6lFPsd2xUpJDc6BkFat62d
24 | Xjr3iWNPC9E9nhPPdCNBv7reX7q81obpeXFMXgECgYEAmk2Qlus3OV0tfoNRqNpe
25 | Mb0teduf2+h3xaI1XDIzPVtZF35ELY/RkAHlmWRT4PCdR0zXDidE67L6XdJyecSt
26 | FdOUH8z5qUraVVebRFvJqf/oGsXc4+ex1ZKUTbY0wqY1y9E39yvB3MaTmZFuuqk8
27 | f3cg+fr8aou7pr9SHhJlZCU=
28 | -----END RSA PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/jwt-auth/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | org.eclipse.microprofile.samples12
6 | samples-parent
7 | 1.0-SNAPSHOT
8 |
9 |
10 | jwt-auth
11 | pom
12 |
13 | MicroProfile 1.2: JWT-AUTH
14 |
15 |
16 | basic-authentication
17 | jaxrs
18 |
19 |
20 |
21 |
22 | org.eclipse.microprofile.samples12
23 | test-utils
24 | ${project.version}
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/metrics/application-metrics/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4.0.0
5 |
6 |
7 | org.eclipse.microprofile.samples12
8 | metrics
9 | 1.0-SNAPSHOT
10 |
11 |
12 | application-metrics
13 | war
14 | MicroProfile 1.2: Metrics - Application Metrics
15 |
16 |
17 |
--------------------------------------------------------------------------------
/metrics/application-metrics/src/main/java/org/eclipse/microprofile12/metrics/application/ApplicationInit.java:
--------------------------------------------------------------------------------
1 | /** Copyright Payara Services Limited **/
2 |
3 | package org.eclipse.microprofile12.metrics.application;
4 |
5 | import javax.ws.rs.ApplicationPath;
6 | import javax.ws.rs.core.Application;
7 |
8 | /**
9 | * @author Gaurav Gupta
10 | */
11 | @ApplicationPath("/")
12 | public class ApplicationInit extends Application {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/metrics/application-metrics/src/main/java/org/eclipse/microprofile12/metrics/application/UserResource.java:
--------------------------------------------------------------------------------
1 | /** Copyright Payara Services Limited **/
2 |
3 | package org.eclipse.microprofile12.metrics.application;
4 |
5 | import static java.util.Arrays.asList;
6 | import java.util.List;
7 | import javax.enterprise.context.ApplicationScoped;
8 | import javax.ws.rs.GET;
9 | import javax.ws.rs.Path;
10 | import javax.ws.rs.core.Response;
11 | import org.eclipse.microprofile.metrics.MetricUnits;
12 | import org.eclipse.microprofile.metrics.annotation.Counted;
13 | import org.eclipse.microprofile.metrics.annotation.Gauge;
14 |
15 | /**
16 | * @author Gaurav Gupta
17 | */
18 | @ApplicationScoped
19 | @Path("/user")
20 | public class UserResource {
21 |
22 | private final List users = asList("Arjan", "Gaurav", "Mert", "Mike", "Ondrej");
23 |
24 | @GET
25 | @Path("/all")
26 | @Counted(monotonic = true)
27 | public Response getUsers() {
28 | return Response
29 | .ok(users)
30 | .build();
31 | }
32 |
33 | @GET
34 | @Path("/count")
35 | @Gauge(unit = MetricUnits.NONE)
36 | public int getUserCount() {
37 | return users.size();
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/metrics/application-metrics/src/test/java/org/eclipse/microprofile12/metrics/application/ApplicationMetricsTest.java:
--------------------------------------------------------------------------------
1 | /** Copyright Payara Services Limited **/
2 |
3 | package org.eclipse.microprofile12.metrics.application;
4 |
5 | import static javax.ws.rs.client.ClientBuilder.newClient;
6 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
7 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
8 | import static org.junit.Assert.assertTrue;
9 | import java.io.IOException;
10 | import java.io.StringReader;
11 | import java.net.URI;
12 | import java.net.URL;
13 | import javax.json.Json;
14 | import javax.json.JsonObject;
15 | import javax.json.JsonReader;
16 | import javax.ws.rs.client.WebTarget;
17 | import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
18 | import javax.ws.rs.core.Response;
19 | import org.jboss.arquillian.container.test.api.Deployment;
20 | import org.jboss.arquillian.container.test.api.RunAsClient;
21 | import org.jboss.arquillian.junit.Arquillian;
22 | import org.jboss.arquillian.junit.InSequence;
23 | import org.jboss.arquillian.test.api.ArquillianResource;
24 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
25 | import org.jboss.shrinkwrap.api.spec.WebArchive;
26 | import static org.junit.Assert.assertEquals;
27 | import org.junit.Before;
28 | import org.junit.Test;
29 | import org.junit.runner.RunWith;
30 |
31 | /**
32 | * @author Gaurav Gupta
33 | */
34 | @RunWith(Arquillian.class)
35 | public class ApplicationMetricsTest {
36 |
37 | @ArquillianResource
38 | private URL base;
39 |
40 | @Deployment(testable = false)
41 | public static WebArchive createDeployment() {
42 | WebArchive archive
43 | = create(WebArchive.class)
44 | .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
45 | .addClass(ApplicationInit.class)
46 | .addClass(UserResource.class);
47 |
48 | System.out.println("************************************************************");
49 | System.out.println(archive.toString(true));
50 | System.out.println("************************************************************");
51 |
52 | return archive;
53 | }
54 |
55 | @Before
56 | public void init() throws IOException{
57 | invokeUserResource();
58 | }
59 |
60 | @Test
61 | @InSequence(1)
62 | @RunAsClient
63 | public void testBasePrometheusMetrics() throws IOException {
64 | Response response
65 | = getApplicationMetricTarget()
66 | .request(TEXT_PLAIN)
67 | .get();
68 | String responseText = response.readEntity(String.class);
69 | System.out.println("testBasePrometheusMetrics " + responseText);
70 | assertTrue(responseText.contains("# TYPE application:org_eclipse_microprofile12_metrics_application_user_resource_get_users counter")
71 | || responseText.contains("# TYPE application_org_eclipse_microprofile12_metrics_application_UserResource_getUsers_total counter"));
72 | assertTrue(responseText.contains("# TYPE application:org_eclipse_microprofile12_metrics_application_user_resource_get_user_count gauge")
73 | || responseText.contains("# TYPE application_org_eclipse_microprofile12_metrics_application_UserResource_getUserCount gauge"));
74 | }
75 |
76 | @Test
77 | @InSequence(2)
78 | @RunAsClient
79 | public void testBaseJsonMetrics() throws IOException {
80 | Response response
81 | = getApplicationMetricTarget()
82 | .request(APPLICATION_JSON)
83 | .get();
84 | JsonObject jsonObject = Json
85 | .createReader(new StringReader(response.readEntity(String.class)))
86 | .readObject();
87 |
88 | assertEquals(jsonObject.getInt("org.eclipse.microprofile12.metrics.application.UserResource.getUsers"), 2);
89 | assertEquals(jsonObject.getInt("org.eclipse.microprofile12.metrics.application.UserResource.getUserCount"), 5);
90 | }
91 |
92 | private WebTarget getApplicationMetricTarget() throws IOException {
93 | return newClient().target(URI.create(new URL(base, "/metrics/application").toExternalForm()));
94 | }
95 |
96 | private void invokeUserResource() throws IOException{
97 | //invoke UserResource.getUsers
98 | newClient()
99 | .target(URI.create(new URL(base, "user/all").toExternalForm()))
100 | .request(APPLICATION_JSON)
101 | .get();
102 |
103 | //invoke UserResource.getUserCount
104 | newClient()
105 | .target(URI.create(new URL(base, "user/count").toExternalForm()))
106 | .request(APPLICATION_JSON)
107 | .get();
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/metrics/base-metrics/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4.0.0
5 |
6 |
7 | org.eclipse.microprofile.samples12
8 | metrics
9 | 1.0-SNAPSHOT
10 |
11 |
12 | base-metrics
13 | war
14 | MicroProfile 1.2: Metrics - Base Metrics
15 |
16 |
17 |
--------------------------------------------------------------------------------
/metrics/base-metrics/src/test/java/org/eclipse/microprofile12/metrics/base/BaseMetricsTest.java:
--------------------------------------------------------------------------------
1 | /** Copyright Payara Services Limited **/
2 |
3 | package org.eclipse.microprofile12.metrics.base;
4 |
5 | import static javax.ws.rs.client.ClientBuilder.newClient;
6 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
7 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
8 | import static org.junit.Assert.assertTrue;
9 | import java.io.IOException;
10 | import java.io.StringReader;
11 | import java.net.MalformedURLException;
12 | import java.net.URI;
13 | import java.net.URL;
14 | import javax.json.Json;
15 | import javax.json.JsonObject;
16 | import javax.ws.rs.client.WebTarget;
17 | import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
18 | import javax.ws.rs.core.Response;
19 | import org.jboss.arquillian.container.test.api.Deployment;
20 | import org.jboss.arquillian.container.test.api.RunAsClient;
21 | import org.jboss.arquillian.junit.Arquillian;
22 | import org.jboss.arquillian.test.api.ArquillianResource;
23 | import org.jboss.shrinkwrap.api.asset.EmptyAsset;
24 | import org.jboss.shrinkwrap.api.spec.WebArchive;
25 | import org.junit.Test;
26 | import org.junit.runner.RunWith;
27 |
28 | /**
29 | * @author Gaurav Gupta
30 | */
31 | @RunWith(Arquillian.class)
32 | public class BaseMetricsTest {
33 |
34 | @ArquillianResource
35 | private URL base;
36 |
37 | @Deployment(testable = false)
38 | public static WebArchive createDeployment() {
39 | WebArchive archive
40 | = create(WebArchive.class)
41 | .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
42 |
43 | System.out.println("************************************************************");
44 | System.out.println(archive.toString(true));
45 | System.out.println("************************************************************");
46 |
47 | return archive;
48 | }
49 |
50 | @Test
51 | @RunAsClient
52 | public void testBasePrometheusMetrics() throws IOException {
53 | Response response
54 | = getBaseMetricTarget()
55 | .request(TEXT_PLAIN)
56 | .get();
57 | String responseText = response.readEntity(String.class);
58 | assertTrue(responseText.contains("# TYPE base:thread_max_count")
59 | || responseText.contains("# TYPE base_thread_max_count"));
60 | assertTrue(responseText.contains("# TYPE base:thread_count")
61 | || responseText.contains("# TYPE base_thread_count"));
62 | assertTrue(responseText.contains("# TYPE base:cpu_system_load_average")
63 | || responseText.contains("# TYPE base_cpu_systemLoadAverage"));
64 | assertTrue(responseText.contains("# TYPE base:jvm_uptime")
65 | || responseText.contains("# TYPE base_jvm_uptime_seconds"));
66 | }
67 |
68 | @Test
69 | @RunAsClient
70 | public void testBaseJsonMetrics() throws IOException {
71 | Response response
72 | = getBaseMetricTarget()
73 | .request(APPLICATION_JSON)
74 | .get();
75 | JsonObject jsonObject = Json
76 | .createReader(new StringReader(response.readEntity(String.class)))
77 | .readObject();
78 | assertTrue(jsonObject.containsKey("thread.max.count"));
79 | assertTrue(jsonObject.containsKey("thread.count"));
80 | assertTrue(jsonObject.containsKey("cpu.systemLoadAverage"));
81 | assertTrue(jsonObject.containsKey("jvm.uptime"));
82 | }
83 |
84 | private WebTarget getBaseMetricTarget() throws MalformedURLException {
85 | return newClient().target(URI.create(new URL(base, "/metrics/base").toExternalForm()));
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/metrics/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4.0.0
5 |
6 |
7 | org.eclipse.microprofile.samples12
8 | samples-parent
9 | 1.0-SNAPSHOT
10 |
11 |
12 | metrics
13 | pom
14 |
15 | MicroProfile 1.2: Metrics
16 |
17 |
18 | base-metrics
19 | application-metrics
20 |
21 |
22 |
23 |
24 | org.eclipse.microprofile.samples12
25 | test-utils
26 | ${project.version}
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 | 4.0.0
8 |
9 |
10 | 3.5
11 |
12 |
13 | org.eclipse.microprofile.samples12
14 | samples-parent
15 | 1.0-SNAPSHOT
16 | pom
17 |
18 | Eclipse MicroProfile 1.2 Samples: root
19 |
20 |
21 | 1.8
22 | 3.5
23 | UTF-8
24 |
25 | false
26 | false
27 |
28 | ${skipTests}
29 | ${skipTests}
30 | ${skipTests}
31 | ${skipTests}
32 |
33 |
35 | 5.182-SNAPSHOT
36 | 5.182-SNAPSHOT
37 | 17.0.0.4
38 | 2.3.0.Final
39 |
40 | 1.0.Beta3
41 | 5.Beta3-m3
42 |
43 |
44 |
45 |
46 | central
47 | Central Repository
48 |
49 | https://repo.maven.apache.org/maven2
50 |
51 |
52 | true
53 |
54 |
55 | false
56 |
57 |
58 |
59 |
60 | payara-milestones
61 | Payara Milestones
62 | https://raw.github.com/payara/Payara_PatchedProjects/master
63 |
64 | true
65 |
66 |
67 | false
68 |
69 |
70 |
71 |
72 | ossrh
73 | Sonatype-snapshot
74 | https://oss.sonatype.org/content/repositories/snapshots
75 |
76 | false
77 |
78 |
79 | true
80 |
81 |
82 |
83 |
84 | jvnet-nexus-staging
85 | Java.net Staging Repositories
86 | https://maven.java.net/content/repositories/staging
87 |
88 | true
89 |
90 |
91 | false
92 |
93 |
94 |
95 |
96 |
97 |
98 |
100 |
101 | config
102 | fault-tolerance
103 | jwt-auth
104 | metrics
105 | test-utils
106 |
107 |
108 |
109 |
110 |
111 | org.jboss.arquillian
112 | arquillian-bom
113 | 1.4.0.Final
114 | import
115 | pom
116 |
117 |
118 | org.jboss.arquillian.container
119 | arquillian-container-test-api
120 | 1.4.0.Final
121 |
122 |
123 | com.h2database
124 | h2
125 | 1.4.197
126 |
127 |
128 | fish.payara.arquillian
129 | payara-client-ee7
130 | 1.0.Beta3-m3
131 | test
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | javax
140 | javaee-api
141 | 7.0
142 | provided
143 |
144 |
145 |
146 | org.eclipse.microprofile.config
147 | microprofile-config-api
148 | 1.1
149 | provided
150 |
151 |
152 | org.eclipse.microprofile.fault-tolerance
153 | microprofile-fault-tolerance-api
154 | 1.0
155 | provided
156 |
157 |
158 | org.eclipse.microprofile.jwt
159 | microprofile-jwt-auth-api
160 | 1.0
161 | provided
162 |
163 |
164 | org.eclipse.microprofile.metrics
165 | microprofile-metrics-api
166 | 1.0
167 | provided
168 |
169 |
170 |
171 |
172 |
173 | junit
174 | junit
175 | 4.13.1
176 | test
177 |
178 |
179 | org.hamcrest
180 | hamcrest-core
181 | 1.3
182 | test
183 |
184 |
185 | org.hamcrest
186 | hamcrest-library
187 | 1.3
188 | test
189 |
190 |
191 | org.jboss.arquillian.junit
192 | arquillian-junit-container
193 | test
194 |
195 |
196 | org.jboss.arquillian.protocol
197 | arquillian-protocol-servlet
198 | test
199 |
200 |
201 | org.jboss.shrinkwrap.resolver
202 | shrinkwrap-resolver-impl-maven
203 | test
204 | jar
205 |
206 |
207 | org.jboss.shrinkwrap.resolver
208 | shrinkwrap-resolver-impl-maven-archive
209 | test
210 |
211 |
212 | xmlunit
213 | xmlunit
214 | 1.6
215 | test
216 |
217 |
218 | org.skyscreamer
219 | jsonassert
220 | 1.5.0
221 | test
222 |
223 |
224 | net.sourceforge.htmlunit
225 | htmlunit
226 | 2.30
227 | test
228 |
229 |
230 | rhino
231 | js
232 | 1.7R2
233 | test
234 |
235 |
236 | org.json
237 | json
238 | 20180130
239 | test
240 |
241 |
242 | com.jayway.awaitility
243 | awaitility
244 | 1.7.0
245 | test
246 |
247 |
248 |
249 |
250 |
251 | ${project.artifactId}
252 |
253 |
254 |
255 | src/test/resources
256 | true
257 |
258 |
259 |
260 |
261 |
262 | org.apache.maven.plugins
263 | maven-compiler-plugin
264 | 3.7.0
265 |
266 | ${java.min.version}
267 | ${java.min.version}
268 |
269 |
270 |
271 | org.apache.maven.plugins
272 | maven-surefire-report-plugin
273 | 2.21.0
274 |
275 | true
276 | true
277 |
278 |
279 |
280 | org.apache.maven.plugins
281 | maven-surefire-plugin
282 | 2.21.0
283 |
284 |
285 | javax.annotation
286 | javax.annotation-api
287 | 1.3.2
288 |
289 |
290 |
291 |
292 | org.apache.maven.plugins
293 | maven-war-plugin
294 | 3.2.0
295 |
296 | true
297 | false
298 |
299 |
300 |
301 | org.apache.maven.plugins
302 | maven-enforcer-plugin
303 | 3.0.0-M1
304 |
305 |
306 |
307 | At least Maven in version
308 | ${maven.min.version} is
309 | required.
310 | ${maven.min.version}
311 |
312 |
313 | At least a JDK in version
314 | ${java.min.version} is
315 | required.
316 | ${java.min.version}
317 |
318 |
319 |
320 |
321 |
322 |
323 | enforce
324 |
325 |
326 |
327 |
328 |
329 | org.apache.maven.plugins
330 | maven-dependency-plugin
331 | 3.1.0
332 |
333 |
334 | org.apache.maven.plugins
335 | maven-resources-plugin
336 | 3.0.2
337 |
338 |
339 | org.wildfly.plugins
340 | wildfly-maven-plugin
341 | 1.2.1.Final
342 |
343 |
344 |
345 |
346 |
347 |
348 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 | payara-ci-managed
359 |
360 |
361 | true
362 |
363 |
364 |
365 |
366 | fish.payara.arquillian
367 | payara-client-ee7
368 |
369 |
370 |
371 |
372 | fish.payara.arquillian
373 | arquillian-payara-server-4-managed
374 | ${payara.container.version}
375 | test
376 |
377 |
378 |
379 |
380 |
381 |
382 | org.apache.maven.plugins
383 | maven-dependency-plugin
384 |
385 |
386 | unpack
387 | process-test-classes
388 |
389 | unpack
390 |
391 |
392 | ${session.executionRootDirectory}/target
393 | ${session.executionRootDirectory}/target/dependency-maven-plugin-markers
394 |
395 |
396 | fish.payara.distributions
397 | payara-web
398 | ${payara.version}
399 | zip
400 | false
401 | ${session.executionRootDirectory}/target
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 | org.apache.maven.plugins
410 | maven-surefire-plugin
411 |
412 |
413 |
414 | javax.annotation
415 | javax.annotation-api
416 | 1.3.1
417 |
418 |
419 |
420 | ${session.executionRootDirectory}/target/payara5
421 |
422 |
423 |
424 | ${session.executionRootDirectory}/target/payara5
425 | payara-remote
426 | payara
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 | payara-micro-managed
436 |
437 |
438 | true
439 | true
440 |
441 |
442 |
443 |
445 |
446 | fish.payara.arquillian
447 | payara-client-ee7
448 |
449 |
450 |
451 |
452 | fish.payara.arquillian
453 | arquillian-payara-micro-5-managed
454 | ${payara.container.version}
455 | test
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 | org.apache.maven.plugins
464 | maven-dependency-plugin
465 |
466 |
467 | process-test-classes
468 |
469 | copy
470 |
471 |
472 |
473 |
474 | fish.payara.extras
475 | payara-micro
476 | ${payara.micro.version}
477 | false
478 | ${session.executionRootDirectory}/target/
479 | payara-micro-${payara.micro.version}.jar
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 | maven-surefire-plugin
489 |
490 |
491 | ${session.executionRootDirectory}/target/payara-micro-${payara.micro.version}.jar
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 | payara-remote
501 |
502 |
503 |
504 | fish.payara.arquillian
505 | payara-client-ee7
506 |
507 |
508 |
509 |
510 | fish.payara.arquillian
511 | arquillian-payara-server-4-remote
512 | ${payara.container.version}
513 | test
514 |
515 |
516 |
517 |
518 |
519 | maven-surefire-plugin
520 |
521 |
522 | payara-remote
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 | liberty-ci-managed
536 |
537 |
538 |
539 | fish.payara.arquillian
540 | payara-client-ee7
541 |
542 |
543 |
544 | org.jboss.arquillian.container
545 | arquillian-wlp-managed-8.5
546 | 1.0.0.CR1
547 | test
548 |
549 |
550 |
551 |
552 |
553 |
554 | org.apache.maven.plugins
555 | maven-dependency-plugin
556 |
557 |
558 | unpack
559 | test-compile
560 |
561 | unpack
562 |
563 |
564 |
565 |
566 |
567 | io.openliberty
568 | openliberty-runtime
569 | ${liberty.version}
570 |
571 |
572 |
574 | zip
575 | false
576 | ${session.executionRootDirectory}/target/
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 | org.apache.maven.plugins
585 | maven-antrun-plugin
586 | 1.8
587 |
588 |
589 | unpack
590 | process-test-classes
591 |
592 | run
593 |
594 |
595 |
596 |
598 | Copying server.xml
599 |
602 | Copying key.jks
603 |
605 |
608 |
609 |
610 |
611 |
612 |
613 |
614 | org.apache.maven.plugins
615 | maven-surefire-plugin
616 |
617 |
618 | liberty-ci-managed
619 |
620 | ${session.executionRootDirectory}/target/wlp
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 | thorntail
634 |
635 |
636 |
637 |
638 | io.thorntail
639 | bom
640 | ${thorntail.version}
641 | import
642 | pom
643 |
644 |
645 |
646 |
647 |
648 |
649 |
651 |
652 | io.thorntail
653 | arquillian
654 | test
655 |
656 |
657 | io.thorntail
658 | microprofile
659 |
660 |
661 |
662 |
663 |
664 |
665 | maven-surefire-plugin
666 |
667 |
668 |
669 |
670 | arquillian-thorntail.xml
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 | nothing
680 |
681 |
682 |
685 |
686 | javadocs
687 |
688 |
689 | javadocs
690 |
691 |
692 |
693 |
694 |
695 | org.apache.maven.plugins
696 | maven-dependency-plugin
697 | 2.4
698 |
699 |
700 | sources
701 | process-resources
702 |
703 | sources
704 | resolve
705 |
706 |
707 | javadoc
708 | false
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 | org.apache.maven.plugins
722 | maven-surefire-report-plugin
723 | 2.19.1
724 |
725 | true
726 | true
727 |
728 |
729 |
730 |
731 |
732 |
733 |
--------------------------------------------------------------------------------
/test-utils/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | org.eclipse.microprofile.samples12
8 | samples-parent
9 | 1.0-SNAPSHOT
10 |
11 |
12 | test-utils
13 | MicroProfile 1.2: test-utils
14 |
15 |
16 |
17 | junit
18 | junit
19 | 4.13.1
20 |
21 |
22 | org.jboss.arquillian.container
23 | arquillian-container-test-api
24 |
25 |
26 | org.jboss.shrinkwrap.resolver
27 | shrinkwrap-resolver-api-maven
28 |
29 |
30 | com.nimbusds
31 | nimbus-jose-jwt
32 | 5.1
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/test-utils/src/main/java/org/eclipse/microprofile12/CliCommands.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12;
2 |
3 | import static java.lang.Runtime.getRuntime;
4 | import static java.lang.Thread.currentThread;
5 |
6 | import java.io.IOException;
7 | import java.nio.file.Path;
8 | import java.nio.file.Paths;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 | import java.util.Scanner;
12 | import java.util.logging.Logger;
13 |
14 | /**
15 | * Methods to execute "cli commands" against various servers.
16 | *
17 | * @author Arjan Tijms
18 | *
19 | */
20 | public class CliCommands {
21 |
22 | private static final Logger logger = Logger.getLogger(CliCommands.class.getName());
23 | private static final String OS = System.getProperty("os.name").toLowerCase();
24 |
25 | public static int payaraGlassFish(List cliCommands) {
26 |
27 | String gfHome = System.getProperty("glassfishRemote_gfHome");
28 | if (gfHome == null) {
29 | logger.info("glassfishRemote_gfHome not specified");
30 | return -1;
31 | }
32 |
33 | Path gfHomePath = Paths.get(gfHome);
34 | if (!gfHomePath.toFile().exists()) {
35 | logger.severe("glassfishRemote_gfHome at " + gfHome + " does not exists");
36 | return -1;
37 | }
38 |
39 | if (!gfHomePath.toFile().isDirectory()) {
40 | logger.severe("glassfishRemote_gfHome at " + gfHome + " is not a directory");
41 | return -1;
42 | }
43 |
44 | Path asadminPath = gfHomePath.resolve(isWindows()? "bin/asadmin.bat" : "bin/asadmin");
45 |
46 | if (!asadminPath.toFile().exists()) {
47 | logger.severe("asadmin command at " + asadminPath.toAbsolutePath() + " does not exists");
48 | return -1;
49 | }
50 |
51 | List cmd = new ArrayList<>();
52 |
53 | cmd.add(asadminPath.toAbsolutePath().toString());
54 | cmd.addAll(cliCommands);
55 |
56 | ProcessBuilder processBuilder = new ProcessBuilder(cmd);
57 | processBuilder.redirectErrorStream(true);
58 |
59 | try {
60 | return
61 | waitToFinish(
62 | readAllInput(
63 | destroyAtShutDown(
64 | processBuilder.start())));
65 | } catch (IOException e) {
66 | return -1;
67 | }
68 | }
69 |
70 | public static Process destroyAtShutDown(final Process process) {
71 | getRuntime().addShutdownHook(new Thread(new Runnable() {
72 | @Override
73 | public void run() {
74 | if (process != null) {
75 | process.destroy();
76 | try {
77 | process.waitFor();
78 | } catch (InterruptedException e) {
79 | currentThread().interrupt();
80 | throw new RuntimeException(e);
81 | }
82 | }
83 | }
84 | }));
85 |
86 | return process;
87 | }
88 |
89 | public static Process readAllInput(Process process) {
90 | // Read any output from the process
91 | try (Scanner scanner = new Scanner(process.getInputStream())) {
92 | while (scanner.hasNextLine()) {
93 | System.out.println(scanner.nextLine());
94 | }
95 | }
96 |
97 | return process;
98 | }
99 |
100 | public static int waitToFinish(Process process) {
101 |
102 | // Wait up to 30s for the process to finish
103 | int startupTimeout = 30 * 1000;
104 | while (startupTimeout > 0) {
105 | startupTimeout -= 200;
106 | try {
107 | Thread.sleep(200);
108 | } catch (InterruptedException e1) {
109 | // Ignore
110 | }
111 |
112 | try {
113 | int exitValue = process.exitValue();
114 |
115 | System.out.println("Asadmin process exited with status " + exitValue);
116 | return exitValue;
117 |
118 | } catch (IllegalThreadStateException e) {
119 | // process is still running
120 | }
121 | }
122 |
123 | throw new IllegalStateException("Asadmin process seems stuck after waiting for 30 seconds");
124 | }
125 |
126 | public static boolean isWindows() {
127 | return OS.contains("win");
128 | }
129 |
130 | }
131 |
--------------------------------------------------------------------------------
/test-utils/src/main/java/org/eclipse/microprofile12/JwtTokenGenerator.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12;
2 |
3 | import static com.nimbusds.jose.JOSEObjectType.JWT;
4 | import static com.nimbusds.jose.JWSAlgorithm.RS256;
5 | import static com.nimbusds.jwt.JWTClaimsSet.parse;
6 | import static java.lang.Thread.currentThread;
7 | import static net.minidev.json.parser.JSONParser.DEFAULT_PERMISSIVE_MODE;
8 |
9 | import java.security.KeyFactory;
10 | import java.security.PrivateKey;
11 | import java.security.spec.PKCS8EncodedKeySpec;
12 | import java.util.Base64;
13 |
14 | import org.eclipse.microprofile.jwt.Claims;
15 |
16 | import com.nimbusds.jose.JWSHeader;
17 | import com.nimbusds.jose.crypto.RSASSASigner;
18 | import com.nimbusds.jwt.SignedJWT;
19 |
20 | import net.minidev.json.JSONObject;
21 | import net.minidev.json.parser.JSONParser;
22 |
23 | public class JwtTokenGenerator {
24 |
25 | public static String generateJWTString(String jsonResource) throws Exception {
26 | byte[] byteBuffer = new byte[16384];
27 | currentThread().getContextClassLoader()
28 | .getResource(jsonResource)
29 | .openStream()
30 | .read(byteBuffer);
31 |
32 | JSONParser parser = new JSONParser(DEFAULT_PERMISSIVE_MODE);
33 | JSONObject jwtJson = (JSONObject) parser.parse(byteBuffer);
34 |
35 | long currentTimeInSecs = (System.currentTimeMillis() / 1000);
36 | long expirationTime = currentTimeInSecs + 1000;
37 |
38 | jwtJson.put(Claims.iat.name(), currentTimeInSecs);
39 | jwtJson.put(Claims.auth_time.name(), currentTimeInSecs);
40 | jwtJson.put(Claims.exp.name(), expirationTime);
41 |
42 | SignedJWT signedJWT = new SignedJWT(new JWSHeader
43 | .Builder(RS256)
44 | .keyID("/privateKey.pem")
45 | .type(JWT)
46 | .build(), parse(jwtJson));
47 |
48 | signedJWT.sign(new RSASSASigner(readPrivateKey("privateKey.pem")));
49 |
50 | return signedJWT.serialize();
51 | }
52 |
53 | public static PrivateKey readPrivateKey(String resourceName) throws Exception {
54 | byte[] byteBuffer = new byte[16384];
55 | int length = currentThread().getContextClassLoader()
56 | .getResource(resourceName)
57 | .openStream()
58 | .read(byteBuffer);
59 |
60 | String key = new String(byteBuffer, 0, length).replaceAll("-----BEGIN (.*)-----", "")
61 | .replaceAll("-----END (.*)----", "")
62 | .replaceAll("\r\n", "")
63 | .replaceAll("\n", "")
64 | .trim();
65 |
66 | return KeyFactory.getInstance("RSA")
67 | .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(key)));
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/test-utils/src/main/java/org/eclipse/microprofile12/Libraries.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12;
2 |
3 | import org.jboss.shrinkwrap.api.spec.JavaArchive;
4 | import org.jboss.shrinkwrap.resolver.api.maven.Maven;
5 |
6 | public class Libraries {
7 |
8 | public static JavaArchive[] awaitability() {
9 | return Maven.resolver()
10 | .loadPomFromFile("pom.xml")
11 | .resolve("com.jayway.awaitility:awaitility")
12 | .withTransitivity()
13 | .as(JavaArchive.class);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/test-utils/src/main/java/org/eclipse/microprofile12/Parameter.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Target({ElementType.FIELD})
10 | public @interface Parameter {
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/test-utils/src/main/java/org/eclipse/microprofile12/ParameterRule.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12;
2 |
3 | import org.jboss.arquillian.container.test.api.Deployment;
4 |
5 | import org.junit.rules.MethodRule;
6 | import org.junit.runners.model.FrameworkMethod;
7 | import org.junit.runners.model.Statement;
8 |
9 | import javax.naming.InitialContext;
10 | import javax.naming.NamingException;
11 | import java.lang.reflect.Field;
12 | import java.lang.reflect.Method;
13 | import java.util.List;
14 |
15 | /**
16 | * Helper class for Parametrized tests as described here:
17 | * http://blog.schauderhaft.de/2012/12/16/writing-parameterized-tests-with-junit-rules/
18 | *
19 | * @param
20 | */
21 | public class ParameterRule implements MethodRule {
22 | private final List params;
23 |
24 | public ParameterRule(List params) {
25 | if (params == null || params.size() == 0) {
26 | throw new IllegalArgumentException("'params' must be specified and have more then zero length!");
27 | }
28 | this.params = params;
29 | }
30 |
31 | @Override
32 | public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
33 | return new Statement() {
34 | @Override
35 | public void evaluate() throws Throwable {
36 | boolean runInContainer = getDeploymentMethod(target).getAnnotation(Deployment.class).testable();
37 | if (runInContainer) {
38 | evaluateParametersInContainer(base, target);
39 | } else {
40 | evaluateParametersInClient(base, target);
41 | }
42 | }
43 | };
44 | }
45 |
46 | private Method getDeploymentMethod(Object target) throws NoSuchMethodException {
47 | Method[] methods = target.getClass().getDeclaredMethods();
48 | for (Method method : methods) {
49 | if (method.getAnnotation(Deployment.class) != null) return method;
50 | }
51 | throw new IllegalStateException("No method with @Deployment annotation found!");
52 | }
53 |
54 | private void evaluateParametersInContainer(Statement base, Object target) throws Throwable {
55 | if (isRunningInContainer()) {
56 | evaluateParamsToTarget(base, target);
57 | } else {
58 | ignoreStatementExecution(base);
59 | }
60 | }
61 |
62 | private void evaluateParametersInClient(Statement base, Object target) throws Throwable {
63 | if (isRunningInContainer()) {
64 | ignoreStatementExecution(base);
65 | } else {
66 | evaluateParamsToTarget(base, target);
67 | }
68 | }
69 |
70 | private boolean isRunningInContainer() {
71 | try {
72 | new InitialContext().lookup("java:comp/env");
73 | return true;
74 | } catch (NamingException e) {
75 | return false;
76 | }
77 | }
78 |
79 | private void evaluateParamsToTarget(Statement base, Object target) throws Throwable {
80 | for (Object param : params) {
81 | Field targetField = getTargetField(target);
82 | if (!targetField.isAccessible()) {
83 | targetField.setAccessible(true);
84 | }
85 | targetField.set(target, param);
86 | base.evaluate();
87 | }
88 | }
89 |
90 | private Field getTargetField(Object target) throws NoSuchFieldException {
91 | Field[] allFields = target.getClass().getDeclaredFields();
92 | for (Field field : allFields) {
93 | if (field.getAnnotation(Parameter.class) != null) return field;
94 | }
95 | throw new IllegalStateException("No field with @Parameter annotation found! Forgot to add it?");
96 | }
97 |
98 | private void ignoreStatementExecution(Statement base) {
99 | try {
100 | base.evaluate();
101 | } catch (Throwable ignored) {}
102 | }
103 | }
--------------------------------------------------------------------------------
/test-utils/src/main/java/org/eclipse/microprofile12/ServerOperations.java:
--------------------------------------------------------------------------------
1 | package org.eclipse.microprofile12;
2 |
3 | import java.nio.file.Paths;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | /**
8 | * Various high level Java EE 7 samples specific operations to execute against
9 | * the various servers used for running the samples
10 | *
11 | * @author arjan
12 | *
13 | */
14 | public class ServerOperations {
15 |
16 | /**
17 | * Add the default test user and credentials to the identity store of
18 | * supported containers
19 | */
20 | public static void addUsersToContainerIdentityStore() {
21 |
22 | // TODO: abstract adding container managed users to utility class
23 | // TODO: consider PR for sending CLI commands to Arquillian
24 |
25 | String javaEEServer = System.getProperty("javaEEServer");
26 |
27 | if ("glassfish-remote".equals(javaEEServer) || "payara-remote".equals(javaEEServer)) {
28 |
29 | System.out.println("Adding user for glassfish-remote");
30 |
31 | List cmd = new ArrayList<>();
32 |
33 | cmd.add("create-file-user");
34 | cmd.add("--groups");
35 | cmd.add("g1");
36 | cmd.add("--passwordfile");
37 | cmd.add(Paths.get("").toAbsolutePath() + "/src/test/resources/password.txt");
38 |
39 | cmd.add("u1");
40 |
41 | CliCommands.payaraGlassFish(cmd);
42 | } else {
43 | if (javaEEServer == null) {
44 | System.out.println("javaEEServer not specified");
45 | } else {
46 | System.out.println(javaEEServer + " not supported");
47 | }
48 | }
49 |
50 | // TODO: support other servers than Payara and GlassFish
51 |
52 | // WildFly ./bin/add-user.sh -a -u u1 -p p1 -g g1
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/test-utils/src/main/resources/arquillian-thorntail.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
11 |
12 |
13 | localhost
14 | ${thorntail.arquillian.daemon.port:12345}
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/test-utils/src/main/resources/arquillian.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 | production
11 |
12 |
13 |
14 |
15 |
16 | xml
17 | ${arquillian.liberty.wlpHome}
18 |
19 |
20 |
21 |
22 |
23 | xml
24 | ${arquillian.liberty.wlpHome}
25 | -Dwas.debug.mode=true -Dcom.ibm.websphere.ras.inject.at.transform=true -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/test-utils/src/main/resources/key.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/javaee-samples/microprofile1.2-samples/ea5b9f0d6a17d8eab847d6cb9e2dd2e07a71e90a/test-utils/src/main/resources/key.jks
--------------------------------------------------------------------------------
/test-utils/src/main/resources/logging.properties:
--------------------------------------------------------------------------------
1 | handlers= java.util.logging.ConsoleHandler
2 | java.util.logging.ConsoleHandler.level = FINER
3 |
4 | org.jboss.arquillian.container.was.wlp_managed_8_5.WLPManagedContainer.level=FINER
--------------------------------------------------------------------------------
/test-utils/src/main/resources/server.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | microProfile-1.2
7 | localConnector-1.0
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------