[
{
"Id":1,
"Name":"user 1",
"Registration":"2018-12-28"
},
{
"Id":2,
"Name":"user 2",
"Registration":"2018-12-28"
}
]
Configuração JSON-B
Este exemplo mostra como customizar jsonb para uma aplicaçao JAX-RS. JSONB é o novo padrão jakartaee-api: 8.0 para json serialização/desserialização. São necessárias poucas anotações e o JsonbConfig oferece muitas configurações.
Executando e testando o Endpoint
O aplicativo pode ser executado com `mvn clean install tomee:run' se a porta 8080 está disponível, você pode chamar o seguinte terminal:(GET) http://localhost:8080/jsonb-configuration/api/users que deve responder com o seguinte json:
@ApplicationPath
Classe de ponto de entrada JAXRS, da seguinte maneira jaxrs carregará todas as classes e métodos @Path anotados sem especificá-los.
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
@ApplicationPath("api")
public class JAXRSApplication extends Application {
}
Recurso @Path Rest
Classe jaxrs simples com um endpoint GET
import java.util.ArrayList;
import java.util.List;
import jakarta.ejb.Stateless;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.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;
}
}
Configuração JSONB
Implementando ContextResolver<>, você pode personalizar os padrões jaxrs; neste exemplo, vamos personalizar a serialização/desserialização JSONB
import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbConfig;
import jakarta.json.bind.config.PropertyNamingStrategy;
import jakarta.ws.rs.ext.ContextResolver;
import jakarta.ws.rs.ext.Provider;
@Provider
public class JSONBConfiguration implements ContextResolver<Jsonb> {
private Jsonb jsonb;
public JSONBConfiguration() {
// jsonbConfig oferece muitas configurações.
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;
}
}
Acessando o endpoint rest
O teste implanta a aplicação web no TomEE embedded com o Arquillian e chama o endpoint do usuário
package org.superbiz.rest;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDate;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import org.apache.cxf.jaxrs.client.WebClient;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.superbiz.JAXRSApplication;
import org.superbiz.JSONBConfiguration;
import org.superbiz.model.User;
@RunWith(Arquillian.class)
public class UserServiceTest {
@ArquillianResource
private URL base;
@Deployment(testable = false)
public static WebArchive app() {
return ShrinkWrap.create(WebArchive.class)
.addClasses(UserService.class, JAXRSApplication.class, JSONBConfiguration.class, User.class);
}
@Test
public void get() throws IOException {
final String message = WebClient.create(base.toExternalForm()).path("api/users").get(String.class);
System.out.println(message);
String assertDate = LocalDate.of(2019, Month.JANUARY, 1)
.format(DateTimeFormatter.ofPattern("yyyy - MM - dd"));
System.out.println(assertDate);
// test withDateFormat("yyyy - MM - dd")
Assert.assertTrue(message.contains(assertDate));
// test withFormatting(true)
Assert.assertTrue(message.contains("\n"));
}
}
Executando
A execução do exemplo pode ser feita no maven com um simples comando `mvn clean install', executado no diretório `jsonb-configuration'.
Ao executar, você verá uma saída semelhante à seguinte.
Running org.superbiz.rest.UserServiceTest
INFO: Starting TomEE from: /tmp/arquillian-apache-tomee-23754
INFO: Starting Servlet engine: [Apache Tomcat/11.0.25]
INFO: Starting ProtocolHandler ["http-nio-52978"]
INFO: Configuring enterprise application: /path/to/tomee/examples/jsonb-configuration/target/tomee-embedded/0/3e85ced9-0908-4b9e-8993-d5f11b448e1a
INFO: Enterprise application "/path/to/tomee/examples/jsonb-configuration/target/tomee-embedded/0/3e85ced9-0908-4b9e-8993-d5f11b448e1a" loaded.
INFO: Deployed Application(path=/path/to/tomee/examples/jsonb-configuration/target/tomee-embedded/0/3e85ced9-0908-4b9e-8993-d5f11b448e1a)
INFO: Provider{clazz=org.superbiz.JSONBConfiguration, discovered=true, singleton=false}
INFO: REST Application: http://localhost:52978/3e85ced9-0908-4b9e-8993-d5f11b448e1a/api -> org.superbiz.JAXRSApplication
INFO: Service URI: http://localhost:52978/3e85ced9-0908-4b9e-8993-d5f11b448e1a/api/users -> EJB org.superbiz.rest.UserService
INFO: GET http://localhost:52978/3e85ced9-0908-4b9e-8993-d5f11b448e1a/api/users -> List<User> users()
[
{
"Id":1,
"Name":"user 1",
"Registration":"2019 - 01 - 01"
},
{
"Id":2,
"Name":"user 2",
"Registration":"2019 - 01 - 01"
}
]
2019 - 01 - 01
INFO: Undeploying app: /path/to/tomee/examples/jsonb-configuration/target/tomee-embedded/0/3e85ced9-0908-4b9e-8993-d5f11b448e1a
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.816 s -- in org.superbiz.rest.UserServiceTest
Results:
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Dentro do jar
jakartaee-api:8.0 traz todas as dependências necessárias para iniciar um aplicativo REST que esteja funcionando.
Se olharmos para o jar construído por maven, veremos que o aplicativo em si é bem pequeno:
$ jar tvf target/jsonb-configuration-10.0.0-M1-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/jsonb-configuration/
1791 Fri Dec 28 19:10:44 CET 2018 META-INF/maven/org.superbiz/jsonb-configuration/pom.xml
128 Fri Dec 28 19:36:08 CET 2018 META-INF/maven/org.superbiz/jsonb-configuration/pom.properties
Esse jar único pode ser implantado em qualquer Java EE compatível implementação. No TomEE, basta colocá-lo no diretório tomee.home/webapps/.