API do cliente RESTEasy
1. Introdução
Emprevious article, nos concentramos na implementação do lado do servidorRESTEasy deJAX-RS 2.0.
JAX-RS 2.0 apresenta uma nova API de cliente para que você possa fazer solicitações HTTP para seus serviços Web RESTful remotos. Jersey, Apache CXF, Restlet e RESTEasy são apenas um subconjunto das implementações mais populares.
Neste artigo, exploraremos como consumirREST API enviando solicitações comRESTEasy API.
2. Configuração do Projeto
Adicione em seupom.xml a seguinte dependência:
3.0.14.Final
org.jboss.resteasy
resteasy-client
${resteasy.version}
...
3. Código do lado do cliente
A implementação do cliente é bastante, sendo composta por 3 classes principais:
-
-
Cliente
-
WebTarget
-
Resposta
-
A interfaceClient é um construtor de instânciasWebTarget.
WebTarget representa um URL distinto ou modelo de URL a partir do qual você pode construir mais WebTargets de sub-recursos ou invocar solicitações.
Na verdade, existem duas maneiras de criar um cliente:
-
A maneira padrão, usando oorg.jboss.resteasy.client.ClientRequest
-
RESTeasy Proxy Framework: usando a classeResteasyClientBuilder
Vamos nos concentrar no RESTEasy Proxy Framework aqui.
Em vez de usar anotações JAX-RS para mapear uma solicitação recebida para o método RESTFul Web Service, a estrutura do cliente constrói uma solicitação HTTP que ela usa para chamar em um RESTful Web Service remoto.
Então, vamos começar a escrever uma interface Java e usar anotações JAX-RS nos métodos e na interface.
3.1. A interfaceServicesClient
@Path("/movies")
public interface ServicesInterface {
@GET
@Path("/getinfo")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
Movie movieByImdbId(@QueryParam("imdbId") String imdbId);
@POST
@Path("/addmovie")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
Response addMovie(Movie movie);
@PUT
@Path("/updatemovie")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
Response updateMovie(Movie movie);
@DELETE
@Path("/deletemovie")
Response deleteMovie(@QueryParam("imdbId") String imdbId);
}
3.2. The Movie Class
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "movie", propOrder = { "imdbId", "title" })
public class Movie {
protected String imdbId;
protected String title;
// getters and setters
}
3.3. A Solicitação de Criação
Agora, geraremos um cliente proxy que podemos usar para consumir a API:
String transformerImdbId = "tt0418279";
Movie transformerMovie = new Movie("tt0418279", "Transformer 2");
final String path = "http://127.0.0.1:8080/RestEasyTutorial/rest";
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target(UriBuilder.fromPath(path));
ServicesInterface proxy = target.proxy(ServicesInterface.class);
// POST
Response moviesResponse = proxy.addMovie(transformerMovie);
System.out.println("HTTP code: " + moviesResponse.getStatus());
moviesResponse.close();
// GET
Movie movies = proxy.movieByImdbId(transformerImdbId);
// PUT
transformerMovie.setTitle("Transformer 4");
moviesResponse = proxy.updateMovie(transformerMovie);
moviesResponse.close();
// DELETE
moviesResponse = proxy.deleteMovie(batmanMovie.getImdbId());
moviesResponse.close();
Observe que a API do cliente RESTEasy é baseada no ApacheHttpClient.
Observe também que, após cada operação, precisaremos fechar a resposta antes de realizar uma nova operação. Isso é necessário porque, por padrão, o cliente tem apenas uma única conexão HTTP disponível.
Finalmente, observe como estamos trabalhando com os DTOs diretamente - não estamos lidando com a lógica empacotar / descompactar de e paraJSON ouXML; isso acontece nos bastidores usandoJAXB ouJackson, pois a classeMovie foi anotada corretamente.
3.4. A criação de solicitação com pool de conexão
Uma observação do exemplo anterior é que tínhamos apenas uma conexão disponível. Se - por exemplo, tentamos fazer:
Response batmanResponse = proxy.addMovie(batmanMovie);
Response transformerResponse = proxy.addMovie(transformerMovie);
sem invocarclose() embatmanResponse - uma exceção será lançada quando a segunda linha for executada:
java.lang.IllegalStateException:
Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
Novamente - isso simplesmente acontece porque oHttpClient padrão usado pelo RESTEasy éorg.apache.http.impl.conn.SingleClientConnManager - o que, obviamente, só disponibiliza uma única conexão.
Agora - para contornar essa limitação - a instânciaRestEasyClient deve ser criada de forma diferente (com um pool de conexão):
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
cm.setMaxTotal(200); // Increase max total connection to 200
cm.setDefaultMaxPerRoute(20); // Increase default max connection per route to 20
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
ResteasyWebTarget target = client.target(UriBuilder.fromPath(path));
ServicesInterface proxy = target.proxy(ServicesInterface.class);
Agora podemosbenefit from a proper connection poole podemos ter várias solicitações em execução por meio de nosso cliente, sem necessariamente ter que liberar a conexão a cada vez.
4. Conclusão
Neste tutorial rápido, apresentamos oRESTEasy Proxy Frameworke construímos uma API de cliente super simples com ele.
A estrutura nos fornece mais alguns métodos auxiliares para configurar um cliente e pode ser definida como o espelho oposto às especificações do servidor JAX-RS.
O exemplo usado neste artigo está disponível comosample project in GitHub.