JAX-RS ou Comment créer et utiliser des services RESTful en 10 min ?

En 2 mots, REST (Representation State Transfer) est un principe d’architecture applicative qui s’appuie sur les principes fondateurs du Web :

  • les URI qui représentent des ressources auxquelles votre application se réfère
  • Le protocole HTTP et ses méthodes GET, PUT, PUT et DELETE qui permettent d’interagir avec ces ressources
  • La dimension « Stateless » permet d’assurer une montée en charge sans limite
  • Les mime type qui permettent de décrire le contenu d’une interaction

Alors évidemment vous ne pourrez pas découvrir automatiquement dans un annuaire un service REST ; vous ne pourrez pas dynamiquement faire correspondre son contenu à un objet construit dynamiquement ; vous ne pourrez pas l’implémenter sur tout un ensemble de protocoles de MQSeries à IMAP/SMTP en passant par SOAP ; vous ne gèrerez pas la sécurité, les transactions, les attachements, les versions ou la sémantique… Bref, REST ça veut dire simple et ultra facile à intégrer ! C’est la plupart du temps 5 URI et une doc de 3 pages pour expliquer comment l’utiliser.

Maintenant que la stack WS-* est devenu le Next-Gen CORBA, quelques personnes un peu saine d’esprit se disent que pour planter un clou, rien ne vaut parfois marteau ou un pistolet à clou. C’est REST ! Et ça marche… en 10 minutes.

Java EE 6 spécifie une API REST nommée JAX-RS (aka javax.ws.rs.*). L’implémentation de référence de cette API est le projet Jersey qui n’est ni plus ni moins qu’une servlet qui prend en charge vos classes java en fonction d’annotations que vous allez utiliser. Ca parait compliqué dit comme ça mais comme vous allez vous en rendre compte, c’est bête comme un pistolet à clous. Dans cet article, vous trouverez un exemple d’implémentation d’un service REST développé en JAX-RS, implémenté avec Jersey et déployé sur Glassfish 3.0.

Créer une classe basée sur l’API JAX-RS

L’API REST s’appuie sur le principe des ressources. Pour implémenter un service REST, il suffit donc d’implémenter une classe qui contient des méthodes capables de traiter des flux entrant ou sortant. Selon le type de méthode HTTP (GET, POST, PUT ou DELETE), la méthode doit prendre un ou plusieurs paramètres du type qui vous arrange ! Dans mon exemple, j’utilise un type String pour renvoyer le contenu de la méthode mais vous pouvez par exemple utiliser un OutputStream. Pour implementer le service REST, il suffit ensuite d’utiliser quelques annotations pour faire le lien entre la Servlet et votre classe, vos méthodes, vos paramètres. Voici un HelloWorld du genre :

package demo.arkzoyd;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

@Path("demo")
public class RESTDemoService {

@GET @Path("{myparam}")
@Produces("text/html")
public String getHtml(@PathParam("myparam") String myparam) {
return "<html><body>"+myparam+"</body></html>";
}
}

Ici les annotations signifient ce qui suit :

  • @Path indique le chemin de la classe et de la méthode; si la servlet s’appelle jax-rs, par exemple, pour référencer la classe et la méthode getHtml ci-dessous, il suffit de mettre jax-rs/demo/[qqchose] dans votre URI
  • @PathParam permet de référencer un paramètre dans les annotations @Path. Dans le cas ci-dessous, le paramètre que vous passerez dans l’URL sera affecté en valeur au paramètre String myparam de votre méthode getHtml
  • @GET indique que votre méthode implémente la méthode HTTP GET
  • @Produces("text/html") indique que le mime type renvoyé par la méthode est de type HTML

Et c’est fini; vous avez développé un service RESTful; il vous reste à le déployer…

Déployer votre service REST avec Jersey

Pour déployer votre service JAX-RS, il suffit de l’ajouter à une application web (e.g. un .war !) et de vous assurer que cette application implémente la servlet JAX-RS. Dans mon cas, j’utilise Glassfish et l’implémentation de référence Jersey; mon descripteur de déploiement ressemble simplement à ce qui suit :

<?xml version="1.0" encoding="ASCII"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>rest</display-name>
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/jaxrs/*</url-pattern>
</servlet-mapping>
</web-app>

Si vous utilisez Oracle Enterprise Pack for Eclipse (OEPE) et Glassfish, le fait d’ajoutez la Facet JAX-RS à votre projet modifie votre descripteur de déploiement et vous pourrez déployer votre service en cliquant « Run on Server ».

Accéder à votre service REST depuis votre navigateur web

Etant donné que votre service REST s’appuie entièrement sur les principes du web et que mon exemple renvoie un mime-type HTML, il est possible d’utiliser le service web depuis votre navigateur web préféré; dans mon cas, mon serveur étant red.arkzoyd.com:8080 et mon application rest, pour utiliser le service REST, il suffit de naviguer vers l’URL http://red.arkzoyd.com:8080/rest/jax-rs/demo/ABCD pour vous afficher une page web dont le BODY est ABCD, c’est à dire la valeur de mon paramétre.

Développer un client REST

Ca parait assez logique, REST étant basé sur le WEB, vous pouvez interagir avec un service REST avec l’API réseau classique de Java SE. Pour simplifier ces interactions, Jersey propose une bibliothèque cliente: Voici donc un exemple de client qui utilise mon service avec l’API client de Jersey :

package demo.arkzoyd;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;

public class RestDemoClient {

public static void main(String[] args) {
Client client = Client.create();
WebResource webResource = client.resource(
"http://red.arkzoyd.com:8080/rest/jaxrs/demo/XyZ");
String s = webResource.get(String.class);
System.out.println(s);
}
}

Si j’exécute ce client, il retourne le contenu suivant :

<html><body>XyZ</body></html>

Alors vous me direz REST, JAX-RS, Jersey, beaucoup de bruit pour rien ? Les cas d’utilisation dans le contexte d’ouverture actuel du web et du triomphe des Twitter ou Amazon sont surement bien plus importants que les cas WS-*. Qu’est-ce que vous en dites ?

Gregory Guillou

About Gregory Guillou

Gregory Guillou has written 758 post in this blog.

Senior Technical Architect at Easyteam

3 thoughts on “JAX-RS ou Comment créer et utiliser des services RESTful en 10 min ?

  1. krm

    Bonsoir,

    Pour avoir le client on fait comment? Il faut importer quelque chose?
    Eh ben faire une petite page web qui permet de supprimer ajouter et modifier on fait comment? J’ai déjà une BD, mes services Rest fonctionnent…
    Merci.

  2. Alexis MP

    on peut se passer de web.xml au prix d’une classe héritant de javax.ws.rs.core.Application
    et annotée avec @ApplicationPath(« /jaxrs/* »)

    on peut aussi renvoyer des objets directement qui, s’ils sont annotés JAXB (@XmlRootElement), seront disponibles en XML et JSON sans effort particulier.

    (et merci pour tous ces blogs sur JavaEE et GlassFish!)