API do cliente RESTEasy

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.