jsr 339 - java api for restful web services
TRANSCRIPT
JSR 339 Java API for RESTful Web Services
GujavaSC / Adopt a JSRMembros do GujavaSCParticipação Adopt a JSRGrupo de estudos
ArtigosPalestras
O que é REST?
É um estilo arquitetural…
Estilo arquitetural???
É um estilo arquitetural…
Enxaimel
Telhado
Madeiras
Tijolos
EstiloArquitetural
RESTHTTP
CaracterísticasRecursos são identificados por um ID;Sem estado;Vincule as coisas;Múltiplas representações;Interface uniforme.
CaracterísticasRecursos são identificados por um ID;Sem estado;Vincule as coisas;Múltiplas representações;Interface uniforme.
Interface Uniforme
Verbos HTTP Ação
POST Cria um novo recurso
PUT Atualiza um recurso
DELETE Remove um recurso
GET Retorna um recurso
JAX-RS 1.xFinal Release em 2008Objetivos
Baseado em POJOCentralizado em HTTPIndependência de formatoIndependência de containerInclusão no Java EE 6
Exemplo JAX-RS 1.0@Path("books")public class BookResource {
@GET@Path("/year/{year}")@Produces(MediaType.APPLICATION_JSON)public Response listByYearAndName(@PathParam("year") Integer year,
@QueryParam("name") String name) {
List<Book> books = getListByYearAndName(year, name);ResponseBuilder rb = Response.ok(books);return rb.build();
}}
http://localhost:8080/rest-example/resources/books/year/2011?name=Book1
Exemplo JAX-RS 1.0
http://localhost:8080/rest-example/resources/books/year/2011?name=Book1
@Path("books")public class BookResource {
@GET@Path("/year/{year}")@Produces(MediaType.APPLICATION_JSON)public Response listByYearAndName(@PathParam("year") Integer year,
@QueryParam("name") String name) {
List<Book> books = getListByYearAndName(year, name);ResponseBuilder rb = Response.ok(books);return rb.build();
}}
Exemplo JAX-RS 1.0
http://localhost:8080/rest-example/resources/books/year/2011?name=Book1
@Path("books")public class BookResource {
@GET@Path("/year/{year}")@Produces(MediaType.APPLICATION_JSON)public Response listByYearAndName(@PathParam("year") Integer year,
@QueryParam("name") String name) {
List<Book> books = getListByYearAndName(year, name);ResponseBuilder rb = Response.ok(books);return rb.build();
}}
@Path("books")public class BookResource {
@GET@Path("/year/{year}")@Produces(MediaType.APPLICATION_JSON)public Response listByYearAndName(@PathParam("year") Integer year,
@QueryParam("name") String name) {
List<Book> books = getListByYearAndName(year, name);ResponseBuilder rb = Response.ok(books);return rb.build();
}}
Exemplo JAX-RS 1.0
http://localhost:8080/rest-example/resources/books/year/2011?name=Book1
Exemplo JAX-RS 1.0@Path("books")public class BookResource {
@GET@Path("/year/{year}")@Produces(MediaType.APPLICATION_JSON)public Response listByYearAndName(@PathParam("year") Integer year,
@QueryParam("name") String name) {
List<Book> books = getListByYearAndName(year, name);ResponseBuilder rb = Response.ok(books);return rb.build();
}}
http://localhost:8080/rest-example/resources/books/year/2011?name=Book1
Exemplo JAX-RS 1.0@Path("books")public class BookResource {
@GET@Path("/year/{year}")@Produces(MediaType.APPLICATION_JSON)public Response listByYearAndName(@PathParam("year") Integer year,
@QueryParam("name") String name) {
List<Book> books = getListByYearAndName(year, name);ResponseBuilder rb = Response.ok(books);return rb.build();
}}
http://localhost:8080/rest-example/resources/books/year/2011?name=Book1
Exemplo JAX-RS 1.0@Path("books")public class BookResource {
@GET@Path("/year/{year}")@Produces(MediaType.APPLICATION_JSON)public Response listByYearAndName(@PathParam("year") Integer year,
@QueryParam("name") String name) {
List<Book> books = getListByYearAndName(year, name);ResponseBuilder rb = Response.ok(books);return rb.build();
}}
http://localhost:8080/rest-example/resources/books/year/2011?name=Book1
Exemplo JAX-RS 1.0@Path("books")public class BookResource {
@GET@Path("/year/{year}")@Produces(MediaType.APPLICATION_JSON)public Response listByYearAndName(@PathParam("year") Integer year,
@QueryParam("name") String name) {
List<Book> books = getListByYearAndName(year, name);ResponseBuilder rb = Response.ok(books);return rb.build();
}}
http://localhost:8080/rest-example/resources/books/year/2011?name=Book1
Exemplo JAX-RS 1.0@Path("books")public class BookResource {
@GET@Path("/year/{year}")@Produces(MediaType.APPLICATION_JSON)public Response listByYearAndName(@PathParam("year") Integer year,
@QueryParam("name") String name) {
List<Book> books = getListByYearAndName(year, name);ResponseBuilder rb = Response.ok(books);return rb.build();
}}
http://localhost:8080/rest-example/resources/books/year/2011?name=Book1
Exemplo JAX-RS 1.0@Path("books")public class BookResource {
@GET@Path("/year/{year}")@Produces(MediaType.APPLICATION_JSON)public List<Book> listByYearAndName(@PathParam("year") Integer year,
@QueryParam("name") String name) {
List<Book> books = getListByYearAndName(year, name);// ResponseBuilder rb = Response.ok(books);// return rb.build();return books;
}}
http://localhost:8080/rest-example/resources/books/year/2011?name=Book1
JAX-RS 2.0 Final Release em Maio de 2013Solicitações (JSR 339)
Client APIAsynchronous processingFilters / InterceptorsBean ValidationHypermediaMVC
Client API
Client APIBaseada na API do Jersey (versão 1.x);Consumir serviços criados em qualquer linguagem.
Qual é o recurso?
Book!
Como foi exposto?
@Path("books")
public class BookResource {
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response read(@PathParam("id") Integer id) {
return Response.ok(readObject(id)).build();
}
}
http://localhost:8080/rest-example/resources/books/10
Como consultávamos?
@Test
public void deveConterOLivro_javaee6() throws Exception {
URL url = new URL("http://localhost:8080/rest-example/resources/books/10");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
String result = IOUtils.toString(con.getInputStream(), "UTF-8");
con.disconnect();
Book book = new Gson().fromJson(result, Book.class);
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee6() throws Exception {
URL url = new URL("http://localhost:8080/rest-example/resources/books/10");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
String result = IOUtils.toString(con.getInputStream(), "UTF-8");
con.disconnect();
Book book = new Gson().fromJson(result, Book.class);
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee6() throws Exception {
URL url = new URL("http://localhost:8080/rest-example/resources/books/10");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
String result = IOUtils.toString(con.getInputStream(), "UTF-8");
con.disconnect();
Book book = new Gson().fromJson(result, Book.class);
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee6() throws Exception {
URL url = new URL("http://localhost:8080/rest-example/resources/books/10");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
String result = IOUtils.toString(con.getInputStream(), "UTF-8");
con.disconnect();
Book book = new Gson().fromJson(result, Book.class);
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee6() throws Exception {
URL url = new URL("http://localhost:8080/rest-example/resources/books/10");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
String result = IOUtils.toString(con.getInputStream(), "UTF-8");
con.disconnect();
Book book = new Gson().fromJson(result, Book.class);
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee6() throws Exception {
URL url = new URL("http://localhost:8080/rest-example/resources/books/10");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
String result = IOUtils.toString(con.getInputStream(), "UTF-8");
con.disconnect();
Book book = new Gson().fromJson(result, Book.class);
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee6() throws Exception {
URL url = new URL("http://localhost:8080/rest-example/resources/books/10");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
String result = IOUtils.toString(con.getInputStream(), "UTF-8");
con.disconnect();
Book book = new Gson().fromJson(result, Book.class);
assertThat(book, notNullValue());
}
GSON, Jackson, Jettison, XStream
@Test
public void deveConterOLivro_javaee6() throws Exception {
URL url = new URL("http://localhost:8080/rest-example/resources/books/10");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
String result = IOUtils.toString(con.getInputStream(), "UTF-8");
con.disconnect();
Book book = new Gson().fromJson(result, Book.class);
assertThat(book, notNullValue());
}
E agora com a Client API?
@Test
public void deveConterOLivro_javaee7() {
Client client = ClientBuilder.newClient();
WebTarget target =
client.target("http://localhost:8080/rest-example/resources");
WebTarget path = target.path("books/{id}");
WebTarget bookId = path.resolveTemplate("id", "10");
Builder invocation = bookId.request();
Book book = invocation.get(Book.class);
client.close();
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee7() {
Client client = ClientBuilder.newClient();
WebTarget target =
client.target("http://localhost:8080/rest-example/resources");
WebTarget path = target.path("books/{id}");
WebTarget bookId = path.resolveTemplate("id", "10");
Builder invocation = bookId.request();
Book book = invocation.get(Book.class);
client.close();
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee7() {
Client client = ClientBuilder.newClient();
WebTarget target =
client.target("http://localhost:8080/rest-example/resources");
WebTarget path = target.path("books/{id}");
WebTarget bookId = path.resolveTemplate("id", "10");
Builder invocation = bookId.request();
Book book = invocation.get(Book.class);
client.close();
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee7() {
Client client = ClientBuilder.newClient();
WebTarget target =
client.target("http://localhost:8080/rest-example/resources");
WebTarget path = target.path("books/{id}"); WebTarget bookId = path.resolveTemplate("id", "10");
Builder invocation = bookId.request();
Book book = invocation.get(Book.class);
client.close();
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee7() {
Client client = ClientBuilder.newClient();
WebTarget target =
client.target("http://localhost:8080/rest-example/resources");
WebTarget path = target.path("books/{id}");
WebTarget bookId = path.resolveTemplate("id", "10");
Builder invocation = bookId.request();
Book book = invocation.get(Book.class);
client.close();
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee7() {
Client client = ClientBuilder.newClient();
WebTarget target =
client.target("http://localhost:8080/rest-example/resources");
WebTarget path = target.path("books/{id}");
WebTarget bookId = path.resolveTemplate("id", "10");
Builder invocation = bookId.request();
Book book = invocation.get(Book.class);
client.close();
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee7() {
Client client = ClientBuilder.newClient();
WebTarget target =
client.target("http://localhost:8080/rest-example/resources");
WebTarget path = target.path("books/{id}");
WebTarget bookId = path.resolveTemplate("id", "10");
Builder invocation = bookId.request();
Book book = invocation.get(Book.class);
client.close();
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee7() {
Client client = ClientBuilder.newClient();
WebTarget target =
client.target("http://localhost:8080/rest-example/resources");
WebTarget path = target.path("books/{id}");
WebTarget bookId = path.resolveTemplate("id", "10");
Builder invocation = bookId.request();
Book book = invocation.get(Book.class);
client.close();
assertThat(book, notNullValue());
}
@Test
public void deveConterOLivro_javaee7() {
Client client = ClientBuilder.newClient();
WebTarget target =
client.target("http://localhost:8080/rest-example/resources");
WebTarget path = target.path("books/{id}");
WebTarget bookId = path.resolveTemplate("id", "10");
Builder invocation = bookId.request();
Book book = invocation.get(Book.class);
client.close();
assertThat(book, notNullValue());
}
...“um pouco” mais fluente...
@Test
public void deveConterOLivro_javaee7() {
Client client = ClientBuilder.newClient();
Book book = client.target("http://localhost:8080/rest-example/resources")
.path("books/{id}")
.resolveTemplate("id", "10")
.request()
.get(Book.class);
client.close();
assertThat(book, notNullValue());
}
...@Delete...
@Test
public void deletarOLivro_javaee7() {
Client client = ClientBuilder.newClient();
Response res = client.target("http://localhost:8080/rest-example/resources")
.path("books/{id}")
.resolveTemplate("id", "10")
.request()
.delete();
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), res.getStatus());
}
@Test
public void deletarOLivro_javaee7() {
Client client = ClientBuilder.newClient();
Response res = client.target("http://localhost:8080/rest-example/resources")
.path("books/{id}")
.resolveTemplate("id", "10")
.request()
.delete();
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), res.getStatus());
}
@Test
public void deletarOLivro_javaee7() {
Client client = ClientBuilder.newClient();
Response res = client.target("http://localhost:8080/rest-example/resources")
.path("books/{id}")
.resolveTemplate("id", "10")
.request()
.delete();
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), res.getStatus());
}
@Test
public void deletarOLivro_javaee7() {
Client client = ClientBuilder.newClient();
Response res = client.target("http://localhost:8080/rest-example/resources")
.path("books/{id}")
.resolveTemplate("id", "10")
.request()
.delete();
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), res.getStatus());}
...@Post...
@Test
public void inserirOLivro_javaee7() {
Client client = ClientBuilder.newClient();
Book book = new Book(1, "Android", "Direto das trincheiras");
Response response =
client.target("http://localhost:8080/rest-example/resources")
.path("books")
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(book,
MediaType.APPLICATION_JSON));
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
}
@Test
public void inserirOLivro_javaee7() {
Client client = ClientBuilder.newClient();
Book book = new Book(1, "Android", "Direto das trincheiras");
Response response =
client.target("http://localhost:8080/rest-example/resources")
.path("books")
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(book,
MediaType.APPLICATION_JSON));
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
}
@Test
public void inserirOLivro_javaee7() {
Client client = ClientBuilder.newClient();
Book book = new Book(1, "Android", "Direto das trincheiras");
Response response =
client.target("http://localhost:8080/rest-example/resources")
.path("books")
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(book,
MediaType.APPLICATION_JSON));
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
}
@Test
public void inserirOLivro_javaee7() {
Client client = ClientBuilder.newClient();
Book book = new Book(1, "Android", "Direto das trincheiras");
Response response =
client.target("http://localhost:8080/rest-example/resources")
.path("books")
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(book,
MediaType.APPLICATION_JSON));
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
}
Como configurar Filters e Interceptors?
@Test
public void inserirOLivroComFiltroDeLog() {
Client client = ClientBuilder.newClient();
client.register(MyLoggingFilter.class);
Book book = new Book(1, "Android", "Direto das trincheiras");
Response response =
client.target("http://localhost:8080/rest-example/resources")
.path("books")
.register(MyEntityInterceptor.class)
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(book, MediaType.APPLICATION_JSON));
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
}
@Test
public void inserirOLivroComFiltroDeLog() {
Client client = ClientBuilder.newClient();
client.register(MyLoggingFilter.class);
Book book = new Book(1, "Android", "Direto das trincheiras");
Response response =
client.target("http://localhost:8080/rest-example/resources")
.path("books")
.register(MyEntityInterceptor.class)
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(book, MediaType.APPLICATION_JSON));
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
}
@Test
public void inserirOLivroComFiltroDeLog() {
Client client = ClientBuilder.newClient();
client.register(MyLoggingFilter.class);
Book book = new Book(1, "Android", "Direto das trincheiras");
Response response =
client.target("http://localhost:8080/rest-example/resources")
.path("books")
.register(MyEntityInterceptor.class)
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(book, MediaType.APPLICATION_JSON));
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
}
@Test
public void inserirOLivroComFiltroDeLog() {
Client client = ClientBuilder.newClient();
client.register(MyLoggingFilter.class);
Book book = new Book(1, "Android", "Direto das trincheiras");
Response response =
client.target("http://localhost:8080/rest-example/resources")
.path("books")
.register(MyEntityInterceptor.class)
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(book, MediaType.APPLICATION_JSON));
response.close(); client.close();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
}
AsynchronousProcessing
Que tal uma chamada assíncrona?
@Path("books")
public class BookResource {
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response read(@PathParam("id") Integer id) throws
InterruptedException {
Thread.sleep(5000L);
return Response.ok(readObject(id)).build();
}
}
@Path("books")
public class BookResource {
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response read(@PathParam("id") Integer id) throws
InterruptedException {
Thread.sleep(5000L); return Response.ok(readObject(id)).build();
}
} Simulando um processamento pesado.
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled());
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
assertThat(asyncResponse.get(), notNullValue());
}
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled());
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
assertThat(asyncResponse.get(), notNullValue());
}
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled());
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
assertThat(asyncResponse.get(), notNullValue());
}
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled());
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
assertThat(asyncResponse.get(), notNullValue());
}
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled()); // false
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
assertThat(asyncResponse.get(), notNullValue());
}
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled()); // false
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
assertThat(asyncResponse.get(), notNullValue());
}
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled()); // false
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
assertThat(asyncResponse.get(), notNullValue());
}
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled()); // false
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone()); // false
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
assertThat(asyncResponse.get(), notNullValue());
}
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled()); // false
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone()); // false
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
assertThat(asyncResponse.get(), notNullValue());
}
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled()); // false
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone()); // false
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone());
assertThat(asyncResponse.get(), notNullValue());
}
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled()); // false
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone()); // false
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone()); // true
assertThat(asyncResponse.get(), notNullValue());
}
@Test
public void buscaOLivroDeFormaAssincrona() {
WebTarget target = ClientBuilder.newClient()
.target("http://localhost:8080/rest-example/resources")
.path("books/10");
Future<Book> asyncResponse = target.request().async().get(Book.class);
System.out.println("Cancelado: " + asyncResponse.isCancelled()); // false
Thread.sleep(2000L);
System.out.println("Finalizado: " + asyncResponse.isDone()); // false
Thread.sleep(5000L);
System.out.println("Finalizado: " + asyncResponse.isDone()); // true
assertThat(asyncResponse.get(), notNullValue());
}
Timeout no método get()JSR 236 - Concurrency Utilities for JavaTM EE
@Testpublic void buscaOLivroDeFormaAssincrona() { WebTarget target = ClientBuilder.newClient() .target("http://localhost:8080/rest-example/resources") .path("books/10"); Future<Book> asyncResponse = target.request().async().get(Book.class);
assertThat(asyncResponse.get(20L, TimeUnit.SECONDS), notNullValue());}
@Testpublic void buscaOLivroDeFormaAssincrona() { WebTarget target = ClientBuilder.newClient() .target("http://localhost:8080/rest-example/resources") .path("books/10"); Future<Book> asyncResponse = target.request().async().get(Book.class);
assertThat(asyncResponse.get(20L, TimeUnit.SECONDS), notNullValue());}
@Testpublic void buscaOLivroDeFormaAssincrona() { WebTarget target = ClientBuilder.newClient() .target("http://localhost:8080/rest-example/resources") .path("books/10"); Future<Book> asyncResponse = target.request().async().get(Book.class);
assertThat(asyncResponse.get(2L, TimeUnit.SECONDS), notNullValue());}
@Testpublic void buscaOLivroDeFormaAssincrona() { WebTarget target = ClientBuilder.newClient() .target("http://localhost:8080/rest-example/resources") .path("books/10"); Future<Book> asyncResponse = target.request().async().get(Book.class);
assertThat(asyncResponse.get(2L, TimeUnit.SECONDS), notNullValue());}
Posso enviar um InvocationCallback?
@Testpublic void buscaOLivroDeFormaAssincrona() { WebTarget target = ClientBuilder.newClient() .target("http://localhost:8080/rest-example/resources") .path("books/10"); target.request().async().get(new InvocationCallback<Book>() { public void completed(Book book) { assertThat(book, notNullValue()); }
public void failed(Throwable throwable) { fail(); } }); }
@Testpublic void buscaOLivroDeFormaAssincrona() { WebTarget target = ClientBuilder.newClient() .target("http://localhost:8080/rest-example/resources") .path("books/10"); target.request().async().get(new InvocationCallback<Book>() { public void completed(Book book) { assertThat(book, notNullValue()); }
public void failed(Throwable throwable) { fail(); } }); }
@Testpublic void buscaOLivroDeFormaAssincrona() { WebTarget target = ClientBuilder.newClient() .target("http://localhost:8080/rest-example/resources") .path("books/10"); target.request().async().get(new InvocationCallback<Book>() { public void completed(Book book) { assertThat(book, notNullValue()); }
public void failed(Throwable throwable) { fail(); } }); }
@Testpublic void buscaOLivroDeFormaAssincrona() { WebTarget target = ClientBuilder.newClient() .target("http://localhost:8080/rest-example/resources") .path("books/10"); target.request().async().get(new InvocationCallback<Book>() { public void completed(Book book) { assertThat(book, notNullValue()); }
public void failed(Throwable throwable) { fail(); } }); }
Assíncrono no servidor......se você quiser!
Primeiro, sem EJB...
@Path("async/books")
public class AsyncBookResource {
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public void longRunningOperation(@Suspended final AsyncResponse
asyncResponse) {
Runnable command = new Runnable() {
public void run() {
Thread.sleep(10000L);
asyncResponse.resume(new Book());
}
};
Executors.newSingleThreadExecutor().execute(command);
}
}
@Path("async/books")
public class AsyncBookResource {
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public void longRunningOperation(@Suspended final AsyncResponse
asyncResponse) {
Runnable command = new Runnable() {
public void run() {
Thread.sleep(10000L);
asyncResponse.resume(new Book());
}
};
Executors.newSingleThreadExecutor().execute(command);
}
}
@Path("async/books")
public class AsyncBookResource {
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public void longRunningOperation(@Suspended final AsyncResponse
asyncResponse) {
Runnable command = new Runnable() { public void run() {
Thread.sleep(10000L);
asyncResponse.resume(new Book());
}
};
Executors.newSingleThreadExecutor().execute(command);
}
}
@Path("async/books")
public class AsyncBookResource {
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public void longRunningOperation(@Suspended final AsyncResponse
asyncResponse) {
Runnable command = new Runnable() {
public void run() {
Thread.sleep(10000L);
asyncResponse.resume(new Book());
}
};
Executors.newSingleThreadExecutor().execute(command); // JSR 236
}
}
@Path("async/books")
public class AsyncBookResource {
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public void longRunningOperation(@Suspended final AsyncResponse
asyncResponse) {
Runnable command = new Runnable() {
public void run() {
Thread.sleep(10000L);
asyncResponse.resume(new Book());
}
};
Executors.newSingleThreadExecutor().execute(command); // JSR 236
}
}
@Path("async/books")
public class AsyncBookResource {
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public void longRunningOperation(@Suspended final AsyncResponse
asyncResponse) {
Runnable command = new Runnable() {
public void run() {
Thread.sleep(10000L);
asyncResponse.resume(new Book()); }
};
Executors.newSingleThreadExecutor().execute(command); // JSR 236
}
}
E se for com EJB?
@Stateless
@Path("async/books")
public class AsyncBookResource {
@GET
@Path("/")
@Asynchronous
@Produces(MediaType.APPLICATION_JSON)
public void longRunningOperation(@Suspended final AsyncResponse
asyncResponse) {
Thread.sleep(10000L);
asyncResponse.resume(new Book());
}
}
EJB 3.1 (Java EE 6)
@Stateless
@Path("async/books")
public class AsyncBookResource {
@GET
@Path("/")
@Asynchronous
@Produces(MediaType.APPLICATION_JSON)
public void longRunningOperation(@Suspended final AsyncResponse
asyncResponse) {
Thread.sleep(10000L);
asyncResponse.resume(new Book());
}
}
@Stateless
@Path("async/books")
public class AsyncBookResource {
@GET
@Path("/")
@Asynchronous
@Produces(MediaType.APPLICATION_JSON)
public void longRunningOperation(@Suspended final AsyncResponse
asyncResponse) {
Thread.sleep(10000L);
asyncResponse.resume(new Book());
}
}
@Stateless
@Path("async/books")
public class AsyncBookResource {
@GET
@Path("/")
@Asynchronous
@Produces(MediaType.APPLICATION_JSON)
public void longRunningOperation(@Suspended final AsyncResponse
asyncResponse) {
Thread.sleep(10000L);
asyncResponse.resume(new Book());
}
}
Filters and Interceptors
O que são os filters?
ClientRequestFilter
ClientResponseFilter
@Provider
public class LoggingFilter implements ClientRequestFilter,
ClientResponseFilter {
public void filter(ClientRequestContext requestContext) throws
IOException {
log(requestContext);
}
public void filter(ClientRequestContext requestContext,
ClientResponseContext responseContext) throws IOException {
log(responseContext);
}
}
@Provider
public class LoggingFilter implements ClientRequestFilter,
ClientResponseFilter {
public void filter(ClientRequestContext requestContext) throws
IOException {
log(requestContext);
}
public void filter(ClientRequestContext requestContext,
ClientResponseContext responseContext) throws IOException {
log(responseContext);
}
}
@Provider
public class LoggingFilter implements ClientRequestFilter,
ClientResponseFilter {
public void filter(ClientRequestContext requestContext) throws
IOException {
log(requestContext);
}
public void filter(ClientRequestContext requestContext,
ClientResponseContext responseContext) throws IOException {
log(responseContext);
}
}
@Provider
public class LoggingFilter implements ClientRequestFilter,
ClientResponseFilter {
public void filter(ClientRequestContext requestContext) throws
IOException {
log(requestContext);
}
public void filter(ClientRequestContext requestContext,
ClientResponseContext responseContext) throws IOException {
log(responseContext);
}
}
@Provider
public class LoggingFilter implements ClientRequestFilter,
ClientResponseFilter {
public void filter(ClientRequestContext requestContext) throws
IOException {
log(requestContext);
}
public void filter(ClientRequestContext requestContext,
ClientResponseContext responseContext) throws IOException { log(responseContext);
}
}
ContainerRequestFilter
ContainerResponserFilter
@Provider
class LoggingFilter implements ContainerRequestFilter,
ContainerResponseFilter {
public void filter(ContainerRequestContext requestContext) throws
IOException {
log(requestContext);
}
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException {
log(responseContext);
}
}
@Provider
class LoggingFilter implements ContainerRequestFilter,
ContainerResponseFilter {
public void filter(ContainerRequestContext requestContext) throws
IOException {
log(requestContext);
}
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException {
log(responseContext);
}
}
@Provider
class LoggingFilter implements ContainerRequestFilter,
ContainerResponseFilter {
public void filter(ContainerRequestContext requestContext) throws
IOException {
log(requestContext);
}
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException {
log(responseContext);
}
}
@Provider
class LoggingFilter implements ContainerRequestFilter,
ContainerResponseFilter {
public void filter(ContainerRequestContext requestContext) throws
IOException {
log(requestContext);
}
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException {
log(responseContext);
}
}
@Provider
class LoggingFilter implements ContainerRequestFilter,
ContainerResponseFilter {
public void filter(ContainerRequestContext requestContext) throws
IOException {
log(requestContext);
}
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException { log(responseContext);
}
}
O que são os interceptors?
ReaderInterceptor
WriterInterceptor
Descompactando a requisição
@Provider
public class GzipReaderInterceptor implements ReaderInterceptor {
Object aroundReadFrom(ReaderInterceptorContext ctx) ... {
if (isGzipped(ctx)) {
InputStream old = ctx.getInputStream();
ctx.setInputStream(new GZIPInputStream(old));
try {
return ctx.proceed();
} finally {
ctx.setInputStream(old);
}
} else {
return ctx.proceed();
}
}
}
@Provider
public class GzipReaderInterceptor implements ReaderInterceptor {
Object aroundReadFrom(ReaderInterceptorContext ctx) ... {
if (isGzipped(ctx)) {
InputStream old = ctx.getInputStream();
ctx.setInputStream(new GZIPInputStream(old));
try {
return ctx.proceed();
} finally {
ctx.setInputStream(old);
}
} else {
return ctx.proceed();
}
}
}
@Provider
public class GzipReaderInterceptor implements ReaderInterceptor {
Object aroundReadFrom(ReaderInterceptorContext ctx) ... {
if (isGzipped(ctx)) {
InputStream old = ctx.getInputStream();
ctx.setInputStream(new GZIPInputStream(old));
try {
return ctx.proceed();
} finally {
ctx.setInputStream(old);
}
} else {
return ctx.proceed();
}
}
}
@Provider
public class GzipReaderInterceptor implements ReaderInterceptor {
Object aroundReadFrom(ReaderInterceptorContext ctx) ... {
if (isGzipped(ctx)) {
InputStream old = ctx.getInputStream();
ctx.setInputStream(new GZIPInputStream(old));
try {
return ctx.proceed();
} finally {
ctx.setInputStream(old);
}
} else {
return ctx.proceed();
}
}
}
Compactando a resposta
@Providerpublic class GzipWriteInterceptor implements WriteInterceptor {
void aroundWriteTo(WriterInterceptorContext ctx) ... {
OutputStream old = ctx.getOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(old);
ctx.setOutputStream(gzipOutputStream);
updateHeaders(ctx);
try {
ctx.proceed();
} finally {
gzipOutputStream.finish();
ctx.setOutputStream(old);
}
}
}
@Provider
public class GzipWriteInterceptor implements WriteInterceptor {
void aroundWriteTo(WriterInterceptorContext ctx) ... {
OutputStream old = ctx.getOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(old);
ctx.setOutputStream(gzipOutputStream);
updateHeaders(ctx);
try {
ctx.proceed();
} finally {
gzipOutputStream.finish();
ctx.setOutputStream(old);
}
}
}
@Provider
public class GzipWriteInterceptor implements WriteInterceptor {
void aroundWriteTo(WriterInterceptorContext ctx) ... { OutputStream old = ctx.getOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(old);
ctx.setOutputStream(gzipOutputStream);
updateHeaders(ctx);
try {
ctx.proceed();
} finally {
gzipOutputStream.finish();
ctx.setOutputStream(old);
}
}
}
@Provider
public class GzipWriteInterceptor implements WriteInterceptor {
void aroundWriteTo(WriterInterceptorContext ctx) ... { OutputStream old = ctx.getOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(old);
ctx.setOutputStream(gzipOutputStream);
updateHeaders(ctx);
try {
ctx.proceed();
} finally {
gzipOutputStream.finish();
ctx.setOutputStream(old);
}
}
}
Mas, qual é a diferença mesmo?
Filters: Acesso ao contexto do request/response.
Exemplo de FiltersLogar origem do request.Verificar qual o método http utilizado. Qual a URI.
Interceptors: Acesso ao contexto da mensagem.
Exemplo de InterceptorsCompactar o conteúdo da mensagem a ser enviada.Descompactar o conteúdo da mensagem a ser lida.
Posso logar minhas requisições antes de chegar ao método?
@PreMatching
@Provider@PreMatchingpublic class HttpPreMatchingFilter implements ContainerRequestFilter {
public void filter(ContainerRequestContext requestContext) throws IOException {
... }
}
@Provider@PreMatchingpublic class HttpPreMatchingFilter implements ContainerRequestFilter {
public void filter(ContainerRequestContext requestContext) throws IOException {
... }
}
@Provider@PreMatchingpublic class HttpPreMatchingFilter implements ContainerRequestFilter {
public void filter(ContainerRequestContext requestContext) throws IOException {
... }
}
Mas se eu quiser logar um método específico, é possível?
@NameBinding
@NameBinding@Target({ ElementType.TYPE, ElementType.METHOD })@Retention(value = RetentionPolicy.RUNTIME)public @interface Logged {}
Similar aos qualificadores do CDI
@Provider @Loggedpublic class LoggingFilter implements ContainerRequestFilter, ContainerResponseFilter {
...}
@Path("/")public class MyResourceClass { @GET @Logged @Path("{name}") @Produces("text/plain") public String hello(@PathParam("name") String name) { return "Hello " + name; }
}
E a ordem? Posso definir?
@Priority
@Provider@Authenticated@Priority(Priorities.AUTHENTICATION)public class AuthenticationFilter implements ContainerRequestFilter{ ...}
Modifier and Type Constant Field Value
public static final int AUTHENTICATION 1000
public static final int AUTHORIZATION 2000
public static final int ENTITY_CODER 3000
public static final int HEADER_DECORATOR 4000
public static final int USER 5000
javax.ws.rs.Priorities
Bean ValidationJSR-349
Como eu aplico?
public class Book {
private Integer id;
@NotNull private String name;
private String description; private Integer year; private String genero;
}
@POST@Consumes(MediaType.APPLICATION_JSON)public Response create(@Valid Book book) {
ResponseBuilder rb = Response.ok(createObject(book)); return rb.build();
}
@GET@Path("/year/{year}")@Produces(MediaType.APPLICATION_JSON)public Response listByYearAndName(@Max(2015) @PathParam("year") Integer year, @QueryParam("name") String name) { List<Book> books = getListByYearAndName(year, name); ResponseBuilder rb = Response.ok(books); return rb.build();
}
HATEOASHipermídia como motor do estado do aplicativo
“If the engine of application is not being driven by hypertext, then it cannot be RESTful and
cannot be a REST API” (Roy T. Fielding)
Book Purchase
Related Books
Author
Receipt
/books/1/author/books/genre/programming/books/1/purchase
/books/1/purchase/12/receipt
/books/1
Exemplo
Link: <http://gujavasc.org/resources/books/1/purchase>; rel=purchase, …
<book> <id>1</id> <year>2013</year> <name>REST in practice</name> <genre>programming</genre> <author>http://gujavasc.org/resources/books/1/author</author> <related>http://gujavasc.org/resources/books/genre/programming</related></book>
Links Transicionais
Links Estruturais
Links Transicionais@GET@Path("{id}")@Produces(MediaType.APPLICATION_JSON)public Response read(@PathParam("id") Integer id, @Context UriInfo uriInfo){
Link purchaseLink = Link.fromPath(uriInfo.getRequestUri().toString() + "/purchase")
.rel("purchase")
.build();
return Response.ok(readObject(id)) .links(purchaseLink) .link(uriInfo.getRequestUri().toString() + "/genre/programming", "genre") .build();
}
Links Transicionais@GET@Path("{id}")@Produces(MediaType.APPLICATION_JSON)public Response read(@PathParam("id") Integer id, @Context UriInfo uriInfo){
Link purchaseLink = Link.fromPath(uriInfo.getRequestUri().toString() + "/purchase")
.rel("purchase")
.build();
return Response.ok(readObject(id)) .links(purchaseLink) .link(uriInfo.getRequestUri().toString() + "/genre/programming", "genre") .build();
}
Links Transicionais@GET@Path("{id}")@Produces(MediaType.APPLICATION_JSON)public Response read(@PathParam("id") Integer id, @Context UriInfo uriInfo){
Link purchaseLink = Link.fromPath(uriInfo.getRequestUri().toString() + "/purchase")
.rel("purchase")
.build();
return Response.ok(readObject(id)) .links(purchaseLink) .link(uriInfo.getRequestUri().toString() + "/genre/programming", "genre") .build();
}
Links Transicionais@GET@Path("{id}")@Produces(MediaType.APPLICATION_JSON)public Response read(@PathParam("id") Integer id, @Context UriInfo uriInfo){
Link purchaseLink = Link.fromPath(uriInfo.getRequestUri().toString() + "/purchase")
.rel("purchase")
.build();
return Response.ok(readObject(id)) .links(purchaseLink) .link(uriInfo.getRequestUri().toString() + "/genre/programming", "genre") .build();
}
Links Transicionais@GET@Path("{id}")@Produces(MediaType.APPLICATION_JSON)public Response read(@PathParam("id") Integer id, @Context UriInfo uriInfo){
Link purchaseLink = Link.fromPath(uriInfo.getRequestUri().toString() + "/purchase")
.rel("purchase")
.build();
return Response.ok(readObject(id)) .links(purchaseLink) .link(uriInfo.getRequestUri().toString() + "/genre/programming", "genre") .build();
}
Links Transicionais@GET@Path("{id}")@Produces(MediaType.APPLICATION_JSON)public Response read(@PathParam("id") Integer id, @Context UriInfo uriInfo){
Link purchaseLink = Link.fromPath(uriInfo.getRequestUri().toString() + "/purchase")
.rel("purchase")
.build();
return Response.ok(readObject(id)) .links(purchaseLink) .link(uriInfo.getRequestUri().toString() + "/genre/programming", "genre") .build();
}
Links Transicionais@GET@Path("{id}")@Produces(MediaType.APPLICATION_JSON)public Response read(@PathParam("id") Integer id, @Context UriInfo uriInfo){
Link purchaseLink = Link.fromPath(uriInfo.getRequestUri().toString() + "/purchase")
.rel("purchase")
.build();
return Response.ok(readObject(id)) .links(purchaseLink) .link(uriInfo.getRequestUri().toString() + "/genre/programming", "genre") .build();
}
Links Transicionais@GET@Path("{id}")@Produces(MediaType.APPLICATION_JSON)public Response read(@PathParam("id") Integer id, @Context UriInfo uriInfo){
Link purchaseLink = Link.fromPath(uriInfo.getRequestUri().toString() + "/purchase")
.rel("purchase")
.build();
return Response.ok(readObject(id)) .links(purchaseLink) .link(uriInfo.getRequestUri().toString() + "/genre/programming", "genre") .build();
}
Integração com Java EEManaged BeansCDIEJBBean ValidationJSON API
OBRIGADO!
Daniel Cunha (Soro) - @dvlc_Ivan Junckes Filho - @ivanjunckes
Ricardo Longa - @ricardolonga
https://github.com/gujavasc/jaxrs2