This is an automated email from the ASF dual-hosted git repository. radcortez pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomee.git
commit d5bf79a2dd6ac568e17b58ce0b3beed6c1b5cf1c Author: Mariani Federico <[email protected]> AuthorDate: Fri Dec 28 19:42:12 2018 +0100 TOMEE-2428 --- examples/mp-jsonb-configuration/README.md | 275 +++++++++++++++++++++ examples/mp-jsonb-configuration/pom.xml | 63 +++++ .../main/java/org/superbiz/JAXRSApplication.java | 9 + .../main/java/org/superbiz/JSONBConfiguration.java | 31 +++ .../src/main/java/org/superbiz/model/User.java | 53 ++++ .../main/java/org/superbiz/rest/UserService.java | 31 +++ .../src/main/webapp/WEB-INF/web.xml | 23 ++ .../java/org/superbiz/rest/UserServiceTest.java | 42 ++++ 8 files changed, 527 insertions(+) diff --git a/examples/mp-jsonb-configuration/README.md b/examples/mp-jsonb-configuration/README.md new file mode 100644 index 0000000..e070050 --- /dev/null +++ b/examples/mp-jsonb-configuration/README.md @@ -0,0 +1,275 @@ +index-group=Unrevised +type=page +status=published +~~~~~~ + +This examples shows how to customize jsonb for a JAX-RS Application. JSONB is the new javaee-api:8.0 standard for json serialization/deserialization. Few annotations are needed and JsonbConfig offers many configurations. + +## Run and test Endpoint + +the application can be run with 'mvn clean install tomee:run' if port 8080 is available you can invoke the following endpoint: (GET) http://localhost:8080/mp-jsonb-configuration/api/users that should respond with the following json: +[ + { + "Id":1, + "Name":"user 1", + "Registration":"2018 - 12 - 28" + }, + { + "Id":2, + "Name":"user 2", + "Registration":"2018 - 12 - 28" + } +] + +## @ApplicationPath + +JAXRS entry point class, as follows jaxrs will load all the annotated @Path classes and methods without specifying them. + + import javax.ws.rs.ApplicationPath; + import javax.ws.rs.core.Application; + + @ApplicationPath("api") + public class JAXRSApplication extends Application { + + } + +## @Path Rest resource + +Simple jaxrs class with a GET endpoint + + import java.util.ArrayList; + import java.util.List; + + import javax.ejb.Stateless; + import javax.ws.rs.Consumes; + import javax.ws.rs.GET; + import javax.ws.rs.Path; + import javax.ws.rs.Produces; + import javax.ws.rs.core.MediaType; + + import org.superbiz.model.User; + + @Path("users") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Stateless + public class UserService { + + @GET + public List<User> users() { + List<User> users = new ArrayList<>(); + User user1 = new User(1, "user 1"); + User user2 = new User(2, "user 2"); + users.add(user1); + users.add(user2); + + return users; + } + } + +## JSONB Configuration + +Implementing ContextResolver<> you can customize jaxrs defaults, in this example we are going to customize JSONB serialization/deserialization + + import javax.json.bind.Jsonb; + import javax.json.bind.JsonbBuilder; + import javax.json.bind.JsonbConfig; + import javax.json.bind.config.PropertyNamingStrategy; + import javax.ws.rs.ext.ContextResolver; + import javax.ws.rs.ext.Provider; + + @Provider + public class JSONBConfiguration implements ContextResolver<Jsonb> { + + private Jsonb jsonb; + + public JSONBConfiguration() { + // jsonbConfig offers a lot of configurations. + JsonbConfig config = new JsonbConfig().withFormatting(true) + .withPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE) + .withDateFormat("yyyy - MM - dd", Locale.ENGLISH); + + jsonb = JsonbBuilder.create(config); + } + + @Override + public Jsonb getContext(Class<?> type) { + return jsonb; + } + + } + +JsonbConfig offers many configurations. + +## Accessing the rest endpoint + +The test spin up an openejb webapp and invoke the users endpoint + + import java.io.IOException; + import java.text.SimpleDateFormat; + import java.util.Date; + + import org.apache.cxf.jaxrs.client.WebClient; + import org.apache.openejb.jee.WebApp; + import org.apache.openejb.junit.ApplicationComposer; + import org.apache.openejb.testing.Classes; + import org.apache.openejb.testing.EnableServices; + import org.apache.openejb.testing.Module; + import org.junit.Assert; + import org.junit.Test; + import org.junit.runner.RunWith; + import org.superbiz.JAXRSApplication; + import org.superbiz.JSONBConfiguration; + + @EnableServices(value = "jaxrs") + @RunWith(ApplicationComposer.class) + public class UserServiceTest { + + @Module + @Classes({ UserService.class, JAXRSApplication.class, JSONBConfiguration.class }) + public WebApp app() { + return new WebApp().contextRoot("test"); + } + + @Test + public void get() throws IOException { + final String message = WebClient.create("http://localhost:4204").path("/test/api/users").get(String.class); + System.out.println(message); + + final SimpleDateFormat sdf = new SimpleDateFormat("yyyy - MM - dd"); + + // test withDateFormat("yyyy - MM - dd") + Assert.assertTrue(message.contains(sdf.format(new Date()))); + // test withFormatting(true) + Assert.assertTrue(message.contains(System.getProperty("line.separator"))); + } + + } + +# Running + +Running the example can be done from maven with a simple 'mvn clean install' command run from the 'mp-jsonb-configuration' directory. + +When run you should see output similar to the following. + + ------------------------------------------------------- + T E S T S + ------------------------------------------------------- + Running org.superbiz.rest.UserServiceTest + INFO - Created new singletonService org.apache.openejb.cdi.ThreadSingletonServiceImpl@7823a2f9 + INFO - Succeeded in installing singleton service + INFO - Cannot find the configuration file [conf/openejb.xml]. Will attempt to create one for the beans deployed. + INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) + INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) + INFO - Creating TransactionManager(id=Default Transaction Manager) + INFO - Creating SecurityService(id=Default Security Service) + INFO - Initializing network services + INFO - Creating ServerService(id=cxf-rs) + INFO - Creating ServerService(id=httpejbd) + INFO - Created ServicePool 'httpejbd' with (10) core threads, limited to (200) threads with a queue of (9) + INFO - Initializing network services + INFO - ** Bound Services ** + INFO - NAME IP PORT + INFO - httpejbd 127.0.0.1 4204 + INFO - ------- + INFO - Ready! + INFO - Configuring enterprise application: /home/federico/Documents/PRIVATO/Apache/tomee/examples/mp-jsonb-configuration/UserServiceTest + INFO - Auto-deploying ejb UserService: EjbDeployment(deployment-id=UserService) + INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) + INFO - Auto-creating a container for bean org.superbiz.rest.UserServiceTest: Container(type=MANAGED, id=Default Managed Container) + INFO - Creating Container(id=Default Managed Container) + INFO - Using directory /tmp for stateful session passivation + INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container) + INFO - Auto-creating a container for bean UserService: Container(type=STATELESS, id=Default Stateless Container) + INFO - Creating Container(id=Default Stateless Container) + INFO - Enterprise application "/home/federico/Documents/PRIVATO/Apache/tomee/examples/mp-jsonb-configuration/UserServiceTest" loaded. + INFO - Creating dedicated application classloader for UserServiceTest + INFO - Assembling app: /home/federico/Documents/PRIVATO/Apache/tomee/examples/mp-jsonb-configuration/UserServiceTest + INFO - Jndi(name=UserServiceLocalBean) --> Ejb(deployment-id=UserService) + INFO - Jndi(name=global/test/UserService!org.superbiz.rest.UserService) --> Ejb(deployment-id=UserService) + INFO - Jndi(name=global/test/UserService) --> Ejb(deployment-id=UserService) + INFO - Created Ejb(deployment-id=UserService, ejb-name=UserService, container=Default Stateless Container) + INFO - Started Ejb(deployment-id=UserService, ejb-name=UserService, container=Default Stateless Container) + INFO - Using readers: + INFO - org.apache.cxf.jaxrs.provider.PrimitiveTextProvider@2f94c4db + INFO - org.apache.cxf.jaxrs.provider.FormEncodingProvider@6b5966e1 + INFO - org.apache.cxf.jaxrs.provider.MultipartProvider@65e61854 + INFO - org.apache.cxf.jaxrs.provider.SourceProvider@1568159 + INFO - org.apache.cxf.jaxrs.provider.JAXBElementTypedProvider@4fcee388 + INFO - org.apache.cxf.jaxrs.provider.JAXBElementProvider@6f80fafe + INFO - org.apache.openejb.server.cxf.rs.johnzon.TomEEJsonbProvider@63cd604c + INFO - org.apache.openejb.server.cxf.rs.johnzon.TomEEJsonpProvider@593e824f + INFO - org.apache.cxf.jaxrs.provider.StringTextProvider@72ccd81a + INFO - org.apache.cxf.jaxrs.provider.BinaryDataProvider@6d8792db + INFO - org.apache.cxf.jaxrs.provider.DataSourceProvider@64bc21ac + INFO - Using writers: + INFO - org.apache.johnzon.jaxrs.WadlDocumentMessageBodyWriter@493dfb8e + INFO - org.apache.cxf.jaxrs.nio.NioMessageBodyWriter@5d25e6bb + INFO - org.apache.cxf.jaxrs.provider.StringTextProvider@72ccd81a + INFO - org.apache.cxf.jaxrs.provider.JAXBElementTypedProvider@4fcee388 + INFO - org.apache.cxf.jaxrs.provider.PrimitiveTextProvider@2f94c4db + INFO - org.apache.cxf.jaxrs.provider.FormEncodingProvider@6b5966e1 + INFO - org.apache.cxf.jaxrs.provider.MultipartProvider@65e61854 + INFO - org.apache.cxf.jaxrs.provider.SourceProvider@1568159 + INFO - org.apache.cxf.jaxrs.provider.JAXBElementProvider@6f80fafe + INFO - org.apache.openejb.server.cxf.rs.johnzon.TomEEJsonbProvider@63cd604c + INFO - org.apache.openejb.server.cxf.rs.johnzon.TomEEJsonpProvider@593e824f + INFO - org.apache.cxf.jaxrs.provider.BinaryDataProvider@6d8792db + INFO - org.apache.cxf.jaxrs.provider.DataSourceProvider@64bc21ac + INFO - Using exception mappers: + INFO - org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper@361c294e + INFO - org.apache.openejb.server.cxf.rs.EJBExceptionMapper@6fff253c + INFO - org.apache.cxf.jaxrs.validation.ValidationExceptionMapper@7859e786 + INFO - org.apache.openejb.server.cxf.rs.CxfRsHttpListener$CxfResponseValidationExceptionMapper@285d851a + INFO - REST Application: http://127.0.0.1:4204/test/api -> org.superbiz.JAXRSApplication@5af28b27 + INFO - Service URI: http://127.0.0.1:4204/test/api/users -> EJB org.superbiz.rest.UserService + INFO - GET http://127.0.0.1:4204/test/api/users -> List<User> users() + INFO - Deployed Application(path=/home/federico/Documents/PRIVATO/Apache/tomee/examples/mp-jsonb-configuration/UserServiceTest) + [ + { + "Id":1, + "Name":"user 1", + "Registration":"2018 - 12 - 28" + }, + { + "Id":2, + "Name":"user 2", + "Registration":"2018 - 12 - 28" + } + ] + INFO - Undeploying app: /home/federico/Documents/PRIVATO/Apache/tomee/examples/mp-jsonb-configuration/UserServiceTest + INFO - Stopping network services + INFO - Stopping server services + Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.203 sec + + Results : + + Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 + +## Inside the jar + +javaee-api:8.0 brings in all the dependencies needed to spin up a working REST application. + +If we look at the jar built by maven, we'll see the application itself is quite small: + + $ jar tvf target/mp-jsonb-configuration-8.0.0-SNAPSHOT.war + 0 Fri Dec 28 19:36:10 CET 2018 META-INF/ + 134 Fri Dec 28 19:36:08 CET 2018 META-INF/MANIFEST.MF + 0 Fri Dec 28 19:36:08 CET 2018 WEB-INF/ + 0 Fri Dec 28 19:36:08 CET 2018 WEB-INF/classes/ + 0 Fri Dec 28 19:36:08 CET 2018 WEB-INF/classes/org/ + 0 Fri Dec 28 19:36:08 CET 2018 WEB-INF/classes/org/superbiz/ + 0 Fri Dec 28 19:36:08 CET 2018 WEB-INF/classes/org/superbiz/model/ + 0 Fri Dec 28 19:36:08 CET 2018 WEB-INF/classes/org/superbiz/rest/ + 1165 Fri Dec 28 19:36:06 CET 2018 WEB-INF/classes/org/superbiz/model/User.class + 402 Fri Dec 28 19:36:06 CET 2018 WEB-INF/classes/org/superbiz/JAXRSApplication.class + 1194 Fri Dec 28 19:36:06 CET 2018 WEB-INF/classes/org/superbiz/rest/UserService.class + 1701 Fri Dec 28 19:36:06 CET 2018 WEB-INF/classes/org/superbiz/JSONBConfiguration.class + 1224 Fri Dec 28 18:28:32 CET 2018 WEB-INF/web.xml + 0 Fri Dec 28 19:36:10 CET 2018 META-INF/maven/ + 0 Fri Dec 28 19:36:10 CET 2018 META-INF/maven/org.superbiz/ + 0 Fri Dec 28 19:36:10 CET 2018 META-INF/maven/org.superbiz/mp-jsonb-configuration/ + 1791 Fri Dec 28 19:10:44 CET 2018 META-INF/maven/org.superbiz/mp-jsonb-configuration/pom.xml + 128 Fri Dec 28 19:36:08 CET 2018 META-INF/maven/org.superbiz/mp-jsonb-configuration/pom.properties + +This single jar could be deployed any any compliant Java EE implementation. In TomEE you'd simply place it in the `tomee.home/webapps/` directory. \ No newline at end of file diff --git a/examples/mp-jsonb-configuration/pom.xml b/examples/mp-jsonb-configuration/pom.xml new file mode 100644 index 0000000..5e01c9e --- /dev/null +++ b/examples/mp-jsonb-configuration/pom.xml @@ -0,0 +1,63 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>org.superbiz</groupId> + <artifactId>mp-jsonb-configuration</artifactId> + <version>8.0.0-SNAPSHOT</version> + <packaging>war</packaging> + <name>OpenEJB :: Examples :: Microprofile JSONB Configuration</name> + + <properties> + <version.javaee-api>8.0</version.javaee-api> + <tomee.version>${project.version}</tomee.version> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.tomee</groupId> + <artifactId>javaee-api</artifactId> + <version>${version.javaee-api}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.tomee</groupId> + <artifactId>openejb-cxf-rs</artifactId> + <version>8.0.0-SNAPSHOT</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.tomee.maven</groupId> + <artifactId>tomee-maven-plugin</artifactId> + <version>${project.version}</version> + <configuration> + <tomeeClassifier>microprofile</tomeeClassifier> + <context>${project.artifactId}</context> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.7.0</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file diff --git a/examples/mp-jsonb-configuration/src/main/java/org/superbiz/JAXRSApplication.java b/examples/mp-jsonb-configuration/src/main/java/org/superbiz/JAXRSApplication.java new file mode 100644 index 0000000..e3fdcfc --- /dev/null +++ b/examples/mp-jsonb-configuration/src/main/java/org/superbiz/JAXRSApplication.java @@ -0,0 +1,9 @@ +package org.superbiz; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +@ApplicationPath("api") +public class JAXRSApplication extends Application { + +} diff --git a/examples/mp-jsonb-configuration/src/main/java/org/superbiz/JSONBConfiguration.java b/examples/mp-jsonb-configuration/src/main/java/org/superbiz/JSONBConfiguration.java new file mode 100644 index 0000000..44bd414 --- /dev/null +++ b/examples/mp-jsonb-configuration/src/main/java/org/superbiz/JSONBConfiguration.java @@ -0,0 +1,31 @@ +package org.superbiz; + +import java.util.Locale; + +import javax.json.bind.Jsonb; +import javax.json.bind.JsonbBuilder; +import javax.json.bind.JsonbConfig; +import javax.json.bind.config.PropertyNamingStrategy; +import javax.ws.rs.ext.ContextResolver; +import javax.ws.rs.ext.Provider; + +@Provider +public class JSONBConfiguration implements ContextResolver<Jsonb> { + + private Jsonb jsonb; + + public JSONBConfiguration() { + // jsonbConfig offers a lot of configurations. + JsonbConfig config = new JsonbConfig().withFormatting(true) + .withPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE) + .withDateFormat("yyyy - MM - dd", Locale.ENGLISH); + + jsonb = JsonbBuilder.create(config); + } + + @Override + public Jsonb getContext(Class<?> type) { + return jsonb; + } + +} diff --git a/examples/mp-jsonb-configuration/src/main/java/org/superbiz/model/User.java b/examples/mp-jsonb-configuration/src/main/java/org/superbiz/model/User.java new file mode 100644 index 0000000..f001495 --- /dev/null +++ b/examples/mp-jsonb-configuration/src/main/java/org/superbiz/model/User.java @@ -0,0 +1,53 @@ +package org.superbiz.model; + +import java.util.Date; + +public class User { + + private Integer id; + private String name; + private Date registration = new Date(); + + public User(Integer id, String name) { + super(); + this.id = id; + this.name = name; + } + + /** + * @return the id + */ + public Integer getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Integer id) { + this.id = id; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + public Date getRegistration() { + return registration; + } + + public void setRegistration(Date registration) { + this.registration = registration; + } + +} diff --git a/examples/mp-jsonb-configuration/src/main/java/org/superbiz/rest/UserService.java b/examples/mp-jsonb-configuration/src/main/java/org/superbiz/rest/UserService.java new file mode 100644 index 0000000..17a327f --- /dev/null +++ b/examples/mp-jsonb-configuration/src/main/java/org/superbiz/rest/UserService.java @@ -0,0 +1,31 @@ +package org.superbiz.rest; + +import java.util.ArrayList; +import java.util.List; + +import javax.ejb.Stateless; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.superbiz.model.User; + +@Path("users") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +@Stateless +public class UserService { + + @GET + public List<User> users() { + List<User> users = new ArrayList<>(); + User user1 = new User(1, "user 1"); + User user2 = new User(2, "user 2"); + users.add(user1); + users.add(user2); + + return users; + } +} diff --git a/examples/mp-jsonb-configuration/src/main/webapp/WEB-INF/web.xml b/examples/mp-jsonb-configuration/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..a956ed6 --- /dev/null +++ b/examples/mp-jsonb-configuration/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> +<web-app xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" + metadata-complete="false" + version="2.5"> + + <display-name>Microprofile JSONB Configuration</display-name> +</web-app> \ No newline at end of file diff --git a/examples/mp-jsonb-configuration/src/test/java/org/superbiz/rest/UserServiceTest.java b/examples/mp-jsonb-configuration/src/test/java/org/superbiz/rest/UserServiceTest.java new file mode 100644 index 0000000..6ee1c24 --- /dev/null +++ b/examples/mp-jsonb-configuration/src/test/java/org/superbiz/rest/UserServiceTest.java @@ -0,0 +1,42 @@ +package org.superbiz.rest; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.cxf.jaxrs.client.WebClient; +import org.apache.openejb.jee.WebApp; +import org.apache.openejb.junit.ApplicationComposer; +import org.apache.openejb.testing.Classes; +import org.apache.openejb.testing.EnableServices; +import org.apache.openejb.testing.Module; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.superbiz.JAXRSApplication; +import org.superbiz.JSONBConfiguration; + +@EnableServices(value = "jaxrs") +@RunWith(ApplicationComposer.class) +public class UserServiceTest { + + @Module + @Classes({ UserService.class, JAXRSApplication.class, JSONBConfiguration.class }) + public WebApp app() { + return new WebApp().contextRoot("test"); + } + + @Test + public void get() throws IOException { + final String message = WebClient.create("http://localhost:4204").path("/test/api/users").get(String.class); + System.out.println(message); + + final SimpleDateFormat sdf = new SimpleDateFormat("yyyy - MM - dd"); + + // test withDateFormat("yyyy - MM - dd") + Assert.assertTrue(message.contains(sdf.format(new Date()))); + // test withFormatting(true) + Assert.assertTrue(message.contains(System.getProperty("line.separator"))); + } + +}
