Java EE - EPSI POE mars 2017 - David Gayerie Licence Creative Commons

L'API JAX-RS

  1. La notion de ressource
  2. Implémenter des ressources avec JAX-RS
  3. Data binding
  4. Générer une réponse
  5. Gérer des exceptions
  6. La validation avec Bean Validation
  7. Injection des dépendances
  8. Support de l'hypermedia (HATEOAS)
  9. Implémenter un client HTTP
  10. Exercice : API Web et JDBC

JAX-RS est l'API conçue pour implémenter des API Web (aussi appelées Web Services RESTful). Les API Web exploitent les possibilités du protocole HTTP pour permettre à des systèmes d'information de communiquer et de s'échanger des services. JAX-RS est donc une API de programmation pour implémenter rapidement des applications basées sur HTTP. Ainsi, comme nous le verrons plus loin, son utilisation n'est pas réservée à l'implémentation de services mais il peut tout aussi bien être utilisé pour développer des applications Web plus traditionnelles.

JAX-RS 2.x est défini par la JSR 339. Comme pour tous les services et toutes API Java EE, il existe plusieurs implémentations de cette spécification : Jersey (l'implémentation de référence), RestEasy, Apache CXF... TomEE intègre l'implèmentation Apache CXF.

La notion de ressource

Dans le Web, ce qui est désigné par une URI est appelé une ressource. Une ressource offre une interface uniforme qui est définie dans HTTP par l'ensemble des méthodes : GET, HEAD, POST, PUT, DELETE, OPTIONS... Un client HTTP positionne dans sa requête une méthode pour indiquer le type d'opération que le serveur doit effectuer sur la ressource.

GET
Demande au serveur une représentation de la ressource cible.
HEAD
Comme un GET sauf que la réponse ne contient jamais de corps. Cette méthode est utile pour obtenir les informations des en-têtes HTTP et valider une requête sans envoyer ni recevoir de corps de message.
PUT
Crée ou met à jour l'état d'une ressource identifiée par l'URI.
DELETE
Détruit l'association de l'URI avec l'état de la ressource.
POST
La sémantique de la méthode POST est probablement la plus compliquée à saisir car cette méthode est utilisable dans différentes situations.
  • Le client souhaite créer une ressource sur le serveur en laissant au serveur le choix de l'URI de la ressource.
  • Le client souhaite ajouter une ressource à une ressource représentant une collection.
  • Le client souhaite que le serveur effectue un traitment.
  • Le client souhaite modifier partiellement une ressource.
OPTIONS
Permet d'obtenir les options de communication (par exemple : les méthodes autorisées pour l'URI). Le serveur doit retourner ces informations dans les en-têtes de réponse. Ainsi l'en-tête de réponse Allow liste les méthodes HTTP autorisées pour cette URI.
TRACE
Permet de simuler un écho de la requête. Cette méthode n'est pas utilisée pour la réalisation d'API Web car elle est surtout utile pour tester la configuration du réseau et obtenir des informations des proxies.
CONNECT
Établit un tunnel à travers un proxy. Cette méthode n'est pas utilisée pour la réalisation d'API Web.

Implémenter des ressources avec JAX-RS

JAX-RS permet d'implémenter des ressources sous la forme de composants Java EE. Une classe représentant une ressource est identifiée grâce à l'annotation @Path.

@Path
L'annotation @javax.ws.rs.Path indique le chemin d'URI qui identifie la ressource. Cette annotation est utilisable sur une classe et sur les méthodes. Utilisée sur une classe, cette annotation permet d'identifier la classe comme une ressource racine qui devient dès lors un composant géré par le serveur d'application.

package fr.epsi;

import javax.ws.rs.Path;

@Path("/user")
public class UserResource {
}

Utilisée sur une méthode, cette annotation permet de spécifier une sous-chemin dans la ressource. Si cette méthode retourne une classe utilisant des annotations JAX-RS, on parle alors de sous-ressource.


package fr.epsi;

import javax.ws.rs.Path;

@Path("/user")
public class UserResource {
	
  @Path("/geo")
  public GeoLocation getGeographicalLocation() {
    //...
  }

}

Dans l'exemple précédent, si la classe GeoLocation utilise elle-même des annotations JAX-RS alors on dit qu'il s'agit d'une sous-ressource. Il devient possible de créer des arborescences de ressources en Java basées sur le chemin de l'URI.

Les annotations de méthodes
JAX-RS fournit une annotation pour presque toutes les méthodes HTTP :

Elles permettent d'indiquer quelle méthode Java doit être appelée pour traiter la méthode de la requête HTTP entrante.


package fr.epsi;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;

@Path("/user")
public class UserResource {

  @GET
  public User get() {
    //....
  }

  @PUT
  public User createOrUpdate() {
    //....
  }
  
  @DELETE
  public void delete() {
    //....
  }

  @POST
  @Path("/subscription")
  public void subscribe() {
    //....
  }

}

Paramètre dans le chemin d'URI
Comme chaque ressource Web est identifiée par une URI, il est important pour le serveur de pouvoir récupérer dans le chemin les informations qui vont lui permettre de réaliser cette identification dynamiquement. Par exemple, le serveur peut extraire du chemin de la ressource une clé primaire lui permettant d'effectuer une recherche en base de données.

Avec JAX-RS, on déclare des paramètres de chemin entre accolades et on utilise l'annotation javax.ws.rs.PathParam pour récupérer leur valeur dans les paramètres des méthodes :


package fr.epsi;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path("/user/{id}")
public class UserResource {
  
  @GET
  public User get(@PathParam("id") long id) {
    //....
  }

  @PUT
  public User createOrUpdate(@PathParam("id") long id, User user) {
    //....
  }
  
  @DELETE
  public void delete(@PathParam("id") long id) {
    //....
  }

  @POST
  @Path("/subscription")
  public void subscribe(@PathParam("id") long id) {
    //....
  }

  @GET
  @Path("/subscription/{idSubscription}")
  public Subscription getSubscription(@PathParam("id") long id, 
                                      @PathParam("idSubscription") String idSub) {
    //....
  }
}

JAX-RS peut réaliser le transtypage d'un paramètre de chemin vers les types primitifs et les chaînes de caractères. Cela permet de garantir un premier contrôle de la validité de la donnée. Si la valeur attendue doit avoir un motif particulier, il est possible de le spécifier avec une expression régulière :


package fr.epsi;

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

@Path("/user/{id: [0-9]{5}}")
public class UserResource {
  
  private final long id;
  
  public UserResource(@PathParam("id") long id) {
    this.id = id;
  }
  
  @GET
  public User get() {
    // ...
  }

}

Par défaut, JAX-RS utilise comme expression régulière pour un paramètre de chemin [^/]+?

@Consumes / @Produces
Lorsqu'un client soumet une requête pour transmettre des informations au serveur (comme des données de formulaire) et quand un serveur retourne du contenu à un client, il est nécessaire de préciser le type de contenu. On utilise pour cela l'en-tête HTTP Content-type avec comme valeur le type MIME.

Une liste (non exhaustive) des types MIME les plus courants est :

text/plain Un fichier texte
text/plain;charset=utf-8 Un fichier texte encodé en UTF-8
text/html Un fichier HTML
application/x-www-form-urlencoded Le format de données pour la soumission d'un formulaire HTML
text/xml ou application/xml Un fichier XML
text/json ou application/json Un fichier JSON
image/jpeg Une image au format jpeg
application/octet-stream Un flux d'octets sans type particulier. Il s'agit du format par défaut si l'en-tête Content-type est absent.

La classe et/ou les méthodes d'une Ressource JAX-RS peuvent utiliser les annotations @Consumes et @Produces pour indiquer respectivement le type de contenu attendu dans la requête et le type de contenu de la réponse.


package fr.epsi;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;

@Path("/user/{id}")
public class UserResource {
  
  private final long id;
  
  public UserResource(@PathParam("id") long id) {
    this.id = id;
  }
  
  @GET
  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
  public User get() {
    // ...
  }

  @PUT
  @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
  public User createOrUpdate(User user) {
    // ...
  }
  
  @DELETE
  public void delete() {
    //....
  }

  @POST
  @Path("/subscription")
  public void subscribe() {
    //....
  }

  @GET
  @Path("/subscription/{idSubscription}")
  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
  public Subscription getSubscription(@PathParam("idSubscription") String idSub) {
    //....
  }
}

@QueryParam
Comme pour les paramètres de chemin, il est possible de récupérer la valeur des paramètres de la requête comme arguments des méthodes de la ressource JAX-RS grâce à l'annotation @javax.ws.rs.QueryParam.

  @GET
  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
  public List<User> search(@QueryParam("name") String name) {
    // ...
  }

@FormParam
Les données transmises via un formulaire HTML peuvent être récupérées comme arguments des méthodes de la ressource JAX-RS grâce à l'annotation @javax.ws.rs.FormParam. Pour le cas d'une requête de formulaire, le contenu attendu est presque toujours de type application/x-www-form-urlencoded.

  @POST
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  public void create(@FormParam("name") String name, @FormParam("age") int age) {
    // ...
  }

@Context
Si vous avez besoin d'obtenir des informations sur le contexte d'exécution de la requête, vous pouvez utilisez l'annotation @javax.ws.rs.core.Context pour obtenir une instance d'une classe particulière. Les classes supportées sont :

  @GET
  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
  public List<User> search(@Context UriInfo uriInfo, @Context Request req) {
    // ...
  }

Data binding

Lorsqu'une méthode d'une ressource retourne une instance d'un objet Java, JAX-RS va tenter de créer une réponse au format souhaité en fonction de l'annotation @Produces. Il existe un ensemble de règles par défaut permettant de passer d'un objet Java à un document XML ou JSON. On appelle l'ensemble de ces règle le data binding.

Si la réponse attentue est au format JSON alors JAX-RS va contruire une réponse en se basant sur les accesseurs (les getters) de la classe.

Si on souhaite retourner une instance de la classe suivante :


package fr.epsi;

import java.util.ArrayList;
import java.util.List;

public class Person {
  
  private String name;
  private int age;
  private List<Person> children = new ArrayList<>();
  
  public Person() {
  }
  
  public Person(String name, int age) {
    this.name = name;
    this.setAge(age);
  }

  public String getName() {
    return name;
  }
  
  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  public List<Person> getChildren() {
    return children;
  }
  
  public Person addChild(Person child) {
    this.children.add(child);
    return child;
  }
}

Si on définit une ressource de la façon suivante :


package fr.epsi;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/person")
public class PersonResource {
  
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public Person get() {
    Person michel = new Person("Michel Raynaud", 56);
    michel.addChild(new Person("Anne Raynaud", 38)).addChild(new Person("Pierre Blémand", 16));
    michel.addChild(new Person("Damien Raynaud", 32));
    return michel;
  }
}

Alors un appel HTTP à cette ressource génèrera un document JSON de la forme :


{"children":[
  {"children":[
    {"children":[],
     "name":"Pierre Blémand",
     "age":16}
   ],
   "name":"Marie Raynaud",
   "age":38},
  {"children":[],
   "name":"Damien Raynaud",
   "age":32}
 ],
 "name":"Michel Raynaud",
 "age":56}
 
 

Il est également possible de passer d'une instance Java à un document XML ou d'un document XML à une instance Java. Pour cela, JAX-RS utilise JAXB (Java Architecture for XML Binding) qui intégré au langage Java. JAXB utilise des annotations pour fournir des indications sur la façon dont une classe Java peut être associée à un document XML.

Les principales annotations JAXB sont :

@XmlRootElement
Une annotation est utilisable sur une classe Java pour indiquer quelle peut être utilisée pour représenter la racine d'un document XML. On peut utiliser l'attribut name de l'annotation pour préciser le nom de l'élément racine du document XML et l'attibut namespace pour en préciser l'espace de nom.
@XmlElement
Une annotation est utilisable sur les accesseurs (getters) des propriétés d'une classe. On peut utiliser l'attribut name de l'annotation pour préciser le nom de l'élément racine du document XML et l'attibut namespace pour en préciser l'espace de nom. Cette annotation est optionnelle. Par défaut JXB considère qu'une propriété produit un élément XML du même nom et sans espace de nom XML.
@XmlTransient
Cette annotation, ajoutée sur les accesseurs d'une propriété d'une classe, indique que cette propriété ne doit pas apparaître dans le document XML.

Si nous reprenons l'exemple de la classe Person, nous pouvons ajouter les annotations JAXB :


package fr.epsi;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="person", namespace="http://www.epsi.fr/cours/javaee")
public class Person {
  
  private String name;
  private int age;
  private List<Person> children = new ArrayList<>();
  
  public Person() {
  }
  
  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  @XmlElement(namespace="http://www.epsi.fr/cours/javaee")
  public String getName() {
    return name;
  }
  
  public void setName(String name) {
    this.name = name;
  }

  @XmlElement(namespace="http://www.epsi.fr/cours/javaee")
  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  @XmlElement(name="person", namespace="http://www.epsi.fr/cours/javaee")
  @XmlElementWrapper(name="children", namespace="http://www.epsi.fr/cours/javaee")
  public List<Person> getChildren() {
    return children;
  }
  
  public Person addChild(Person child) {
    this.children.add(child);
    return child;
  }
}

Si nous autorisons une ressource à produire du XML :


package fr.epsi;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/person")
public class PersonResource {
  
  @GET
  @Produces(MediaType.APPLICATION_XML)
  public Person get() {
    Person michel = new Person("Michel Raynaud", 56);
    michel.addChild(new Person("Anne Raynaud", 38)).addChild(new Person("Pierre Blémand", 16));
    michel.addChild(new Person("Damien Raynaud", 32));
    return michel;
  }
}

Alors un appel HTTP à cette ressource génèrera un document JSON de la forme :


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person xmlns="http://www.epsi.fr/cours/javaee">
  <age>56</age>
  <children>
    <person>
      <age>38</age>
      <children>
        <person>
          <age>16</age>
          <children/>
          <name>Pierre Blémand</name>
        </person>
      </children>
      <name>Anne Raynaud</name>
    </person>
    <person>
      <age>32</age>
      <children/>
      <name>Damien Raynaud</name>
    </person>
  </children>
  <name>Michel Raynaud</name>
</person>

Générer une réponse

Parfois, il n'est pas suffisant de retourner une instance d'un objet Java en laissant à JAX-RS le soin de créer la réponse HTTP. C'est notamment le cas si l'on souhaite retourner un code statut HTTP différent de 200 ou ajouter des en-têtes HTTP dans la réponse. Pour cela, il faut retourner une instance de la classe javax.rs.core.Response. Cette classe suit le design pattern builder et offre un ensemble de méthodes utilitaires pour construire la réponse. Au final, il suffit d'appeler la méthode build() et retourner le résultat.

Exemple d'utilisation de la classe javax.rs.core.Response

package fr.epsi;

import java.net.URI;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

@Path("/person")
public class PersonResource {

  @GET
  @Path("/{name}")
  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
  public Response get(@PathParam("name") String name) { 
    Person person;
    
    // ...
    
    return Response.ok(person).build();
  }

  @POST
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
  public Response create(Person person, @Context UriInfo uriInfo) {
    
    // ... on sauvegarde la représentation de la personne
    
    // on construit l'URI correspondant à la personne
    URI location = uriInfo.getRequestUriBuilder()
                          .path(person.getName())
                          .build();
    
    // On retourne la réponse
    return Response.created(location).entity(person).build();
  }
}

Gérer des exceptions

Par défaut, si une méthode d'une ressource génère une exception, alors JAX-RS la transforme en erreur HTTP 500. Si l'on souhaite retourner un statut d'erreur différent, il est bien évidemment possible d'utiliser la classe javax.rs.core.Response, mais il est plus intéressant de fournir les indications nécessaires à JAX-RS pour modifier son comportement selon le type d'exception lancé par la méthode de la ressource.

Il est possible de lancer une exception de type WebApplicationException ou une exception en héritant. JAX-RS fournit déjà des exceptions spécialisées pour les codes de statut les plus courants : NotFoundException, BadRequestException, ServerErrorException... et même la possibilité de traiter les redirections avec l'exception RedirectionException.

Il est également possible de déclarer une classe implémentant l'interface ExceptionMapper. Un ExceptionMapper est déclaré pour un type d'exception et ses exceptions filles.

Exemple d'un ExceptionMapper pour les exceptions de type ValiditionException

package fr.epsi;

import javax.validation.ValidationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class ValidationExceptionMapper implements ExceptionMapper<ValidationException>{

  @Override
  public Response toResponse(ValidationException exception) {
    return Response.status(Status.BAD_REQUEST)
                   .type(MediaType.TEXT_PLAIN)
                   .entity(exception.getMessage())
                   .build();
  }

}

Dans l'exemple ci-dessus, tout appel à une méthode de ressource qui se terminera par une exception de type ValidationException entrainera un appel de la méthode ValidationExcceptionMapper.toResponse qui génèrera une réponse de type 400 (Bad Request) avec un message en texte brut correspondant au message de l'exception.

La validation avec Bean Validation

Le serveur d'application fournit un service nommé Bean Validation (JSR303). Bean Validation permet d'exprimer les contraintes de validité d'un objet ou des paramètres d'une méthode de ressouce avec des annotations. JAX-RS utilise les informations de ces annotations pour valider les requêtes HTTP.

Utilisation de Bean Validation sur les attributs d'une classe

package fr.epsi;

import java.util.ArrayList;
import java.util.List;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="person", namespace="http://www.epsi.fr/cours/javaee")
public class Person {
  
  @Size(min = 1, message = "Le nom est obligatoire !")
  private String name;

  @Min(value=1, message = "L'âge doit être un nombre positif !")
  @Max(value=99, message = "L'âge ne peut pas dépasser 99 ans !")
  private int age;
  
  private List  <Person> children = new ArrayList  <>();
  
  public Person() {
  }
  
  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  @XmlElement(namespace="http://www.epsi.fr/cours/javaee")
  public String getName() {
    return name;
  }
  
  public void setName(String name) {
    this.name = name;
  }

  @XmlElement(namespace="http://www.epsi.fr/cours/javaee")
  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  @XmlElement(name="person", namespace="http://www.epsi.fr/cours/javaee")
  @XmlElementWrapper(name="children", namespace="http://www.epsi.fr/cours/javaee")
  public List  <Person> getChildren() {
    return children;
  }
  
  public Person addChild(Person child) {
    this.children.add(child);
    return child;
  }
}

Utilisation de Bean Validation sur un paramètre de méthode d'une ressource

package fr.epsi;

import javax.validation.constraints.Size;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/person")
public class PersonResource {

  @GET
  @Path("/{name}")
  @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
  public Response get(
      @Size(min = 1, message = "Chemin de ressource invalide !") 
      @PathParam("name") String name) {
    Person person;

    // ...

    return Response.ok(person).build();
  }
}

La documentation des annotations de Bean Validation est disponible dans la documentation de l'API Java EE : http://docs.oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html

Injection des dépendances

Comme les Servlets, les ressources racines (celles identifiées par l'annotation @Path sur la classe) sont des composants Java EE. À ce titre, elles supportent l'injection de dépendance avec, par exemple, l'annotation @Resource.

Exemple d'injection d'une DataSource

package fr.epsi;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.annotation.Resource;
import javax.sql.DataSource;
import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/person")
public class PersonResource {
  
  @Resource(name="person")
  private DataSource dataSource;

  @GET
  @Path("/{id}")
  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
  public Person get(@PathParam("id") long id) throws SQLException {
    try(Connection con = dataSource.getConnection();
      Statement stmt = con.createStatement();
      ResultSet rs = stmt.executeQuery("select name, age from Person where id=" + id)) {

      if (! rs.next()) {
        throw new NotFoundException();
      }
      return new Person(rs.getString("name"), rs.getInt("age"));
    }
  }
}

Support de l'hypermedia (HATEOAS)

JAX-RS permet d'implémenter un support de l'hypermedia grâce aux liens Web. La classe Link permet de construire une représentation Java d'un lien HTTP :


  Link link = Link.fromPath("/persons").rel("collection").title("Liste des individus").build();

On peut aussi directement positionner un lien dans la réponse HTTP grâce à la méthode link lors de la construction de la réponse :


  Response.ok().link("/persons", "collection").build();

Le code ci-dessus produira une réponse HTTP de la forme :


HTTP/1.1 200 OK
Link: </persons>; rel="collection"
Content-length: 0


La classe Link est également sérialisable en JSON ou XML, il est donc possible de s'en servir comme attribut dans une classe Java.

Implémenter un client HTTP

JAX-RS fournit également une API pour implémenter un client HTTP. On utilise la classe ClientBuilder pour créer une instance de la classe Client.

Exemple d'utilisation d'un client HTTP

package fr.epsi;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;

public class ExempleClient {

  public static void main(String[] args) {
    Client client = ClientBuilder.newClient();

    WebTarget target = client.target("http://www.server.net/person");
    Person person = target.request().get(Person.class);
    
    // ...
  }
}

Exercice : API Web et JDBC

Objectif

Développer une API Web permettant d'ajouter, de supprimer ou de consulter des individus. Un individu est défini par son nom, son prénom et son âge.

Script SQL

Pour la base de données MySQL, le script de création de la table Person sera :


CREATE TABLE IF NOT EXISTS Person (
  id int(11) NOT NULL AUTO_INCREMENT,
  firstname varchar(200) NOT NULL,
  lastname varchar(200) NOT NULL,
  age int(3),
  dateCreation date NOT NULL,
  PRIMARY KEY (id)
) engine=innodb;
        			
Modèle Maven du projet à télécharger
webapp-template.zip
Mise en place du projet
Éditer le fichier pom.xml du template et modifier la balise artifactId pour spécifier le nom de votre projet. Pensez à déclarer la dépendance vers le pilote JDBC dans le fichier pom.xml
Intégration du projet dans Eclipse
L'intégration du projet dans Eclipse suit la même procédure que celle vue lors de l'introduction à Maven
Correction
Vous pouvez télécharger un exemple d'implémentation de la solution.