Upload
daniel-cunha
View
151
Download
2
Embed Size (px)
JSR 339 Java API for RESTful Web Services
GujavaSC / Adopt a JSR
Membros do GujavaSC
Participação Adopt a JSR
Grupo de estudos
Artigos
Palestras
O que é REST?
É um estilo arquitetural…
Estilo arquitetural???
É um estilo arquitetural…
Enxaimel
Telhado
Madeiras
Tijolos
Estilo
Arquitetural
REST
HTTP
Características
Recursos são identificados por um ID;
Sem estado;
Vincule as coisas;
Múltiplas representações;
Interface uniforme.
Características
Recursos 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.x
Final Release em 2008
Objetivos
Baseado em POJO
Centralizado em HTTP
Independência de formato
Independência de container
Inclusã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 2013
Solicitações (JSR 339)
Client API
Asynchronous processing
Filters / Interceptors
Bean Validation
Hypermedia
MVC
Client API
Client API
Baseada 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
@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);
}
}
}
@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çamesmo?
Filters: Acesso ao contexto do request/response.
Exemplo de Filters
Logar origem do request.
Verificar qual o método http utilizado.
Qual a URI.
Interceptors: Acesso ao contexto damensagem.
Exemplo de Interceptors
Compactar o conteúdo da mensagem a ser enviada.
Descompactar o conteúdo da mensagem a ser lida.
Posso logar minhas requisiçõesantes 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;
@NotNullprivate 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();
}
HATEOAS
Hipermí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 EE
Managed Beans
CDI
EJB
Bean Validation
JSON API
OBRIGADO!
Daniel Cunha (Soro) - @dvlc_
Ivan Junckes Filho - @ivanjunckes
Ricardo Longa - @ricardolonga
https://github.com/gujavasc/jaxrs2