API client RESTEasy

API du client RESTEasy

1. introduction

Dans lesprevious article, nous nous sommes concentrés sur l'implémentation côté serveur deRESTEasy deJAX-RS 2.0.

JAX-RS 2.0 introduit une nouvelle API client afin que vous puissiez faire des requêtes HTTP à vos services Web RESTful distants. Jersey, Apache CXF, Restlet et RESTEasy ne sont qu'un sous-ensemble des implémentations les plus courantes.

Dans cet article, nous allons explorer comment consommer lesREST API en envoyant des requêtes avec unRESTEasy API.

2. Configuration du projet

Ajoutez dans vospom.xml la dépendance suivante:


    3.0.14.Final


    
        org.jboss.resteasy
        resteasy-client
        ${resteasy.version}
    
    ...

3. Code côté client

L'implémentation client est assez simple, étant composée de 3 classes principales:

    • Client

    • WebTarget

    • Réponse

L'interfaceClient est un générateur d'instancesWebTarget.

WebTarget représente une URL ou un modèle d'URL distinct à partir duquel vous pouvez créer plus de WebTargets de sous-ressources ou appeler des requêtes.

Il existe vraiment deux façons de créer un client:

  • La manière standard, en utilisant lesorg.jboss.resteasy.client.ClientRequest

  • RESTeasy Proxy Framework: en utilisant la classeResteasyClientBuilder

Nous allons nous concentrer sur le cadre de proxy RESTEasy ici.

Au lieu d'utiliser des annotations JAX-RS pour mapper une demande entrante sur votre méthode de service Web RESTFul, le framework client génère une demande HTTP qu'il utilise pour appeler sur un service Web RESTful distant.

Commençons donc à écrire une interface Java et à utiliser les annotations JAX-RS sur les méthodes et sur l'interface.

3.1. L'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. La classe de cinéma

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "movie", propOrder = { "imdbId", "title" })
public class Movie {

    protected String imdbId;
    protected String title;

    // getters and setters
}

3.3. La création de la demande

Nous allons maintenant générer un client proxy que nous pouvons utiliser pour consommer l'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();

Notez que l'API client RESTEasy est basée sur ApacheHttpClient.

Notez également qu'après chaque opération, nous devrons fermer la réponse avant de pouvoir effectuer une nouvelle opération. Cela est nécessaire car, par défaut, le client ne dispose que d’une seule connexion HTTP.

Enfin, notez comment nous travaillons directement avec les DTO - nous ne traitons pas de la logique marshal / unmarshal vers et depuisJSON ouXML; qui se produit dans les coulisses en utilisantJAXB ouJackson puisque la classeMovie a été correctement annotée.

3.4. La création de demande avec le pool de connexions

L’exemple précédent indiquait qu’une seule connexion était disponible. Si - par exemple, nous essayons de faire:

Response batmanResponse = proxy.addMovie(batmanMovie);
Response transformerResponse = proxy.addMovie(transformerMovie);

sans invoquerclose() surbatmanResponse - une exception sera levée lors de l'exécution de la deuxième ligne:

java.lang.IllegalStateException:
Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.

Encore une fois - cela se produit simplement parce que leHttpClient par défaut utilisé par RESTEasy estorg.apache.http.impl.conn.SingleClientConnManager - ce qui, bien sûr, ne rend disponible qu'une seule connexion.

Maintenant, pour contourner cette limitation, l'instanceRestEasyClient doit être créée différemment (avec un pool de connexions):

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);

Maintenant, nous pouvonsbenefit from a proper connection pool et pouvons avoir plusieurs requêtes en cours d'exécution via notre client sans nécessairement avoir à libérer la connexion à chaque fois.

4. Conclusion

Dans ce tutoriel rapide, nous avons présenté lesRESTEasy Proxy Framework et nous avons construit une API client super simple avec.

La structure nous donne quelques méthodes d’aide supplémentaires pour configurer un client et peut être définie comme le miroir opposé aux spécifications côté serveur JAX-RS.

L'exemple utilisé dans cet article est disponible en tant quesample project in GitHub.