JAX-RS n’est qu’une API!

JAX-RS n'est qu'une API!

1. Vue d'ensemble

Le paradigme REST existe depuis plusieurs années maintenant et il retient toujours beaucoup d’attention.

Une API RESTful peut être implémentée en Java de plusieurs manières: vous pouvez utiliser Spring, JAX-RS, ou vous pouvez simplement écrire vos propres servlets simples si vous êtes assez bon et courageux. Tout ce dont vous avez besoin, c'est de pouvoir exposer les méthodes HTTP. Le reste concerne la manière dont vous les organisez et comment vous guidez le client lors d'appels vers votre API.

Comme vous pouvez le constater à partir du titre, cet article couvrira JAX-RS. Mais que signifie "juste une API"? Cela signifie que l'objectif est de clarifier la confusion entre JAX-RS et ses implémentations et de donner un exemple de ce à quoi ressemble une application Web JAX-RS appropriée.

2. Inclusion dans Java EE

JAX-RS n'est rien de plus qu'une spécification, un ensemble d'interfaces et d'annotations proposées par Java EE. Et puis, bien sûr, nous avons les implémentations; certains des plus connus sontRESTEasy etJersey.

En outre, si vous décidez de créer un serveur d'applications compatible JEE, les responsables Oracle vous indiqueront que, entre autres choses, votre serveur doit fournir une implémentation JAX-RS à utiliser par les applications déployées. C’est pourquoi il s’appelle Java Enterprise EditionPlatform.

Un autre bon exemple de spécification et d'implémentation estJPA etHibernate.

2.1. Guerres légères

Alors, comment tout cela nous aide-t-il, les développeurs? L’aide réside dans le fait que nos déployables peuvent et doivent être très minces, permettant au serveur d’application de fournir les bibliothèques nécessaires. Ceci s'applique également lors du développement d'une API RESTful: l'artefact final ne doit contenir aucune information sur l'implémentation JAX-RS utilisée.

Bien sûr, nous pouvons fournir l'implémentation (here est un tutoriel pour RESTeasy). Mais nous ne pouvons plus appeler notre application «Java EE app». Si demain quelqu'un vient et dit «Ok, time to switch to Glassfish or Payara, JBoss became too expensive!», nous pourrons peut-être le faire, mais ce ne sera pas une tâche facile.

Si nous fournissons notre propre implémentation, nous devons nous assurer que le serveur sait exclure la sienne - ceci se produit généralement en disposant d'un fichier XML propriétaire dans le fichier déployable. Il va sans dire qu'un tel fichier devrait contenir toutes sortes de balises et d'instructions dont personne ne sait rien, à l'exception des développeurs qui ont quitté la société il y a trois ans.

2.2. Connaissez toujours votre serveur

Nous avons dit jusqu'à présent que nous devrions tirer parti de la plate-forme qui nous est proposée.

Avant de choisir un serveur à utiliser, nous devons voir quelle implémentation JAX-RS (nom, fournisseur, version et bogues connus) elle fournit, du moins pour les environnements de production. Par exemple, Glassfish est livré avec Jersey, tandis que Wildfly ou Jboss sont livrés avec RESTEasy.

Cela, bien sûr, signifie un peu de temps consacré à la recherche, mais cela est censé être fait une seule fois, au début du projet ou lors de sa migration vers un autre serveur.

3. Un exemple

Si vous voulez commencer à jouer avec JAX-RS, le chemin le plus court est: avoir un projet webapp Maven avec la dépendance suivante dans lespom.xml:


    javax
    javaee-api
    7.0
    provided

Nous utilisons JavaEE 7 car il existe déjà de nombreux serveurs d'applications qui l'implémentent. Ce fichier API contient les annotations que vous devez utiliser, situées dans le packagejavax.ws.rs. Pourquoi la portée est-elle «fournie»? Parce que ce fichier jar n'a pas besoin non plus d'être dans la version finale - nous en avons besoin au moment de la compilation et il est fourni par le serveur pour l'exécution.

Une fois la dépendance ajoutée, nous devons d'abord écrire la classe d'entrée: une classe vide qui étendjavax.ws.rs.core.Application et est annotée avecjavax.ws.rs.ApplicationPath:

@ApplicationPath("/api")
public class RestApplication extends Application {
}

Nous avons défini le chemin d'entrée comme étant/api. Quels que soient les autres chemins que nous déclarons pour nos ressources, ils seront précédés de/api.

Voyons ensuite une ressource:

@Path("/notifications")
public class NotificationsResource {
    @GET
    @Path("/ping")
    public Response ping() {
        return Response.ok().entity("Service online").build();
    }

    @GET
    @Path("/get/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getNotification(@PathParam("id") int id) {
        return Response.ok()
          .entity(new Notification(id, "john", "test notification"))
          .build();
    }

    @POST
    @Path("/post/")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response postNotification(Notification notification) {
        return Response.status(201).entity(notification).build();
    }
}

Nous avons un point d'extrémité ping simple à appeler et à vérifier si notre application est en cours d'exécution, un GET et un POST pour une notification (il s'agit simplement d'un POJO avec des attributs, ainsi que des getters et des setters).

Déployez cette guerre sur n’importe quel serveur d’application implémentant JEE7 et les commandes suivantes fonctionneront:

curl http://localhost:8080/simple-jaxrs-ex/api/notifications/ping/

curl http://localhost:8080/simple-jaxrs-ex/api/notifications/get/1

curl -X POST -d '{"id":23,"text":"lorem ipsum","username":"johana"}'
  http://localhost:8080/simple-jaxrs-ex/api/notifications/post/
  --header "Content-Type:application/json"

Où simple-jaxrs-ex est la racine de contexte de la webapp.

Ceci a été testé avec Glassfish 4.1.0 et Wildfly 9.0.1.Final. Veuillez noter que les deux dernières commandes ne fonctionneront pas avec Glassfish 4.1.1, à cause du bogue dethis. Il s'agit apparemment d'un problème connu dans cette version de Glassfish, concernant la sérialisation de JSON (si vous devez utiliser cette version de serveur, vous devrez gérer vous-même le marshaling JSON)

4. Conclusion

À la fin de cet article, n'oubliez pas que JAX-RS est une API puissante et que la plupart (sinon la totalité) des éléments dont vous avez besoin sont déjà implémentés par votre serveur Web. Inutile de transformer votre déployable en une pile de bibliothèques ingérable.

Cet article présente un exemple simple et les choses pourraient devenir plus compliquées. Par exemple, vous voudrez peut-être écrire vos propres marshalers. Lorsque cela est nécessaire, recherchez des didacticiels qui résolvent votre problème avec JAX-RS, pas avec Jersey, Resteasy ou toute autre implémentation concrète. Il est très probable que votre problème puisse être résolu avec une ou deux annotations.