JSR 339 - Java API for RESTful Web Services

Post on 16-Apr-2017

1.277 views 2 download

Transcript of JSR 339 - Java API for RESTful Web Services

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