| :index-group: Unrevised |
| :jbake-type: page |
| :jbake-status: status=published |
| = Configurando JSON-B |
| |
| Este ejemplo muestra cómo personalizar jsonb para una aplicación JAX-RS. |
| JSONB es el nuevo estándar `javaee-api: 8.0` para la serialización / |
| deserialización de json. Se necesitan pocas anotaciones y `JsonbConfig` |
| ofrece muchas configuraciones. |
| |
| == Ejecuta y prueba el Endpoint |
| |
| la aplicación se puede ejecutar con `mvn clean install tomee: run` si el puerto |
| 8080 está disponible, puede invocar el siguiente endpoint: |
| |
| [source,bash] |
| ---- |
| $ curl -X GET http://localhost:8080/mp-jsonb-configuration/api/users |
| ---- |
| |
| que debería responder con el siguiente json: |
| |
| [source,bash] |
| ---- |
| [ |
| { |
| "Id":1, |
| "Name":"user 1", |
| "Registration":"2018 - 12 - 28" |
| }, |
| { |
| "Id":2, |
| "Name":"user 2", |
| "Registration":"2018 - 12 - 28" |
| } |
| ] |
| ---- |
| |
| == @ApplicationPath |
| |
| La clase de punto de entrada JAXRS, de la siguiente manera los jaxrs cargarán |
| todos las clases y métodos anotados con `@ Path` sin especificarlos. |
| |
| [source,java] |
| ---- |
| import javax.ws.rs.ApplicationPath; |
| import javax.ws.rs.core.Application; |
| |
| @ApplicationPath("api") |
| public class JAXRSApplication extends Application { |
| |
| } |
| ---- |
| |
| == @Path Recurso Rest |
| |
| Clase jaxrs simple con un método GET |
| |
| [source,java] |
| ---- |
| 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; |
| } |
| } |
| ---- |
| |
| == Configuració JSONB |
| |
| Implementando `ContextResolver <>` puede personalizar los valores |
| predeterminados de jaxrs, en este ejemplo, vamos a personalizar la |
| serialización / deserialización JSONB |
| |
| [source,java] |
| ---- |
| 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` ofrece muchas configuraciones. |
| |
| == Accediendo al recurso Rest |
| |
| La prueba activa una aplicación web openejb e invoca el recurso rest `/users` |
| |
| [source,java] |
| ---- |
| 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"))); |
| } |
| |
| } |
| ---- |
| |
| == Ejecutando |
| |
| Ejecutando el ejemplo se puede hacer desde maven con un simple comando `mvn clean install` ejecutado desde el directorio `mp-jsonb-configuration`. |
| |
| Cuando se ejecute, debería ver una salida similar a la siguiente: |
| |
| [source,console] |
| ---- |
| ------------------------------------------------------- |
| 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 |
| |
| ---- |
| |
| === Dentro del jar |
| |
| `javaee-api: 8.0` incorpora todas las dependencias necesarias para activar una aplicación REST que funcione. |
| |
| Si miramos el jar construido por maven, veremos que la aplicación en sí es bastante pequeña: |
| |
| [source,bash] |
| ---- |
| $ 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 |
| ---- |
| |
| Este jar individual podría desplegarse en cualquier implementación Java EE que cumpla con los requisitos. En TomEE simplemente lo colocaría en el directorio `${tomee.home}/webapps/`. |