├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── jwt-auth ├── README.md ├── basic-authentication │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── org │ │ │ │ └── eclipse │ │ │ │ └── microprofile14 │ │ │ │ └── jwtauth │ │ │ │ └── basic │ │ │ │ ├── ApplicationInit.java │ │ │ │ └── Servlet.java │ │ └── resources │ │ │ ├── META-INF │ │ │ ├── microprofile-config.properties │ │ │ └── public-key.pem │ │ │ └── project-defaults.yml │ │ └── test │ │ ├── etc │ │ └── alt-public-key.pem │ │ ├── java │ │ └── org │ │ │ └── eclipse │ │ │ └── microprofile14 │ │ │ └── jwtauth │ │ │ └── basic │ │ │ ├── BasicAuthenticationAltLocationTest.java │ │ │ └── BasicAuthenticationTest.java │ │ └── resources │ │ ├── jwt-token.json │ │ └── privateKey.pem ├── jaxrs │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── org │ │ │ │ └── eclipse │ │ │ │ └── microprofile14 │ │ │ │ └── jwtauth │ │ │ │ └── jaxrs │ │ │ │ ├── ApplicationInit.java │ │ │ │ └── Resource.java │ │ └── resources │ │ │ ├── META-INF │ │ │ ├── microprofile-config.properties │ │ │ └── public-key.pem │ │ │ └── project-defaults.yml │ │ └── test │ │ ├── java │ │ └── org │ │ │ └── eclipse │ │ │ └── microprofile14 │ │ │ └── jwtauth │ │ │ └── jaxrs │ │ │ └── JaxRsTest.java │ │ └── resources │ │ ├── jwt-token.json │ │ └── privateKey.pem └── pom.xml ├── open-api ├── README.md ├── basic-hello │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── org │ │ │ │ └── eclipse │ │ │ │ └── microprofile14 │ │ │ │ └── openapi │ │ │ │ └── basichello │ │ │ │ ├── ApplicationInit.java │ │ │ │ ├── HelloModelReader.java │ │ │ │ ├── HelloResource.java │ │ │ │ └── OperationHyphenFilter.java │ │ └── resources │ │ │ └── META-INF │ │ │ └── microprofile-config.properties │ │ └── test │ │ └── java │ │ └── org │ │ └── eclipse │ │ └── microprofile14 │ │ └── openapi │ │ └── basichello │ │ └── BasicHelloTest.java └── pom.xml ├── pom.xml ├── rest-client ├── README.md ├── client-server-async │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── org │ │ │ └── eclipse │ │ │ └── microprofile14 │ │ │ └── restclient │ │ │ └── clientserver │ │ │ ├── config │ │ │ └── ApplicationInit.java │ │ │ └── remote │ │ │ └── HelloRemoteResource.java │ │ └── test │ │ └── java │ │ └── org │ │ └── eclipse │ │ └── microprofile14 │ │ └── restclient │ │ └── clientserver │ │ ├── ClientServerAsyncTest.java │ │ └── client │ │ └── HelloService.java ├── client-server │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── org │ │ │ └── eclipse │ │ │ └── microprofile14 │ │ │ └── restclient │ │ │ └── clientserver │ │ │ ├── config │ │ │ └── ApplicationInit.java │ │ │ └── remote │ │ │ └── HelloRemoteResource.java │ │ └── test │ │ └── java │ │ └── org │ │ └── eclipse │ │ └── microprofile14 │ │ └── restclient │ │ └── clientserver │ │ ├── ClientServerTest.java │ │ └── client │ │ └── HelloService.java ├── pom.xml ├── server-internal-async │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── org │ │ │ │ └── eclipse │ │ │ │ └── microprofile14 │ │ │ │ └── restclient │ │ │ │ └── serverinternal │ │ │ │ └── async │ │ │ │ ├── client │ │ │ │ ├── ClientResourceAsync.java │ │ │ │ └── HelloService.java │ │ │ │ ├── config │ │ │ │ ├── ApplicationInit.java │ │ │ │ └── URLServiceConfigSource.java │ │ │ │ └── remote │ │ │ │ └── HelloRemoteResource.java │ │ └── resources │ │ │ └── META-INF │ │ │ └── services │ │ │ └── org.eclipse.microprofile.config.spi.ConfigSource │ │ └── test │ │ └── java │ │ └── org │ │ └── eclipse │ │ └── microprofile14 │ │ └── restclient │ │ └── serverinternal │ │ └── async │ │ └── ServerInternalAsyncTest.java └── server-internal │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── eclipse │ │ │ └── microprofile14 │ │ │ └── restclient │ │ │ └── serverinternal │ │ │ ├── client │ │ │ ├── ClientResource.java │ │ │ └── HelloService.java │ │ │ ├── config │ │ │ ├── ApplicationInit.java │ │ │ └── URLServiceConfigSource.java │ │ │ └── remote │ │ │ └── HelloRemoteResource.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── org.eclipse.microprofile.config.spi.ConfigSource │ └── test │ └── java │ └── org │ └── eclipse │ └── microprofile14 │ └── restclient │ └── serverinternal │ └── ServerInternalTest.java └── test-utils ├── .gitignore ├── pom.xml └── src └── main ├── java └── org │ └── eclipse │ └── microprofile14 │ ├── CliCommands.java │ ├── JwtTokenGenerator.java │ ├── Libraries.java │ ├── Parameter.java │ ├── ParameterRule.java │ └── ServerOperations.java └── resources ├── arquillian-thorntail.xml ├── arquillian.xml ├── key.jks ├── logging.properties └── server.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Directories # 2 | build/ 3 | bin/ 4 | target/ 5 | libs/ 6 | tmp/ 7 | node_modules/ 8 | 9 | # OS Files # 10 | .DS_Store 11 | 12 | *.class 13 | 14 | # Package Files # 15 | *.jar 16 | *.war 17 | *.ear 18 | *.db 19 | rebel.xml 20 | 21 | ###################### 22 | # Windows 23 | ###################### 24 | 25 | # Windows image file caches 26 | Thumbs.db 27 | 28 | # Folder config file 29 | Desktop.ini 30 | 31 | ###################### 32 | # OSX 33 | ###################### 34 | 35 | .DS_Store 36 | .svn 37 | 38 | # Thumbnails 39 | ._* 40 | 41 | # Files that might appear on external disk 42 | .Spotlight-V100 43 | .Trashes 44 | 45 | ###################### 46 | # NetBeans 47 | ###################### 48 | nbproject/ 49 | build/ 50 | nbbuild/ 51 | dist/ 52 | nbdist/ 53 | nbactions.xml 54 | nb-configuration.xml 55 | 56 | ###################### 57 | # IDEA 58 | ###################### 59 | *.iml 60 | *.ipr 61 | *.iws 62 | .idea/ 63 | atlassian-ide-plugin.xml 64 | 65 | 66 | ###################### 67 | # Eclipse 68 | ###################### 69 | 70 | *.pydevproject 71 | .project 72 | .metadata 73 | *.tmp 74 | *.bak 75 | *.swp 76 | *~.nib 77 | local.properties 78 | .classpath 79 | .settings/ 80 | .loadpath 81 | 82 | # External tool builders 83 | .externalToolBuilders/ 84 | 85 | # Locally stored "Eclipse launch configurations" 86 | *.launch 87 | 88 | # CDT-specific 89 | .cproject 90 | 91 | # PDT-specific 92 | .buildpath 93 | 94 | # Testing environment specific 95 | derby.log 96 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | 5 | env: 6 | - SERVER=payara-ci-managed 7 | - SERVER=payara-micro-managed 8 | - SERVER=liberty-ci-managed 9 | - SERVER=wildfly-ci-managed 10 | 11 | install: mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V -Pnothing 12 | 13 | script: mvn clean install -P $SERVER --fail-at-end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 JavaEE Samples 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # microprofile1.4-samples 2 | Eclipse MicroProfile 1.4 Samples 3 | -------------------------------------------------------------------------------- /jwt-auth/README.md: -------------------------------------------------------------------------------- 1 | # Eclipse MicroProfile 1.4 Samples - JWT Auth 1.1 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 | ## Samples ## 7 | 8 | - **basic-authentication** The test sends a very basic signed JWT token to a protected servlet. The MP-JWT Auth implementation 9 | checks if the token is valid and sets the authenticated identity from the `upn` field and `groups` field. Has a variant where the required public key is in the archive, and one where the key is obtained externally (from outside the archive). 10 | **jaxrs ** Just like basic-authentication, but uses a JAX-RS endpoint. Specifically demonstrates the support of @RolesAllowed to secure and endpoint. 11 | 12 | 13 | 14 | ## Implementation config ## 15 | 16 | New in JWT Auth 1.1 is that implementation specific config is not longer mandated. Note that WildFly still needs implementation specific config, but this is not mandated by the spec. 17 | 18 | 19 | ## TCK ## 20 | 21 | The public/private keys are taken from the MP-Auth TCK. 22 | See the following URLs: 23 | 24 | - [MP-Auth TCK](https://github.com/eclipse/microprofile-jwt-auth/tree/master/tck) 25 | - [Payara TCK Ext](https://github.com/payara/Payara/tree/Payara-5/appserver/payara-appserver-modules/microprofile/jwt-auth-tck) 26 | - [Liberty TCK](https://github.com/OpenLiberty/open-liberty/tree/master/dev/com.ibm.ws.security.mp.jwt_fat_tck) 27 | - [WildFly TCK Ext](https://github.com/MicroProfileJWT/wfswarm-jwt-auth-tck) 28 | 29 | -------------------------------------------------------------------------------- /jwt-auth/basic-authentication/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | org.eclipse.microprofile.samples14 7 | jwt-auth 8 | 1.0-SNAPSHOT 9 | 10 | 11 | basic-authentication 12 | war 13 | MicroProfile 1.4: JWT-AUTH - Basic Authentication 14 | 15 | 16 | -------------------------------------------------------------------------------- /jwt-auth/basic-authentication/src/main/java/org/eclipse/microprofile14/jwtauth/basic/ApplicationInit.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.jwtauth.basic; 3 | 4 | import javax.enterprise.context.ApplicationScoped; 5 | 6 | import org.eclipse.microprofile.auth.LoginConfig; 7 | 8 | @LoginConfig( 9 | authMethod = "MP-JWT", 10 | // Even though specified being only for HTTP Basic auth, JBoss/WildFly/Swarm mandates this 11 | // to refer to its proprietary "security domain" concept. 12 | realmName = "MP-JWT" 13 | ) 14 | @ApplicationScoped 15 | public class ApplicationInit { 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /jwt-auth/basic-authentication/src/main/java/org/eclipse/microprofile14/jwtauth/basic/Servlet.java: -------------------------------------------------------------------------------- 1 | /* Copyright Payara Services Limited */ 2 | package org.eclipse.microprofile14.jwtauth.basic; 3 | 4 | import java.io.IOException; 5 | 6 | import javax.annotation.security.DeclareRoles; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.annotation.HttpConstraint; 9 | import javax.servlet.annotation.ServletSecurity; 10 | import javax.servlet.annotation.WebServlet; 11 | import javax.servlet.http.HttpServlet; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | 15 | 16 | @WebServlet("/servlet") 17 | @ServletSecurity(@HttpConstraint(rolesAllowed = "architect")) 18 | @DeclareRoles({"architect", "bar", "kaz"}) 19 | public class Servlet extends HttpServlet { 20 | 21 | private static final long serialVersionUID = 1L; 22 | 23 | @Override 24 | public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 25 | 26 | String webName = null; 27 | if (request.getUserPrincipal() != null) { 28 | webName = request.getUserPrincipal().getName(); 29 | } 30 | 31 | response.setContentType("text/plain"); 32 | 33 | response.getWriter().write( 34 | "This is a protected servlet \n" + 35 | 36 | "web username: " + webName + "\n" + 37 | 38 | "web user has role \"architect\": " + request.isUserInRole("architect") + "\n" + 39 | "web user has role \"bar\": " + request.isUserInRole("bar") + "\n" + 40 | "web user has role \"kaz\": " + request.isUserInRole("kaz") + "\n" 41 | ); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /jwt-auth/basic-authentication/src/main/resources/META-INF/microprofile-config.properties: -------------------------------------------------------------------------------- 1 | mp.jwt.verify.publickey.location=/META-INF/public-key.pem 2 | mp.jwt.verify.issuer=org.eclipse.microprofile12 -------------------------------------------------------------------------------- /jwt-auth/basic-authentication/src/main/resources/META-INF/public-key.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/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 | auth-modules: 26 | # This module integrates the MP-JWT custom authentication mechanism into the web container 27 | http: 28 | code: org.wildfly.extension.undertow.security.jaspi.modules.HTTPSchemeServerAuthModule 29 | module: org.wildfly.extension.undertow 30 | flag: required 31 | login-module-stack-ref: roles-lm-stack -------------------------------------------------------------------------------- /jwt-auth/basic-authentication/src/test/etc/alt-public-key.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/microprofile14/jwtauth/basic/BasicAuthenticationAltLocationTest.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.jwtauth.basic; 3 | 4 | import static java.nio.file.Files.write; 5 | import static java.nio.file.Paths.get; 6 | import static javax.ws.rs.client.ClientBuilder.newClient; 7 | import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION; 8 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 9 | import static org.eclipse.microprofile14.JwtTokenGenerator.generateJWTString; 10 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create; 11 | import static org.junit.Assert.assertFalse; 12 | import static org.junit.Assert.assertTrue; 13 | 14 | import java.io.File; 15 | import java.io.IOException; 16 | import java.net.URI; 17 | import java.net.URL; 18 | 19 | import javax.ws.rs.core.Response; 20 | 21 | import org.jboss.arquillian.container.test.api.Deployment; 22 | import org.jboss.arquillian.container.test.api.RunAsClient; 23 | import org.jboss.arquillian.junit.Arquillian; 24 | import org.jboss.arquillian.test.api.ArquillianResource; 25 | import org.jboss.shrinkwrap.api.spec.WebArchive; 26 | import org.junit.Test; 27 | import org.junit.runner.RunWith; 28 | 29 | @RunWith(Arquillian.class) 30 | public class BasicAuthenticationAltLocationTest { 31 | 32 | @ArquillianResource 33 | private URL base; 34 | 35 | @Deployment(testable = false) 36 | public static WebArchive createDeployment() throws IOException { 37 | 38 | // Gets the file location of the alternative key 39 | String fileLocation = new File("src/test/etc/alt-public-key.pem").toPath().toAbsolutePath().toString(); 40 | System.out.println("Key file is at: " + fileLocation); 41 | 42 | // Put this location in a new configuration file 43 | String configFileContent = 44 | "mp.jwt.verify.publickey.location=file://" + fileLocation + "\n" + 45 | "mp.jwt.verify.issuer=org.eclipse.microprofile12"; 46 | 47 | 48 | // Write this new configuration file to target. 49 | write(get("target/microprofile-config.properties"), configFileContent.getBytes()); 50 | 51 | WebArchive archive = 52 | create(WebArchive.class) 53 | .addClasses( 54 | ApplicationInit.class, 55 | Servlet.class 56 | ).addAsResource( 57 | // Supply the generated file we just created to the archive. This will have the local on disk 58 | // location of the key file in it, which means the key will be loaded externall from the archive. 59 | // (this will work only if the target server is on the same filesystem, of course) 60 | new File("target/microprofile-config.properties"), "META-INF/microprofile-config.properties" 61 | ).addAsResource( 62 | // WildFly file setting up the security system (domain) such that all artifacts to support 63 | // MP-Auth JWT are installed 64 | "project-defaults.yml") 65 | ; 66 | 67 | System.out.println("************************************************************"); 68 | System.out.println(archive.toString(true)); 69 | System.out.println("************************************************************"); 70 | 71 | return archive; 72 | 73 | } 74 | 75 | @Test 76 | @RunAsClient 77 | public void testProtectedPageNotLoggedin() throws IOException { 78 | 79 | Response response = 80 | newClient() 81 | .target( 82 | URI.create(new URL(base, "servlet").toExternalForm())) 83 | .request(TEXT_PLAIN) 84 | .get(); 85 | 86 | // Not logged-in thus should not be accessible. 87 | assertFalse( 88 | "Not authenticated, so should not have been able to access protected resource", 89 | response.readEntity(String.class).contains("This is a protected servlet") 90 | ); 91 | } 92 | 93 | @Test 94 | @RunAsClient 95 | public void testProtectedPageLoggedin() throws Exception { 96 | 97 | String response = 98 | newClient() 99 | .target( 100 | URI.create(new URL(base, "servlet").toExternalForm())) 101 | .request(TEXT_PLAIN) 102 | .header(AUTHORIZATION, "Bearer " + generateJWTString("jwt-token.json")) 103 | .get(String.class); 104 | 105 | // Now has to be logged-in so page is accessible 106 | assertTrue( 107 | "Should have been authenticated, but could not access protected resource", 108 | response.contains("This is a protected servlet") 109 | ); 110 | 111 | // Not only does the page needs to be accessible, the caller should have 112 | // the correct name and roles as well 113 | 114 | // Being able to access a page protected by a role but then seeing the un-authenticated 115 | // (anonymous) user would normally be impossible, but could happen if the authorization 116 | // system checks roles on the authenticated subject, but does not correctly expose 117 | // or propagate these to the HttpServletRequest 118 | assertFalse( 119 | "Protected resource could be accessed, but the user appears to be the unauthenticated user. " + 120 | "This should not be possible", 121 | response.contains("web username: null") 122 | ); 123 | 124 | // An authenticated user should have the exact name "test" and nothing else. 125 | assertTrue( 126 | "Protected resource could be accessed, but the username is not correct.", 127 | response.contains("web username: test") 128 | ); 129 | 130 | // Being able to access a page protected by role "architect" but failing 131 | // the test for this role would normally be impossible, but could happen if the 132 | // authorization system checks roles on the authenticated subject, but does not 133 | // correctly expose or propagate these to the HttpServletRequest 134 | assertTrue( 135 | "Resource protected by role \"architect\" could be accessed, but user fails test for this role." + 136 | "This should not be possible", 137 | response.contains("web user has role \"architect\": true") 138 | ); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /jwt-auth/basic-authentication/src/test/java/org/eclipse/microprofile14/jwtauth/basic/BasicAuthenticationTest.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.jwtauth.basic; 3 | 4 | import static javax.ws.rs.client.ClientBuilder.newClient; 5 | import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION; 6 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 7 | import static org.eclipse.microprofile14.JwtTokenGenerator.generateJWTString; 8 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create; 9 | import static org.junit.Assert.assertFalse; 10 | import static org.junit.Assert.assertTrue; 11 | 12 | import java.io.IOException; 13 | import java.net.URI; 14 | import java.net.URL; 15 | 16 | import javax.ws.rs.core.Response; 17 | 18 | import org.eclipse.microprofile14.jwtauth.basic.ApplicationInit; 19 | import org.eclipse.microprofile14.jwtauth.basic.Servlet; 20 | import org.jboss.arquillian.container.test.api.Deployment; 21 | import org.jboss.arquillian.container.test.api.RunAsClient; 22 | import org.jboss.arquillian.junit.Arquillian; 23 | import org.jboss.arquillian.test.api.ArquillianResource; 24 | import org.jboss.shrinkwrap.api.spec.WebArchive; 25 | import org.junit.Test; 26 | import org.junit.runner.RunWith; 27 | 28 | /** 29 | * @author Arjan Tijms 30 | */ 31 | @RunWith(Arquillian.class) 32 | public class BasicAuthenticationTest { 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 | .addClasses( 42 | ApplicationInit.class, 43 | Servlet.class 44 | ).addAsResource( 45 | // Main Properties file configuring that "org.eclipse.microprofile12" is the valid issuer 46 | // and META-INF/public-key.pem is the public key 47 | "META-INF/microprofile-config.properties" 48 | ).addAsResource( 49 | // Public key to verify the incoming signed JWT's signature 50 | "META-INF/public-key.pem" 51 | ).addAsResource( 52 | // WildFly file configuring that "org.eclipse.microprofile12" is the valid issuer and setting up 53 | // the security system (domain) such that all artifacts to support MP-Auth JWT are installed 54 | "project-defaults.yml") 55 | ; 56 | 57 | System.out.println("************************************************************"); 58 | System.out.println(archive.toString(true)); 59 | System.out.println("************************************************************"); 60 | 61 | return archive; 62 | 63 | } 64 | 65 | @Test 66 | @RunAsClient 67 | public void testProtectedPageNotLoggedin() throws IOException { 68 | 69 | Response response = 70 | newClient() 71 | .target( 72 | URI.create(new URL(base, "servlet").toExternalForm())) 73 | .request(TEXT_PLAIN) 74 | .get(); 75 | 76 | // Not logged-in thus should not be accessible. 77 | assertFalse( 78 | "Not authenticated, so should not have been able to access protected resource", 79 | response.readEntity(String.class).contains("This is a protected servlet") 80 | ); 81 | } 82 | 83 | @Test 84 | @RunAsClient 85 | public void testProtectedPageLoggedin() throws Exception { 86 | 87 | String response = 88 | newClient() 89 | .target( 90 | URI.create(new URL(base, "servlet").toExternalForm())) 91 | .request(TEXT_PLAIN) 92 | .header(AUTHORIZATION, "Bearer " + generateJWTString("jwt-token.json")) 93 | .get(String.class); 94 | 95 | // Now has to be logged-in so page is accessible 96 | assertTrue( 97 | "Should have been authenticated, but could not access protected resource", 98 | response.contains("This is a protected servlet") 99 | ); 100 | 101 | // Not only does the page needs to be accessible, the caller should have 102 | // the correct name and roles as well 103 | 104 | // Being able to access a page protected by a role but then seeing the un-authenticated 105 | // (anonymous) user would normally be impossible, but could happen if the authorization 106 | // system checks roles on the authenticated subject, but does not correctly expose 107 | // or propagate these to the HttpServletRequest 108 | assertFalse( 109 | "Protected resource could be accessed, but the user appears to be the unauthenticated user. " + 110 | "This should not be possible", 111 | response.contains("web username: null") 112 | ); 113 | 114 | // An authenticated user should have the exact name "test" and nothing else. 115 | assertTrue( 116 | "Protected resource could be accessed, but the username is not correct.", 117 | response.contains("web username: test") 118 | ); 119 | 120 | // Being able to access a page protected by role "architect" but failing 121 | // the test for this role would normally be impossible, but could happen if the 122 | // authorization system checks roles on the authenticated subject, but does not 123 | // correctly expose or propagate these to the HttpServletRequest 124 | assertTrue( 125 | "Resource protected by role \"architect\" could be accessed, but user fails test for this role." + 126 | "This should not be possible", 127 | response.contains("web user has role \"architect\": true") 128 | ); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /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 | 3 | 4.0.0 4 | 5 | 6 | org.eclipse.microprofile.samples14 7 | jwt-auth 8 | 1.0-SNAPSHOT 9 | 10 | 11 | jaxrs 12 | war 13 | MicroProfile 1.4: JWT-AUTH - JAX-RS 14 | 15 | 16 | -------------------------------------------------------------------------------- /jwt-auth/jaxrs/src/main/java/org/eclipse/microprofile14/jwtauth/jaxrs/ApplicationInit.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.jwtauth.jaxrs; 3 | 4 | import javax.annotation.security.DeclareRoles; 5 | import javax.ws.rs.ApplicationPath; 6 | import javax.ws.rs.core.Application; 7 | 8 | import org.eclipse.microprofile.auth.LoginConfig; 9 | 10 | @LoginConfig( 11 | authMethod = "MP-JWT", 12 | // Even though specified being only for HTTP Basic auth, JBoss/WildFly/Swarm mandates this 13 | // to refer to its proprietary "security domain" concept. 14 | realmName = "MP-JWT" 15 | ) 16 | @DeclareRoles({"architect", "bar", "kaz"}) 17 | @ApplicationPath("/") 18 | public class ApplicationInit extends Application { 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /jwt-auth/jaxrs/src/main/java/org/eclipse/microprofile14/jwtauth/jaxrs/Resource.java: -------------------------------------------------------------------------------- 1 | /* Copyright Payara Services Limited */ 2 | package org.eclipse.microprofile14.jwtauth.jaxrs; 3 | 4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 5 | 6 | import java.security.Principal; 7 | 8 | import javax.annotation.security.RolesAllowed; 9 | import javax.enterprise.context.ApplicationScoped; 10 | import javax.inject.Inject; 11 | import javax.ws.rs.GET; 12 | import javax.ws.rs.Path; 13 | import javax.ws.rs.Produces; 14 | 15 | @ApplicationScoped 16 | @Path("/resource") 17 | @Produces(TEXT_PLAIN) 18 | public class Resource { 19 | 20 | @Inject 21 | private Principal principal; 22 | 23 | @GET 24 | @Path("/protected") 25 | @RolesAllowed("architect") 26 | public String protectedResource() { 27 | return 28 | "This is a protected resource \n" + 29 | "web username: " + principal.getName() + "\n"; 30 | } 31 | 32 | @GET 33 | @Path("public") 34 | public String publicResource() { 35 | return 36 | "This is a public resource \n" + 37 | "web username: " + principal.getName() + "\n"; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /jwt-auth/jaxrs/src/main/resources/META-INF/microprofile-config.properties: -------------------------------------------------------------------------------- 1 | mp.jwt.verify.publickey.location=/META-INF/public-key.pem 2 | mp.jwt.verify.issuer=org.eclipse.microprofile12 -------------------------------------------------------------------------------- /jwt-auth/jaxrs/src/main/resources/META-INF/public-key.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/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 | thorntail: 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 | logging: 12 | loggers: 13 | io.undertow.request.security: 14 | level: TRACE 15 | security: 16 | security-domains: 17 | MP-JWT: 18 | jaspi-authentication: 19 | login-module-stacks: 20 | roles-lm-stack: 21 | login-modules: 22 | # This stack performs the token verification and group to role mapping 23 | - login-module: rm 24 | code: org.wildfly.swarm.microprofile.jwtauth.deployment.auth.jaas.JWTLoginModule 25 | flag: required 26 | auth-modules: 27 | # This module integrates the MP-JWT custom authentication mechanism into the web container 28 | http: 29 | code: org.wildfly.extension.undertow.security.jaspi.modules.HTTPSchemeServerAuthModule 30 | module: org.wildfly.extension.undertow 31 | flag: required 32 | login-module-stack-ref: roles-lm-stack -------------------------------------------------------------------------------- /jwt-auth/jaxrs/src/test/java/org/eclipse/microprofile14/jwtauth/jaxrs/JaxRsTest.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.jwtauth.jaxrs; 3 | 4 | import static javax.ws.rs.client.ClientBuilder.newClient; 5 | import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION; 6 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 7 | import static org.eclipse.microprofile14.JwtTokenGenerator.generateJWTString; 8 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create; 9 | import static org.jboss.shrinkwrap.api.asset.EmptyAsset.INSTANCE; 10 | import static org.junit.Assert.assertFalse; 11 | import static org.junit.Assert.assertTrue; 12 | 13 | import java.io.IOException; 14 | import java.net.URI; 15 | import java.net.URL; 16 | 17 | import javax.ws.rs.core.Response; 18 | 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 Arjan Tijms 30 | */ 31 | @RunWith(Arquillian.class) 32 | public class JaxRsTest { 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 | .addClasses( 42 | ApplicationInit.class, 43 | Resource.class 44 | ).addAsResource( 45 | // Main Properties file configuring that "org.eclipse.microprofile12" is the valid issuer 46 | // and META-INF/public-key.pem is the public key 47 | "META-INF/microprofile-config.properties" 48 | ).addAsResource( 49 | // Public key to verify the incoming signed JWT's signature 50 | "META-INF/public-key.pem" 51 | ).addAsResource( 52 | // WildFly file configuring that "org.eclipse.microprofile12" is the valid issuer and setting up 53 | // the security system (domain) such that all artifacts to support MP-Auth JWT are installed 54 | "project-defaults.yml") 55 | .addAsWebInfResource( 56 | // Make CDI look at ApplicationInit and discover LoginConfig 57 | INSTANCE, "beans.xml") 58 | ; 59 | 60 | System.out.println("************************************************************"); 61 | System.out.println(archive.toString(true)); 62 | System.out.println("************************************************************"); 63 | 64 | return archive; 65 | 66 | } 67 | 68 | @Test 69 | @RunAsClient 70 | public void testProtectedResourceNotLoggedin() throws IOException { 71 | 72 | System.out.println("-------------------------------------------------------------------------"); 73 | System.out.println("Base URL: " + base); 74 | System.out.println("-------------------------------------------------------------------------"); 75 | 76 | Response response = 77 | newClient() 78 | .target( 79 | URI.create(new URL(base, "resource/protected").toExternalForm())) 80 | .request(TEXT_PLAIN) 81 | .get(); 82 | 83 | // Not logged-in thus should not be accessible. 84 | assertFalse( 85 | "Not authenticated, so should not have been able to access protected resource", 86 | response.readEntity(String.class).contains("This is a protected resource") 87 | ); 88 | } 89 | 90 | @Test 91 | @RunAsClient 92 | public void testPublicResourceNotLoggedin() throws IOException { 93 | 94 | Response response = 95 | newClient() 96 | .target( 97 | URI.create(new URL(base, "resource/public").toExternalForm())) 98 | .request(TEXT_PLAIN) 99 | .get(); 100 | 101 | // Public resource, no log-in needed 102 | assertTrue( 103 | "Public resource is not constrained (protected) so should be accessible without sending the JWT token", 104 | response.readEntity(String.class).contains("This is a public resource") 105 | ); 106 | } 107 | 108 | @Test 109 | @RunAsClient 110 | public void testProtectedResourceLoggedin() throws Exception { 111 | 112 | String response = 113 | newClient() 114 | .target( 115 | URI.create(new URL(base, "resource/protected").toExternalForm())) 116 | .request(TEXT_PLAIN) 117 | .header(AUTHORIZATION, "Bearer " + generateJWTString("jwt-token.json")) 118 | .get(String.class); 119 | 120 | 121 | System.out.println("-------------------------------------------------------------------------"); 122 | System.out.println("Response: " + response); 123 | System.out.println("-------------------------------------------------------------------------"); 124 | 125 | // Now has to be logged-in so page is accessible 126 | assertTrue( 127 | "Should have been authenticated, but could not access protected resource", 128 | response.contains("This is a protected resource") 129 | ); 130 | 131 | // Not only does the resource needs to be accessible, the caller should have 132 | // the correct name 133 | 134 | // Being able to access a page protected by a role but then seeing the un-authenticated 135 | // (anonymous) user would normally be impossible, but could happen if the authorization 136 | // system checks roles on the authenticated subject, but does not correctly expose 137 | // or propagate these to the injected Principal 138 | assertFalse( 139 | "Protected resource could be accessed, but the user appears to be the unauthenticated user. " + 140 | "This should not be possible", 141 | response.contains("web username: null") 142 | ); 143 | 144 | // An authenticated user should have the exact name "test" and nothing else. 145 | assertTrue( 146 | "Protected resource could be accessed, but the username is not correct.", 147 | response.contains("web username: test") 148 | ); 149 | 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /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 | 3 | 4.0.0 4 | 5 | 6 | org.eclipse.microprofile.samples14 7 | samples-parent 8 | 1.0-SNAPSHOT 9 | 10 | 11 | jwt-auth 12 | pom 13 | 14 | MicroProfile 1.4: JWT-AUTH 15 | 16 | 17 | basic-authentication 18 | jaxrs 19 | 20 | 21 | 22 | 23 | org.eclipse.microprofile.samples14 24 | test-utils 25 | ${project.version} 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /open-api/README.md: -------------------------------------------------------------------------------- 1 | # Eclipse MicroProfile 1.4 Samples - Open API 1.0 2 | 3 | - [Wiki project page](https://wiki.eclipse.org/MicroProfile/OpenAPI) 4 | - [Spec, API, TCK GitHub repo](https://github.com/eclipse/microprofile-open-api) 5 | 6 | ## Samples ## 7 | 8 | - **basic-hello** A trivially simple hello-style JAX-RS resource for which an OpenAPI document is created 9 | 10 | 11 | -------------------------------------------------------------------------------- /open-api/basic-hello/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | org.eclipse.microprofile.samples14 8 | open-api 9 | 1.0-SNAPSHOT 10 | 11 | 12 | basic-hello 13 | war 14 | 15 | MicroProfile 1.4: Open API - Basic hello 16 | 17 | 18 | -------------------------------------------------------------------------------- /open-api/basic-hello/src/main/java/org/eclipse/microprofile14/openapi/basichello/ApplicationInit.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.openapi.basichello; 3 | 4 | import javax.ws.rs.ApplicationPath; 5 | import javax.ws.rs.core.Application; 6 | 7 | @ApplicationPath("/api") 8 | public class ApplicationInit extends Application { 9 | 10 | } -------------------------------------------------------------------------------- /open-api/basic-hello/src/main/java/org/eclipse/microprofile14/openapi/basichello/HelloModelReader.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.openapi.basichello; 3 | 4 | import org.eclipse.microprofile.openapi.OASFactory; 5 | import org.eclipse.microprofile.openapi.OASModelReader; 6 | import org.eclipse.microprofile.openapi.models.OpenAPI; 7 | 8 | /** 9 | * Generates a base model to be used by the OpenAPI. 10 | */ 11 | public class HelloModelReader implements OASModelReader { 12 | 13 | @Override 14 | public OpenAPI buildModel() { 15 | return OASFactory.createObject(OpenAPI.class); 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /open-api/basic-hello/src/main/java/org/eclipse/microprofile14/openapi/basichello/HelloResource.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.openapi.basichello; 3 | 4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 5 | 6 | import javax.ws.rs.GET; 7 | import javax.ws.rs.Path; 8 | import javax.ws.rs.Produces; 9 | 10 | import org.eclipse.microprofile.openapi.annotations.Operation; 11 | 12 | @Path("/hello") 13 | public class HelloResource { 14 | 15 | @GET 16 | @Operation( 17 | operationId = "hello world", 18 | description = "This is a well know Hello World service. It will output a variant of the expected 'Hello, world!' phrase.") 19 | @Produces(TEXT_PLAIN) 20 | public String helloWorld() { 21 | return "Hello World!"; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /open-api/basic-hello/src/main/java/org/eclipse/microprofile14/openapi/basichello/OperationHyphenFilter.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.openapi.basichello; 3 | 4 | import org.eclipse.microprofile.openapi.OASFilter; 5 | import org.eclipse.microprofile.openapi.models.Operation; 6 | 7 | /** 8 | * A filter to make final configuration changes to the produced OpenAPI document. 9 | */ 10 | public class OperationHyphenFilter implements OASFilter { 11 | 12 | /** 13 | * Replaces all spaces in each operation id with a hyphen. 14 | */ 15 | @Override 16 | public Operation filterOperation(Operation operation) { 17 | if (operation.getOperationId().contains((" "))) { 18 | operation.setOperationId(operation.getOperationId().replace(" ", "-")); 19 | } 20 | 21 | return operation; 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /open-api/basic-hello/src/main/resources/META-INF/microprofile-config.properties: -------------------------------------------------------------------------------- 1 | # Configure the processing classed defined to edit the OpenAPI document. 2 | mp.openapi.model.reader=org.eclipse.microprofile14.openapi.basichello.HelloModelReader 3 | mp.openapi.filter=org.eclipse.microprofile14.openapi.basichello.OperationHyphenFilter 4 | 5 | # Whether to disable the scanning of application classes 6 | mp.openapi.scan.disable=false -------------------------------------------------------------------------------- /open-api/basic-hello/src/test/java/org/eclipse/microprofile14/openapi/basichello/BasicHelloTest.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.openapi.basichello; 3 | 4 | import static javax.ws.rs.client.ClientBuilder.newClient; 5 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 6 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create; 7 | import static org.junit.Assert.assertTrue; 8 | 9 | import java.io.IOException; 10 | import java.net.URI; 11 | import java.net.URL; 12 | 13 | import org.eclipse.microprofile14.openapi.basichello.ApplicationInit; 14 | import org.eclipse.microprofile14.openapi.basichello.HelloResource; 15 | import org.eclipse.microprofile14.openapi.basichello.OperationHyphenFilter; 16 | import org.jboss.arquillian.container.test.api.Deployment; 17 | import org.jboss.arquillian.container.test.api.RunAsClient; 18 | import org.jboss.arquillian.junit.Arquillian; 19 | import org.jboss.arquillian.test.api.ArquillianResource; 20 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 21 | import org.jboss.shrinkwrap.api.spec.WebArchive; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | 25 | /** 26 | * @author Arjan Tijms 27 | */ 28 | @RunWith(Arquillian.class) 29 | public class BasicHelloTest { 30 | 31 | @ArquillianResource 32 | private URL base; 33 | 34 | @Deployment(testable = false) 35 | public static WebArchive createDeployment() { 36 | WebArchive archive = 37 | create(WebArchive.class) 38 | .addClasses( 39 | ApplicationInit.class, 40 | HelloResource.class, 41 | HelloModelReader.class, 42 | OperationHyphenFilter.class 43 | ).addAsResource( 44 | "META-INF/microprofile-config.properties" 45 | ).addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") 46 | ; 47 | 48 | System.out.println("************************************************************"); 49 | System.out.println(archive.toString(true)); 50 | System.out.println("************************************************************"); 51 | 52 | return archive; 53 | } 54 | 55 | @Test 56 | @RunAsClient 57 | public void testServerInternal() throws IOException { 58 | String response = 59 | newClient() 60 | .target( 61 | URI.create(new URL(base.getProtocol(), base.getHost(), base.getPort(), "/openapi").toExternalForm())) 62 | .request(TEXT_PLAIN) 63 | .get(String.class); 64 | 65 | System.out.println("-------------------------------------------------------------------------"); 66 | System.out.println("Response: " + response); 67 | System.out.println("-------------------------------------------------------------------------"); 68 | 69 | assertTrue( 70 | response.contains("hello-world") 71 | ); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /open-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | org.eclipse.microprofile.samples14 8 | samples-parent 9 | 1.0-SNAPSHOT 10 | 11 | 12 | open-api 13 | pom 14 | 15 | MicroProfile 1.4: Open API 16 | 17 | 18 | basic-hello 19 | 20 | 21 | 22 | 23 | org.eclipse.microprofile.samples14 24 | test-utils 25 | ${project.version} 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 4.0.0 8 | 9 | 10 | 3.5 11 | 12 | 13 | org.eclipse.microprofile.samples14 14 | samples-parent 15 | 1.0-SNAPSHOT 16 | pom 17 | 18 | Eclipse MicroProfile 1.4 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.183 36 | 5.183 37 | 18.0.0.2 38 | 2.3.0.Final 39 | 40 | 1.0.Beta3 41 | 5.Beta3 42 | 43 | 44 | 45 | 46 | central 47 | Central Repository 48 | https://repo.maven.apache.org/maven2 49 | 50 | true 51 | 52 | 53 | false 54 | 55 | 56 | 57 | 58 | payara-milestones 59 | Payara Milestones 60 | https://raw.github.com/payara/Payara_PatchedProjects/master 61 | 62 | true 63 | 64 | 65 | false 66 | 67 | 68 | 69 | 70 | payara-milestones-eclipse 71 | Payara Milestones Eclipse 72 | https://raw.github.com/payara/Payara_PatchedProjects/eclipse 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | 81 | 82 | ossrh 83 | Sonatype-snapshot 84 | https://oss.sonatype.org/content/repositories/snapshots 85 | 86 | false 87 | 88 | 89 | true 90 | 91 | 92 | 93 | 94 | jvnet-nexus-staging 95 | Java.net Staging Repositories 96 | https://maven.java.net/content/repositories/staging 97 | 98 | true 99 | 100 | 101 | false 102 | 103 | 104 | 105 | 106 | 107 | 109 | 110 | jwt-auth 111 | rest-client 112 | open-api 113 | test-utils 114 | 115 | 116 | 117 | 118 | 119 | org.jboss.arquillian 120 | arquillian-bom 121 | 1.4.1.Final 122 | import 123 | pom 124 | 125 | 126 | org.jboss.arquillian.container 127 | arquillian-container-test-api 128 | 1.4.1.Final 129 | 130 | 131 | com.h2database 132 | h2 133 | 1.4.199 134 | 135 | 136 | fish.payara.arquillian 137 | payara-client-ee8 138 | 1.0.Beta3 139 | test 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | javax 148 | javaee-api 149 | 8.0.1 150 | provided 151 | 152 | 153 | 154 | 155 | 156 | 157 | junit 158 | junit 159 | 4.13-beta-3 160 | test 161 | 162 | 163 | org.jboss.arquillian.junit 164 | arquillian-junit-container 165 | test 166 | 167 | 168 | org.jboss.arquillian.protocol 169 | arquillian-protocol-servlet 170 | test 171 | 172 | 173 | org.jboss.shrinkwrap.resolver 174 | shrinkwrap-resolver-impl-maven 175 | test 176 | 177 | 178 | org.jboss.shrinkwrap.resolver 179 | shrinkwrap-resolver-impl-maven-archive 180 | test 181 | 182 | 183 | net.sourceforge.htmlunit 184 | htmlunit 185 | 2.35.0 186 | test 187 | 188 | 189 | 190 | org.eclipse.microprofile 191 | microprofile 192 | 1.4 193 | pom 194 | provided 195 | 196 | 197 | 198 | 199 | jakarta.xml.bind 200 | jakarta.xml.bind-api 201 | 2.3.2 202 | 203 | 204 | org.glassfish.jaxb 205 | jaxb-runtime 206 | 2.3.2 207 | 208 | 209 | 210 | 211 | 212 | ${project.artifactId} 213 | 214 | 215 | 216 | src/test/resources 217 | true 218 | 219 | 220 | 221 | 222 | 223 | org.apache.maven.plugins 224 | maven-compiler-plugin 225 | 3.7.0 226 | 227 | ${java.min.version} 228 | ${java.min.version} 229 | 230 | 231 | 232 | org.apache.maven.plugins 233 | maven-surefire-report-plugin 234 | 2.21.0 235 | 236 | true 237 | true 238 | 239 | 240 | 241 | org.apache.maven.plugins 242 | maven-surefire-plugin 243 | 2.21.0 244 | 245 | 246 | javax.annotation 247 | javax.annotation-api 248 | 1.3.2 249 | 250 | 251 | 252 | 253 | org.apache.maven.plugins 254 | maven-war-plugin 255 | 3.2.0 256 | 257 | true 258 | false 259 | 260 | 261 | 262 | org.apache.maven.plugins 263 | maven-enforcer-plugin 264 | 3.0.0-M1 265 | 266 | 267 | 268 | At least Maven in version 269 | ${maven.min.version} is 270 | required. 271 | ${maven.min.version} 272 | 273 | 274 | At least a JDK in version 275 | ${java.min.version} is 276 | required. 277 | ${java.min.version} 278 | 279 | 280 | 281 | 282 | 283 | 284 | enforce 285 | 286 | 287 | 288 | 289 | 290 | org.apache.maven.plugins 291 | maven-dependency-plugin 292 | 3.1.0 293 | 294 | 295 | org.apache.maven.plugins 296 | maven-resources-plugin 297 | 3.1.0 298 | 299 | 300 | org.wildfly.plugins 301 | wildfly-maven-plugin 302 | 1.2.1.Final 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | payara-ci-managed 319 | 320 | 321 | true 322 | 323 | 324 | 325 | 326 | 327 | fish.payara.arquillian 328 | payara-client-ee8 329 | 330 | 331 | 332 | 333 | fish.payara.arquillian 334 | arquillian-payara-server-4-managed 335 | ${payara.container.version} 336 | test 337 | 338 | 339 | 340 | 341 | 342 | 343 | org.apache.maven.plugins 344 | maven-dependency-plugin 345 | 346 | 347 | unpack 348 | process-test-classes 349 | 350 | unpack 351 | 352 | 353 | ${session.executionRootDirectory}/target 354 | ${session.executionRootDirectory}/target/dependency-maven-plugin-markers 355 | 356 | 357 | fish.payara.distributions 358 | payara-web 359 | ${payara.version} 360 | zip 361 | false 362 | ${session.executionRootDirectory}/target 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | org.apache.maven.plugins 371 | maven-surefire-plugin 372 | 373 | 374 | 375 | javax.annotation 376 | javax.annotation-api 377 | 1.3.1 378 | 379 | 380 | 381 | ${session.executionRootDirectory}/target/payara5 382 | 383 | 384 | 385 | ${session.executionRootDirectory}/target/payara5 386 | payara-remote 387 | payara 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | payara-micro-managed 397 | 398 | 399 | true 400 | true 401 | 402 | 403 | 404 | 405 | 406 | 407 | fish.payara.arquillian 408 | payara-client-ee8 409 | 410 | 411 | 412 | 413 | fish.payara.arquillian 414 | arquillian-payara-micro-5-managed 415 | ${payara.container.version} 416 | test 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | org.apache.maven.plugins 425 | maven-dependency-plugin 426 | 427 | 428 | process-test-classes 429 | 430 | copy 431 | 432 | 433 | 434 | 435 | fish.payara.extras 436 | payara-micro 437 | ${payara.micro.version} 438 | false 439 | ${session.executionRootDirectory}/target/ 440 | payara-micro-${payara.micro.version}.jar 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | maven-surefire-plugin 450 | 451 | 452 | ${session.executionRootDirectory}/target/payara-micro-${payara.micro.version}.jar 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | payara-remote 462 | 463 | 464 | 465 | fish.payara.arquillian 466 | payara-client-ee8 467 | 468 | 469 | 470 | 471 | fish.payara.arquillian 472 | arquillian-payara-server-4-remote 473 | ${payara.container.version} 474 | test 475 | 476 | 477 | 478 | 479 | 480 | maven-surefire-plugin 481 | 482 | 483 | payara-remote 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | liberty-ci-managed 497 | 498 | 499 | 500 | fish.payara.arquillian 501 | payara-client-ee8 502 | 503 | 504 | 505 | org.jboss.arquillian.container 506 | arquillian-wlp-managed-8.5 507 | 1.0.0.CR1 508 | test 509 | 510 | 511 | 512 | 513 | 514 | 515 | org.apache.maven.plugins 516 | maven-dependency-plugin 517 | 518 | 519 | unpack 520 | test-compile 521 | 522 | unpack 523 | 524 | 525 | 526 | 527 | 528 | io.openliberty 529 | openliberty-runtime 530 | ${liberty.version} 531 | 532 | 533 | 535 | zip 536 | false 537 | ${session.executionRootDirectory}/target/ 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | org.apache.maven.plugins 546 | maven-antrun-plugin 547 | 1.8 548 | 549 | 550 | unpack 551 | process-test-classes 552 | 553 | run 554 | 555 | 556 | 557 | 559 | Copying server.xml 560 | 563 | Copying key.jks 564 | 566 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | org.apache.maven.plugins 576 | maven-surefire-plugin 577 | 578 | 579 | liberty-ci-managed 580 | 581 | ${session.executionRootDirectory}/target/wlp 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | thorntail 595 | 596 | 597 | 598 | 599 | 600 | io.thorntail 601 | bom 602 | ${thorntail.version} 603 | import 604 | pom 605 | 606 | 607 | 608 | 609 | 610 | 612 | 613 | io.thorntail 614 | arquillian 615 | test 616 | 617 | 618 | 619 | io.thorntail 620 | microprofile 621 | 622 | 623 | 624 | 625 | 626 | maven-surefire-plugin 627 | 628 | 629 | 630 | 631 | arquillian-thorntail.xml 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | nothing 641 | 642 | 643 | 646 | 647 | javadocs 648 | 649 | 650 | javadocs 651 | 652 | 653 | 654 | 655 | 656 | org.apache.maven.plugins 657 | maven-dependency-plugin 658 | 2.4 659 | 660 | 661 | sources 662 | process-resources 663 | 664 | sources 665 | resolve 666 | 667 | 668 | javadoc 669 | false 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | org.apache.maven.plugins 683 | maven-surefire-report-plugin 684 | 2.19.1 685 | 686 | true 687 | true 688 | 689 | 690 | 691 | 692 | 693 | 694 | -------------------------------------------------------------------------------- /rest-client/README.md: -------------------------------------------------------------------------------- 1 | # Eclipse MicroProfile 1.4 Samples - Rest Client 1.1 2 | 3 | - [Wiki project page](https://wiki.eclipse.org/MicroProfile/RESTClient) 4 | - [Spec, API, TCK GitHub repo](https://github.com/eclipse/microprofile-rest-client) 5 | 6 | ## Samples ## 7 | 8 | - **client-server** A standalone (Java SE) client creates a type-safe local service from an interface definition and uses it to contact a remote JAX-RS resource 9 | - **client-server-async** Variant of client-server where the type-safe service has an async signature, while still connecting to same backend JAX-RS resource 10 | - **server-internal** Injects an internal JAX-RS resource as a type-safe service into another JAX-RS resource 11 | - **server-internal-async** Variant of server-internal where the type-safe service has an async signature, while still connecting to same backend JAX-RS resource 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /rest-client/client-server-async/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | org.eclipse.microprofile.samples14 8 | rest-client 9 | 1.0-SNAPSHOT 10 | 11 | 12 | client-server-async 13 | war 14 | 15 | MicroProfile 1.4: Rest Client - Client-server async 16 | 17 | 18 | -------------------------------------------------------------------------------- /rest-client/client-server-async/src/main/java/org/eclipse/microprofile14/restclient/clientserver/config/ApplicationInit.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.clientserver.config; 3 | 4 | import javax.ws.rs.ApplicationPath; 5 | import javax.ws.rs.core.Application; 6 | 7 | @ApplicationPath("/api") 8 | public class ApplicationInit extends Application { 9 | 10 | } -------------------------------------------------------------------------------- /rest-client/client-server-async/src/main/java/org/eclipse/microprofile14/restclient/clientserver/remote/HelloRemoteResource.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.clientserver.remote; 3 | 4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 5 | 6 | import javax.ws.rs.Consumes; 7 | import javax.ws.rs.GET; 8 | import javax.ws.rs.Path; 9 | import javax.ws.rs.PathParam; 10 | import javax.ws.rs.Produces; 11 | 12 | @Path("/hello") 13 | @Produces(TEXT_PLAIN) 14 | @Consumes(TEXT_PLAIN) 15 | public class HelloRemoteResource { 16 | 17 | @GET 18 | @Path("{name}") 19 | public String hello(@PathParam("name") String name) { 20 | return "Hello " + name + "!"; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /rest-client/client-server-async/src/test/java/org/eclipse/microprofile14/restclient/clientserver/ClientServerAsyncTest.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.clientserver; 3 | 4 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import java.io.IOException; 8 | import java.net.URISyntaxException; 9 | import java.net.URL; 10 | import java.util.concurrent.ExecutionException; 11 | 12 | import org.eclipse.microprofile.rest.client.RestClientBuilder; 13 | import org.eclipse.microprofile.rest.client.RestClientDefinitionException; 14 | import org.eclipse.microprofile14.restclient.clientserver.client.HelloService; 15 | import org.eclipse.microprofile14.restclient.clientserver.config.ApplicationInit; 16 | import org.eclipse.microprofile14.restclient.clientserver.remote.HelloRemoteResource; 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 ClientServerAsyncTest { 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 | .addClasses( 40 | ApplicationInit.class, 41 | HelloRemoteResource.class 42 | ).addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") 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 testClientServerAsync() throws IOException, IllegalStateException, RestClientDefinitionException, URISyntaxException, InterruptedException, ExecutionException { 55 | 56 | HelloService remoteApi = RestClientBuilder.newBuilder() 57 | .baseUrl(base) 58 | .build(HelloService.class); 59 | 60 | 61 | String response = 62 | remoteApi.helloAsync("Programmer (Async)") 63 | .thenApply(String::toUpperCase) 64 | .toCompletableFuture() 65 | .get(); 66 | 67 | System.out.println("-------------------------------------------------------------------------"); 68 | System.out.println("Response: " + response); 69 | System.out.println("-------------------------------------------------------------------------"); 70 | 71 | assertTrue( 72 | response.contains("HELLO PROGRAMMER (ASYNC)!") 73 | ); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /rest-client/client-server-async/src/test/java/org/eclipse/microprofile14/restclient/clientserver/client/HelloService.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.clientserver.client; 3 | 4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 5 | 6 | import java.util.concurrent.CompletionStage; 7 | 8 | import javax.enterprise.context.RequestScoped; 9 | import javax.ws.rs.Consumes; 10 | import javax.ws.rs.GET; 11 | import javax.ws.rs.Path; 12 | import javax.ws.rs.PathParam; 13 | import javax.ws.rs.Produces; 14 | 15 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; 16 | 17 | /** 18 | * 19 | * @author Ondrej Mihalyi 20 | */ 21 | @Path("/api/hello") 22 | @RequestScoped 23 | @RegisterRestClient // Required to enable injection of this interface 24 | public interface HelloService { 25 | 26 | @GET 27 | @Path("{name}") 28 | @Produces(TEXT_PLAIN) 29 | @Consumes(TEXT_PLAIN) 30 | CompletionStage helloAsync(@PathParam("name") String name); 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /rest-client/client-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | org.eclipse.microprofile.samples14 8 | rest-client 9 | 1.0-SNAPSHOT 10 | 11 | 12 | client-server 13 | war 14 | 15 | MicroProfile 1.4: Rest Client - Client-server 16 | 17 | 18 | -------------------------------------------------------------------------------- /rest-client/client-server/src/main/java/org/eclipse/microprofile14/restclient/clientserver/config/ApplicationInit.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.clientserver.config; 3 | 4 | import javax.ws.rs.ApplicationPath; 5 | import javax.ws.rs.core.Application; 6 | 7 | @ApplicationPath("/api") 8 | public class ApplicationInit extends Application { 9 | 10 | } -------------------------------------------------------------------------------- /rest-client/client-server/src/main/java/org/eclipse/microprofile14/restclient/clientserver/remote/HelloRemoteResource.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.clientserver.remote; 3 | 4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 5 | 6 | import javax.ws.rs.Consumes; 7 | import javax.ws.rs.GET; 8 | import javax.ws.rs.Path; 9 | import javax.ws.rs.PathParam; 10 | import javax.ws.rs.Produces; 11 | 12 | @Path("/hello") 13 | @Produces(TEXT_PLAIN) 14 | @Consumes(TEXT_PLAIN) 15 | public class HelloRemoteResource { 16 | 17 | @GET 18 | @Path("{name}") 19 | public String hello(@PathParam("name") String name) { 20 | return "Hello " + name + "!"; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /rest-client/client-server/src/test/java/org/eclipse/microprofile14/restclient/clientserver/ClientServerTest.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.clientserver; 3 | 4 | import static org.jboss.shrinkwrap.api.ShrinkWrap.create; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import java.io.IOException; 8 | import java.net.URISyntaxException; 9 | import java.net.URL; 10 | 11 | import org.eclipse.microprofile.rest.client.RestClientBuilder; 12 | import org.eclipse.microprofile.rest.client.RestClientDefinitionException; 13 | import org.eclipse.microprofile14.restclient.clientserver.client.HelloService; 14 | import org.eclipse.microprofile14.restclient.clientserver.config.ApplicationInit; 15 | import org.eclipse.microprofile14.restclient.clientserver.remote.HelloRemoteResource; 16 | import org.jboss.arquillian.container.test.api.Deployment; 17 | import org.jboss.arquillian.container.test.api.RunAsClient; 18 | import org.jboss.arquillian.junit.Arquillian; 19 | import org.jboss.arquillian.test.api.ArquillianResource; 20 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 21 | import org.jboss.shrinkwrap.api.spec.WebArchive; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | 25 | /** 26 | * @author Arjan Tijms 27 | */ 28 | @RunWith(Arquillian.class) 29 | public class ClientServerTest { 30 | 31 | @ArquillianResource 32 | private URL base; 33 | 34 | @Deployment(testable = false) 35 | public static WebArchive createDeployment() { 36 | WebArchive archive = 37 | create(WebArchive.class) 38 | .addClasses( 39 | ApplicationInit.class, 40 | HelloRemoteResource.class 41 | ).addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") 42 | ; 43 | 44 | System.out.println("************************************************************"); 45 | System.out.println(archive.toString(true)); 46 | System.out.println("************************************************************"); 47 | 48 | return archive; 49 | } 50 | 51 | @Test 52 | @RunAsClient 53 | public void testClientServer() throws IOException, IllegalStateException, RestClientDefinitionException, URISyntaxException { 54 | 55 | HelloService remoteApi = RestClientBuilder.newBuilder() 56 | .baseUrl(base) 57 | .build(HelloService.class); 58 | 59 | String response = remoteApi.hello("Programmer"); 60 | 61 | 62 | 63 | System.out.println("-------------------------------------------------------------------------"); 64 | System.out.println("Response: " + response); 65 | System.out.println("-------------------------------------------------------------------------"); 66 | 67 | assertTrue( 68 | response.contains("Hello Programmer!") 69 | ); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /rest-client/client-server/src/test/java/org/eclipse/microprofile14/restclient/clientserver/client/HelloService.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.clientserver.client; 3 | 4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 5 | 6 | import javax.enterprise.context.RequestScoped; 7 | import javax.ws.rs.Consumes; 8 | import javax.ws.rs.GET; 9 | import javax.ws.rs.Path; 10 | import javax.ws.rs.PathParam; 11 | import javax.ws.rs.Produces; 12 | 13 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; 14 | 15 | /** 16 | * 17 | * @author Ondrej Mihalyi 18 | */ 19 | @Path("/api/hello") 20 | @RequestScoped 21 | @RegisterRestClient // Required to enable injection of this interface 22 | public interface HelloService { 23 | 24 | @GET 25 | @Path("{name}") 26 | @Produces(TEXT_PLAIN) 27 | @Consumes(TEXT_PLAIN) 28 | String hello(@PathParam("name") String name); 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /rest-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | org.eclipse.microprofile.samples14 8 | samples-parent 9 | 1.0-SNAPSHOT 10 | 11 | 12 | rest-client 13 | pom 14 | 15 | MicroProfile 1.4: Rest Client 16 | 17 | 18 | client-server 19 | client-server-async 20 | server-internal 21 | server-internal-async 22 | 23 | 24 | 25 | 26 | org.eclipse.microprofile.samples14 27 | test-utils 28 | ${project.version} 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /rest-client/server-internal-async/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | org.eclipse.microprofile.samples14 8 | rest-client 9 | 1.0-SNAPSHOT 10 | 11 | 12 | server-internal-async 13 | war 14 | 15 | MicroProfile 1.4: Rest Client - Server internal async 16 | 17 | 18 | -------------------------------------------------------------------------------- /rest-client/server-internal-async/src/main/java/org/eclipse/microprofile14/restclient/serverinternal/async/client/ClientResourceAsync.java: -------------------------------------------------------------------------------- 1 | package org.eclipse.microprofile14.restclient.serverinternal.async.client; 2 | 3 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 4 | 5 | import java.util.concurrent.CompletionStage; 6 | 7 | import javax.enterprise.context.RequestScoped; 8 | import javax.inject.Inject; 9 | import javax.ws.rs.GET; 10 | import javax.ws.rs.Path; 11 | import javax.ws.rs.Produces; 12 | 13 | import org.eclipse.microprofile.rest.client.inject.RestClient; 14 | 15 | @Path("clientAsync") 16 | @RequestScoped 17 | public class ClientResourceAsync { 18 | 19 | @Inject 20 | @RestClient 21 | private HelloService helloService; 22 | 23 | @GET 24 | @Produces(TEXT_PLAIN) 25 | public CompletionStage helloWorld() { 26 | return helloService.helloAsync("World (Async)").thenApply(String::toUpperCase); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /rest-client/server-internal-async/src/main/java/org/eclipse/microprofile14/restclient/serverinternal/async/client/HelloService.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.serverinternal.async.client; 3 | 4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 5 | 6 | import java.util.concurrent.CompletionStage; 7 | 8 | import javax.enterprise.context.RequestScoped; 9 | import javax.ws.rs.Consumes; 10 | import javax.ws.rs.GET; 11 | import javax.ws.rs.Path; 12 | import javax.ws.rs.PathParam; 13 | import javax.ws.rs.Produces; 14 | 15 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; 16 | 17 | /** 18 | * 19 | * @author Ondrej Mihalyi 20 | */ 21 | @Path("/api/hello") 22 | @RequestScoped 23 | @RegisterRestClient // Required to enable injection of this interface 24 | public interface HelloService { 25 | 26 | @GET 27 | @Path("{name}") 28 | @Produces(TEXT_PLAIN) 29 | @Consumes(TEXT_PLAIN) 30 | CompletionStage helloAsync(@PathParam("name") String name); 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /rest-client/server-internal-async/src/main/java/org/eclipse/microprofile14/restclient/serverinternal/async/config/ApplicationInit.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.serverinternal.async.config; 3 | 4 | import javax.ws.rs.ApplicationPath; 5 | import javax.ws.rs.core.Application; 6 | 7 | @ApplicationPath("/api") 8 | public class ApplicationInit extends Application { 9 | 10 | } -------------------------------------------------------------------------------- /rest-client/server-internal-async/src/main/java/org/eclipse/microprofile14/restclient/serverinternal/async/config/URLServiceConfigSource.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.serverinternal.async.config; 3 | 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import javax.enterprise.inject.spi.CDI; 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | import org.eclipse.microprofile.config.spi.ConfigSource; 11 | import org.eclipse.microprofile14.restclient.serverinternal.async.client.HelloService; 12 | 13 | /** 14 | * This config source provides the URL MP Rest Client needs to locate the endpoint corresponding 15 | * to the {@link HelloService} interface. 16 | * 17 | * @author Arjan Tijms 18 | * 19 | */ 20 | public class URLServiceConfigSource implements ConfigSource { 21 | 22 | @Override 23 | public Map getProperties() { 24 | Map properties = new HashMap<>(); 25 | properties.put(HelloService.class + "/mp-rest/url", ""); 26 | return properties; 27 | } 28 | 29 | @Override 30 | public String getValue(String propertyName) { 31 | if (propertyName.equals(HelloService.class.getName() + "/mp-rest/url")) { 32 | 33 | try { 34 | HttpServletRequest request = CDI.current().select(HttpServletRequest.class).get(); 35 | 36 | StringBuffer url = request.getRequestURL(); 37 | String uri = request.getRequestURI(); 38 | 39 | return url.substring(0, url.length() - uri.length() + request.getContextPath().length()) + "/"; 40 | } catch (Exception e) { 41 | // Ignore, thrown when the key is requested ahead of a request 42 | } 43 | } 44 | 45 | return null; 46 | } 47 | 48 | @Override 49 | public String getName() { 50 | return "URLServiceConfigSource"; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /rest-client/server-internal-async/src/main/java/org/eclipse/microprofile14/restclient/serverinternal/async/remote/HelloRemoteResource.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.serverinternal.async.remote; 3 | 4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 5 | 6 | import javax.ws.rs.Consumes; 7 | import javax.ws.rs.GET; 8 | import javax.ws.rs.Path; 9 | import javax.ws.rs.PathParam; 10 | import javax.ws.rs.Produces; 11 | 12 | @Path("/hello") 13 | @Produces(TEXT_PLAIN) 14 | @Consumes(TEXT_PLAIN) 15 | public class HelloRemoteResource { 16 | 17 | @GET 18 | @Path("{name}") 19 | public String hello(@PathParam("name") String name) { 20 | return "Hello " + name + "!"; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /rest-client/server-internal-async/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource: -------------------------------------------------------------------------------- 1 | org.eclipse.microprofile14.restclient.serverinternal.async.config.URLServiceConfigSource 2 | -------------------------------------------------------------------------------- /rest-client/server-internal-async/src/test/java/org/eclipse/microprofile14/restclient/serverinternal/async/ServerInternalAsyncTest.java: -------------------------------------------------------------------------------- 1 | package org.eclipse.microprofile14.restclient.serverinternal.async; 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.microprofile14.restclient.serverinternal.async.client.ClientResourceAsync; 13 | import org.eclipse.microprofile14.restclient.serverinternal.async.client.HelloService; 14 | import org.eclipse.microprofile14.restclient.serverinternal.async.config.ApplicationInit; 15 | import org.eclipse.microprofile14.restclient.serverinternal.async.config.URLServiceConfigSource; 16 | import org.eclipse.microprofile14.restclient.serverinternal.async.remote.HelloRemoteResource; 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.spec.WebArchive; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | 25 | /** 26 | * @author Arjan Tijms 27 | */ 28 | @RunWith(Arquillian.class) 29 | public class ServerInternalAsyncTest { 30 | 31 | @ArquillianResource 32 | private URL base; 33 | 34 | @Deployment(testable = false) 35 | public static WebArchive createDeployment() { 36 | WebArchive archive = 37 | create(WebArchive.class) 38 | .addClasses( 39 | ApplicationInit.class, 40 | URLServiceConfigSource.class, 41 | HelloRemoteResource.class, 42 | ClientResourceAsync.class, 43 | HelloService.class 44 | ).addAsResource( 45 | "META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource" 46 | ) 47 | ; 48 | 49 | System.out.println("************************************************************"); 50 | System.out.println(archive.toString(true)); 51 | System.out.println("************************************************************"); 52 | 53 | return archive; 54 | } 55 | 56 | @Test 57 | @RunAsClient 58 | public void testServerInternalAsync() throws IOException { 59 | 60 | String response = 61 | newClient() 62 | .target( 63 | URI.create(new URL(base, "api/clientAsync").toExternalForm())) 64 | .request(TEXT_PLAIN) 65 | .get(String.class); 66 | 67 | System.out.println("-------------------------------------------------------------------------"); 68 | System.out.println("Response: " + response); 69 | System.out.println("-------------------------------------------------------------------------"); 70 | 71 | assertTrue( 72 | response.contains("HELLO WORLD (ASYNC)!") 73 | ); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /rest-client/server-internal/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | org.eclipse.microprofile.samples14 8 | rest-client 9 | 1.0-SNAPSHOT 10 | 11 | 12 | server-internal 13 | war 14 | 15 | MicroProfile 1.4: Rest Client - Server internal 16 | 17 | 18 | -------------------------------------------------------------------------------- /rest-client/server-internal/src/main/java/org/eclipse/microprofile14/restclient/serverinternal/client/ClientResource.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.serverinternal.client; 3 | 4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 5 | 6 | import javax.enterprise.context.RequestScoped; 7 | import javax.inject.Inject; 8 | import javax.ws.rs.GET; 9 | import javax.ws.rs.Path; 10 | import javax.ws.rs.Produces; 11 | 12 | import org.eclipse.microprofile.rest.client.inject.RestClient; 13 | 14 | @Path("client") 15 | @RequestScoped 16 | public class ClientResource { 17 | 18 | @Inject 19 | @RestClient 20 | private HelloService helloService; 21 | 22 | @GET 23 | @Produces(TEXT_PLAIN) 24 | public String helloWorld() { 25 | return helloService.hello("World"); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /rest-client/server-internal/src/main/java/org/eclipse/microprofile14/restclient/serverinternal/client/HelloService.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.serverinternal.client; 3 | 4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 5 | 6 | import javax.enterprise.context.RequestScoped; 7 | import javax.ws.rs.Consumes; 8 | import javax.ws.rs.GET; 9 | import javax.ws.rs.Path; 10 | import javax.ws.rs.PathParam; 11 | import javax.ws.rs.Produces; 12 | 13 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; 14 | 15 | /** 16 | * 17 | * @author Ondrej Mihalyi 18 | */ 19 | @Path("/api/hello") 20 | @RequestScoped 21 | @RegisterRestClient // Required to enable injection of this interface 22 | public interface HelloService { 23 | 24 | @GET 25 | @Path("{name}") 26 | @Produces(TEXT_PLAIN) 27 | @Consumes(TEXT_PLAIN) 28 | String hello(@PathParam("name") String name); 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /rest-client/server-internal/src/main/java/org/eclipse/microprofile14/restclient/serverinternal/config/ApplicationInit.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.serverinternal.config; 3 | 4 | import javax.ws.rs.ApplicationPath; 5 | import javax.ws.rs.core.Application; 6 | 7 | @ApplicationPath("/api") 8 | public class ApplicationInit extends Application { 9 | 10 | } -------------------------------------------------------------------------------- /rest-client/server-internal/src/main/java/org/eclipse/microprofile14/restclient/serverinternal/config/URLServiceConfigSource.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.serverinternal.config; 3 | 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import javax.enterprise.inject.spi.CDI; 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | import org.eclipse.microprofile.config.spi.ConfigSource; 11 | import org.eclipse.microprofile14.restclient.serverinternal.client.HelloService; 12 | 13 | /** 14 | * This config source provides the URL MP Rest Client needs to locate the endpoint corresponding 15 | * to the {@link HelloService} interface. 16 | * 17 | * @author Arjan Tijms 18 | * 19 | */ 20 | public class URLServiceConfigSource implements ConfigSource { 21 | 22 | @Override 23 | public Map getProperties() { 24 | Map properties = new HashMap<>(); 25 | properties.put(HelloService.class + "/mp-rest/url", ""); 26 | return properties; 27 | } 28 | 29 | @Override 30 | public String getValue(String propertyName) { 31 | if (propertyName.equals(HelloService.class.getName() + "/mp-rest/url")) { 32 | 33 | try { 34 | HttpServletRequest request = CDI.current().select(HttpServletRequest.class).get(); 35 | 36 | StringBuffer url = request.getRequestURL(); 37 | String uri = request.getRequestURI(); 38 | 39 | return url.substring(0, url.length() - uri.length() + request.getContextPath().length()) + "/"; 40 | } catch (Exception e) { 41 | // Ignore, thrown when the key is requested ahead of a request 42 | } 43 | } 44 | 45 | return null; 46 | } 47 | 48 | @Override 49 | public String getName() { 50 | return "URLServiceConfigSource"; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /rest-client/server-internal/src/main/java/org/eclipse/microprofile14/restclient/serverinternal/remote/HelloRemoteResource.java: -------------------------------------------------------------------------------- 1 | /** Copyright Payara Services Limited **/ 2 | package org.eclipse.microprofile14.restclient.serverinternal.remote; 3 | 4 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN; 5 | 6 | import javax.ws.rs.Consumes; 7 | import javax.ws.rs.GET; 8 | import javax.ws.rs.Path; 9 | import javax.ws.rs.PathParam; 10 | import javax.ws.rs.Produces; 11 | 12 | @Path("/hello") 13 | @Produces(TEXT_PLAIN) 14 | @Consumes(TEXT_PLAIN) 15 | public class HelloRemoteResource { 16 | 17 | @GET 18 | @Path("{name}") 19 | public String hello(@PathParam("name") String name) { 20 | return "Hello " + name + "!"; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /rest-client/server-internal/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource: -------------------------------------------------------------------------------- 1 | org.eclipse.microprofile14.restclient.serverinternal.config.URLServiceConfigSource 2 | -------------------------------------------------------------------------------- /rest-client/server-internal/src/test/java/org/eclipse/microprofile14/restclient/serverinternal/ServerInternalTest.java: -------------------------------------------------------------------------------- 1 | package org.eclipse.microprofile14.restclient.serverinternal; 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.microprofile14.restclient.serverinternal.client.ClientResource; 13 | import org.eclipse.microprofile14.restclient.serverinternal.client.HelloService; 14 | import org.eclipse.microprofile14.restclient.serverinternal.config.ApplicationInit; 15 | import org.eclipse.microprofile14.restclient.serverinternal.config.URLServiceConfigSource; 16 | import org.eclipse.microprofile14.restclient.serverinternal.remote.HelloRemoteResource; 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.spec.WebArchive; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | 25 | /** 26 | * @author Arjan Tijms 27 | */ 28 | @RunWith(Arquillian.class) 29 | public class ServerInternalTest { 30 | 31 | @ArquillianResource 32 | private URL base; 33 | 34 | @Deployment(testable = false) 35 | public static WebArchive createDeployment() { 36 | WebArchive archive = 37 | create(WebArchive.class) 38 | .addClasses( 39 | ApplicationInit.class, 40 | URLServiceConfigSource.class, 41 | HelloRemoteResource.class, 42 | ClientResource.class, 43 | HelloService.class 44 | ).addAsResource( 45 | "META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource" 46 | ) 47 | ; 48 | 49 | System.out.println("************************************************************"); 50 | System.out.println(archive.toString(true)); 51 | System.out.println("************************************************************"); 52 | 53 | return archive; 54 | } 55 | 56 | @Test 57 | @RunAsClient 58 | public void testServerInternal() throws IOException { 59 | 60 | String response = 61 | newClient() 62 | .target( 63 | URI.create(new URL(base, "api/client").toExternalForm())) 64 | .request(TEXT_PLAIN) 65 | .get(String.class); 66 | 67 | System.out.println("-------------------------------------------------------------------------"); 68 | System.out.println("Response: " + response); 69 | System.out.println("-------------------------------------------------------------------------"); 70 | 71 | assertTrue( 72 | response.contains("Hello World!") 73 | ); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /test-utils/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /test-utils/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | org.eclipse.microprofile.samples14 8 | samples-parent 9 | 1.0-SNAPSHOT 10 | 11 | 12 | test-utils 13 | MicroProfile 1.4: test-utils 14 | 15 | 16 | 17 | junit 18 | junit 19 | 4.12 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 | 7.1 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test-utils/src/main/java/org/eclipse/microprofile14/CliCommands.java: -------------------------------------------------------------------------------- 1 | package org.eclipse.microprofile14; 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/microprofile14/JwtTokenGenerator.java: -------------------------------------------------------------------------------- 1 | package org.eclipse.microprofile14; 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/microprofile14/Libraries.java: -------------------------------------------------------------------------------- 1 | package org.eclipse.microprofile14; 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/microprofile14/Parameter.java: -------------------------------------------------------------------------------- 1 | package org.eclipse.microprofile14; 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/microprofile14/ParameterRule.java: -------------------------------------------------------------------------------- 1 | package org.eclipse.microprofile14; 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/microprofile14/ServerOperations.java: -------------------------------------------------------------------------------- 1 | package org.eclipse.microprofile14; 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.4-samples/0be7890237d6cdc403d2c89ce5133a57d2c7bf16/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 | --------------------------------------------------------------------------------