Tutoriel sur le développement de services web REST avec JAX-RS, Maven et Eclipse

Le but de cette troisième leçon est d'apprendre à manipuler l'API JAX-RS pour le développement de services web REST à partir de la plateforme de développement Java. La leçon insiste sur les développements serveur et client d'un service web REST.

Chaque exercice est fourni avec un projet Java Maven contenant des classes et des fichiers de configuration qu'il faudra compléter au fur et à mesure des questions. À la fin de chaque exercice une solution du projet Java sera donnée.

Buts pédagogiques : transformation d'une classe Java en service web REST, manipulation des annotations JAX-RS, génération de fichier WADL, utilisation de SOAP-UI pour invoquer un service REST à partir de WADL, utilisation de l'implémentation JERSEY, utilisation de l'API cliente de JERSEY.

Pour réagir au contenu de ce tutoriel, un espace de dialogue vous est proposé sur le forum : 5 commentaires Donner une note à l'article (5).

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Prérequis logiciels

Avant de démarrer cette série d'exercices sur l'utilisation de l'API JAX-WS, veuillez préparer votre environnement de développement en installant les outils suivants :

II. Exercice 1 : développer un service web REST « Bonjour ENSMA »

III-A. But

  • Développer un service web REST à partir d'une classe Java.
  • Publier en local.
  • Afficher le contrat de description WADL.
  • Tester le service web avec CURL puis SOAP-UI.

III-B. Description

Le service web de type REST de ce premier exercice consiste à fournir un accès à la ressource « Bonjour ENSMA » qui permet de donner des messages différents selon la date du jour. Les services proposés n'autorisent que la lecture à la ressource (GET). Ces services de récupération peuvent posséder des paramètres. Enfin, le format de récupération de la ressource est du XML.

III-C. Étapes à suivre

  • Démarrer l'environnement de développement Eclipse.
  • Importer le projet Maven HelloENSMARestWebServiceExercice1.zipHelloENSMARestWebServiceExercice1.zip (File -> Import -> General -> Existing Projects into Workspace et choisir l'option Select archive file puis sélectionner l'archive).
  • Depuis le package soa.jaxrslabs.helloensmarestwebserviceexercice1, créer une classe HelloENSMA qui représentera la ressource « Bonjour ENSMA ». La ressource sera accessible via le chemin /helloensma.
 
Sélectionnez
1.
2.
3.
4.
@Path("helloensma")
public class HelloENSMA {
    public HelloENSMA() { }
}
  • Dans le corps de la méthode String getXml()utilisée pour récupérer la ressource « Bonjour ENSMA », recopier le contenu suivant :
 
Sélectionnez
1.
2.
3.
4.
5.
@GET
@Produces("application/xml")
public String getXml() {
    return "<bonjour>Bonjour ENSMA</bonjour>";
}
  • Afin de résoudre les problèmes de dépendances vers la bibliothèque Jax-RS, compléter le fichier de description Maven pom.xml en ajoutant la dépendance suivante (balise dependencies) :
 
Sélectionnez
1.
2.
3.
4.
5.
<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet-core</artifactId>
    <version>2.12</version>
</dependency>
  • Créer la classe HelloENSMAMain utilisée pour publier en local notre service REST.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
public class HelloENSMAMain {

    public static final URI BASE_URI = getBaseURI();

    private static URI getBaseURI() {
        return UriBuilder.fromUri("http://localhost/rest/").port(9991).build();
    }

    public static void main(String[] args) {
        ResourceConfig rc = new ResourceConfig();
        rc.packages("soa.jaxrslabs.helloensmarestwebserviceexercice1");
        try {
            HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, rc);
            server.start();

            System.out.println(String.format("Jersey app started with WADL available at "
                    + "%sapplication.wadl\nHit enter to stop it...",
                    BASE_URI, BASE_URI));
            System.in.read();
            server.shutdownNow();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • Afin de résoudre les problèmes de dépendances vers le serveur Grizzly, compléter le fichier de description Maven pom.xml.
 
Sélectionnez
1.
2.
3.
4.
5.
<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-grizzly2-http</artifactId>
    <version>2.12</version>
</dependency>
  • Exécuter la classe HelloENSMAMain.
  • Ouvrir une fenêtre d'un navigateur web et tester la récupération de la ressource « Bonjour ENSMA » (requête GET via l'URL http://localhost:9991/rest/helloensma).)

Ce premier service REST n'est pas parfait puisque le type de retour est une simple chaîne de caractères. Comment pourrions-nous retourner à la fois une information, un code de statut ou des informations dans l'en-tête de la réponse ? Pour cela, nous allons utiliser un objet Response pour le retour des prochains services REST.

  • Ajouter une nouvelle méthode Java getXmlWithParams dans la classe HelloENSMA qui permet de récupérer la ressource « Bonjour ENSMA » en XML via des paramètres de requêtes. Ces paramètres seront donnés via le chemin et via l'en-tête de la requête en utilisant respectivement les annotations @PathParam et @HeaderParam.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
@GET
@Path("{id}")
@Produces("application/xml")
public Response getXmlWithParams(
        @PathParam("id") String id,
        @DefaultValue("all") @HeaderParam("name") String name) {
    System.out.println(id);
    System.out.println(name);
    return Response
      .status(Status.OK)
      .entity("<bonjour>Bonjour ENSMA de la part de " + name + "</bonjour>")
      .build();
}

Pour envoyer des paramètres au niveau de l'en-tête de la requête, nous utiliserons l'outil CURL, qui est un outil en ligne de commande, pour construire des requêtes HTTP (disponible à l'adresse suivante : http://curl.haxx.se/)).

  • Depuis une invite de commande saisir la commande suivante :
Console exercice 1
  • À partir d'un navigateur web, afficher le contrat de description WADL via l'URL suivante : http://localhost:9991/rest/application.wadl.
  • Démarrer l'outil SOAP-UI et créer un projet à partir de ce contrat de description.
  • Envoyer une requête HTTP de type GET pour récupérer une ressource « Bonjour ENSMA ». Modifier cette requête de façon à transmettre également les paramètres via le chemin et via l'en-tête de la requête HTTP.

III. Exercice 2 : développer un service web REST « Interrogation et réservation d'un train »

IV-A. But

  • Développer un service web REST à partir d'une classe Java.
  • Utilisation d'un Sub-Resource Locator.
  • Mise en place d'un CRUD complet.
  • Publier en local.
  • Tester le service web avec Postman.

IV-B. Description

Le service web REST de ce deuxième exercice consiste à créer un système CRUD pour l'interrogation et la réservation de trains. Les ressources manipulées par les services sont donc un train et une réservation. Le service web REST doit pouvoir lister l'ensemble des trains, lister les trains qui satisfont un critère de recherche (ville de départ, ville d'arrivée, jour de départ et un intervalle de temps), de créer, de modifier, de supprimer et de lister une réservation pour un client donné. Nous insisterons sur l'accessibilité des services et non sur le code métier.

IV-C. Étapes à suivre

  • Importer le projet Maven BookTrainRestWebServiceExercice2.zipBookTrainRestWebServiceExercice2.zip (File -> Import -> General -> Existing Projects into Workspace et choisir l'option Select archive file puis sélectionner l'archive).
  • Créer la classe Train (dans le package soa.jaxrslabs.booktrainrestwebserviceexercice2) qui modélise le concept de Train et qui contient un attribut String numTrain (identifiant fonctionnel d'un train), un attribut String villeDepart (la ville de départ du train), un attribut String villeArrivee (la ville d'arrivée du train), un attribut int heureDepart (heure de départ depuis la ville de départ). Ajouter des modificateurs et des accesseurs sur tous les attributs. Voir le code suivant :
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
package soa.jaxrslabs.booktrainrestwebserviceexcercice2;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "train")
public class Train {

    private String numTrain;

    private String villeDepart;

    private String villeArrivee;

    private int heureDepart; // Format : 1230 = 12h30

    public Train() {
    }

    public Train(String numTrain, String villeDepart, String villeArrivee, int heureDepart) {
        this.numTrain = numTrain;
        this.villeDepart = villeDepart;
        this.villeArrivee = villeArrivee;
        this.heureDepart = heureDepart;
    }

    public int getHeureDepart() {
        return heureDepart;
    }

    public void setHeureDepart(int heureDepart) {
        this.heureDepart = heureDepart;
    }

    public String getNumTrain() {
        return numTrain;
    }

    public void setNumTrain(String numTrain) {
        this.numTrain = numTrain;
    }

    public String getVilleArrivee() {
        return villeArrivee;
    }

    public void setVilleArrivee(String villeArrivee) {
        this.villeArrivee = villeArrivee;
    }

    public String getVilleDepart() {
        return villeDepart;
    }

    public void setVilleDepart(String villeDepart) {
        this.villeDepart = villeDepart;
    }
}
  • Créer la classe BookTrainBDqui sert à laisser persister toutes les informations concernant le service web de cet exercice.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
package soa.jaxrslabs.booktrainrestwebserviceexcercice2;

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

public class BookTrainBD {

    private static List<Train> trains = new ArrayList<Train>();

    private static List<BookTrain> bookTrains = new ArrayList<BookTrain>();

    static {
        trains.add(new Train("TR123", "Poitiers", "Paris", 1250));
        trains.add(new Train("TR127", "Poitiers", "Paris", 1420));
        trains.add(new Train("TR129", "Poitiers", "Paris", 1710));
    }

    public static List<Train> getTrains() {
        return trains;
    }

    public static List<BookTrain> getBookTrains() {
        return bookTrains;
    }
}
  • Créer la classe TrainResource(dans le package soa.jaxrslabs.booktrainrestwebserviceexercice2) permettant l'accès aux services web REST de la ressource Train. Définir comme chemin de ressource racine la valeur /trains(utilisation de l'annotation @Path) puis ajouter trois méthodes qui permettent respectivement de retourner 1) la liste des trains 2) un train en fonction de son identifiant fonctionnel et 3) une recherche de trains par critères passés en paramètres de la requête (ville de départ, ville d'arrivée et heure de départ). Pour cette dernière méthode, le sous-chemin associé est /search. Noter que le format de retour des services est du XML.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
package soa.jaxrslabs.booktrainrestwebserviceexcercice2;

import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

@Path("/trains")
@Produces("application/xml")
public class TrainResource {

    public TrainResource() {
    }

    @GET
    public Response getTrains() {
        System.out.println("getTrains");

        return Response
          .status(Status.OK)
          .entity(BookTrainBD.getTrains())
          .build();
    }

    @GET
    @Path("numTrain-{id}")
    public Response getTrain(@PathParam("id") String numTrain) {
        System.out.println("getTrain");

        for (Train current : BookTrainBD.getTrains()) {
            if (numTrain.equals(current.getNumTrain())) {
                return Response
                  .status(Status.OK)
                  .entity(current)
                  .build();
            }
        }

        return Response
          .status(Status.NO_CONTENT)
          .build();
    }

    @GET
    @Path("/search")
    public Response searchTrainsByCriteria(@QueryParam("departure") String departure, @QueryParam("arrival") String arrival, @QueryParam("arrivalhour") String arrivalHour) {
        System.out.println("searchTrainsByCriteria");

        return Response
          .status(Status.OK)
          .entity(BookTrainBD.getTrains().subList(0, 2))
          .build();
    }
}
  • Créer la classe BookTrainMainutilisée pour publier en local notre service REST.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
package soa.jaxrslabs.booktrainrestwebserviceexcercice2;

import java.net.URI;

import javax.ws.rs.core.UriBuilder;

import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;

public class BookTrainMain {

    public static final URI BASE_URI = getBaseURI();

    private static URI getBaseURI() {
        return UriBuilder.fromUri("http://localhost/rest/").port(9992).build();
    }

    public static void main(String[] args) {
        ResourceConfig rc = new ResourceConfig();
        rc.registerClasses(BookTrainResource.class, TrainResource.class);

        try {
            HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, rc);
            server.start();

            System.out.println(String.format("Jersey app started with WADL available at "
                    + "%sapplication.wadl\nHit enter to stop it...",
                    BASE_URI, BASE_URI));

            System.in.read();
            server.shutdownNow();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
package soa.jaxrslabs.booktrainrestwebserviceexcercice2;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "booktrain")
public class BookTrain {

    private String numBook;

    private Train currenTrain;

    private int numberPlaces;

    public String getNumBook() {
        return numBook;
    }

    public void setNumBook(String bookNumber) {
        this.numBook = bookNumber;
    }

    public Train getCurrenTrain() {
        return currenTrain;
    }

    public void setCurrenTrain(Train currenTrain) {
        this.currenTrain = currenTrain;
    }

    public int getNumberPlaces() {
        return numberPlaces;
    }

    public void setNumberPlaces(int numberPlaces) {
        this.numberPlaces = numberPlaces;
    }
}
  • Compléter la classe BookTrainBDde façon à laisser persister les informations concernant les services liés à la réservation de trains.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
package soa.jaxrslabs.booktrainrestwebserviceexcercice2;

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

public class BookTrainBD {

    private static List<Train> trains = new ArrayList<Train>();

    private static List<BookTrain> bookTrains = new ArrayList<BookTrain>();

    static {
        trains.add(new Train("TR123", "Poitiers", "Paris", 1250));
        trains.add(new Train("TR127", "Poitiers", "Paris", 1420));
        trains.add(new Train("TR129", "Poitiers", "Paris", 1710));
    }

    public static List<Train> getTrains() {
        return trains;
    }

    public static List<BookTrain> getBookTrains() {
        return bookTrains;
    }
}
  • Créer la classe BookTrainResource(dans le package soa.jaxrslabs.booktrainwebservicerestexercice2) permettant l'accès aux services web REST de la ressource Réservation. Quatre méthodes sont à définir. La première createBookTrainest invoquée pour la création d'une ressource Réservation (méthode POST). La deuxième getBookTrains(méthode GET) est utilisée pour lister l'ensemble des réservations. La troisième getBookTrain(méthode GET) permet de retourner les informations d'une réservation à partir d'un numéro de réservation. Finalement removeBookTrain(méthode DELETE) permet de supprimer une réservation.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
package soa.jaxrslabs.booktrainrestwebserviceexcercice2;

import java.util.List;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

public class BookTrainResource {

    @POST
    public Response createBookTrain(@QueryParam("numTrain") String numTrain, @QueryParam("numberPlaces") int numberPlaces) {  
        Train currentTrain = null;

        for (Train current : BookTrainBD.getTrains()) {
            if (current.getNumTrain().equals(numTrain)) {
                currentTrain = current;
            }
        }

        if (currentTrain == null) {
            return Response
              .status(Status.NO_CONTENT)
              .build();
        }

        BookTrain newBookTrain = new BookTrain();
        newBookTrain.setNumberPlaces(numberPlaces);
        newBookTrain.setCurrenTrain(currentTrain);
        newBookTrain.setNumBook(Long.toString(System.currentTimeMillis()));

        BookTrainBD.getBookTrains().add(newBookTrain);

        return Response
          .status(Status.OK)
          .entity(newBookTrain.getNumBook())
          .build();
    }

    @GET
    public Response getBookTrains() {
        System.out.println("getBookTrains");

        return Response
          .status(Status.OK)
          .entity(BookTrainBD.getBookTrains())
          .build();
    }

    @GET
    @Path("{id}")
    public Response getBookTrain(@PathParam("id") String bookNumber) {
        List<BookTrain> bookTrains = BookTrainBD.getBookTrains();

        for (BookTrain current : bookTrains) {
            if (current.getNumBook().equals(bookNumber)) {
                return Response
                  .status(Status.OK)
                  .entity(current)
                  .build();
            }
        }

        return Response
          .status(Status.NO_CONTENT)
          .build();
    }

    @DELETE
    @Path("{id}")
    public Response removeBookTrain(@PathParam("id") String bookNumber) {
        BookTrain currentBookTrain = null;
        for (BookTrain current : BookTrainBD.getBookTrains()) {
            if (current.getNumBook().equals(bookNumber)) {
                currentBookTrain = current;
            }
        }

        BookTrainBD.getBookTrains().remove(currentBookTrain);
        return Response.status(Status.ACCEPTED).build();
    }
}
  • L'accès à la ressource Réservation (via la classe BookTrainRessource) est obtenu via l'utilisation d'un sub-resource locator. Compléter la classe TrainResource.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
package soa.jaxrslabs.booktrainrestwebserviceexcercice2;

import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

@Path("/trains")
@Produces("application/xml")
public class TrainResource {

    // Identique au code précédent

    @Path("/booktrains")
    public BookTrainResource getBookTrainResource() {
        return new BookTrainResource();
    }
}
  • Compléter la classe BookTrainMain de manière à ajouter la classe BookTrainResource correspondant à la ressource Réservation.
  • Exécuter la classe BookTrainMain et à partir de CURL, SOAP-UI ou Postman, invoquer chaque service (création d'une réservation, lister les réservations, obtenir les informations d'une réservation et supprimer la réservation créée).

Solution de l'exercice 2 : BookTrainRestWebServiceExercice2-sol.zipBookTrainRestWebServiceExercice2-sol.zip

IV. Exercice 3 : développer un client de service web REST « Interrogation et réservation de trains »

V-A. But

  • Développer un client de service web REST à partir de l'API JERSEY.
  • Création des requêtes via le patron Builder.

V-B. Description

Ce troisième exercice se propose de fournir un client pour l'accès au service web REST défini dans l'exercice 2. Une interface graphique en Java/Swing permet de contrôler les appels aux différents services.

Swing exercice 2

V-C. Étapes à suivre

  • Importer le projet Maven BookTrainRestWebServiceExercice3.zipBookTrainRestWebServiceExercice3.zip (File -> Import -> General -> Existing Projects into Workspace et choisir l'option Select archive file puis sélectionner l'archive).
  • Copier les classes BookTrain et Train du projet BookTrainRestWebServiceExercice2 vers le projet BookTrainRestWebServiceExercice3.
  • Compléter la classe BookTrainClientMain à partir du code ci-dessous. Noter que les traitements des trois boutons seront à compléter par la suite (callGetTrains(), callGetBookTrains(), createBookTrains()).
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
package soa.jaxrslabs.booktrainrestwebserviceexcercice3;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;

public class BookTrainClientMain extends JFrame {

    // Sera complété dans la suite.

    public BookTrainClientMain() {
        super("Client Réservation Train");

        this.initializeService();
        this.setLayout(new GridLayout(3, 1, 10, 10));
        JPanel panelTrains = new JPanel();
        panelTrains.setLayout(new GridLayout(1, 1));

        JButton getTrains = new JButton("GetTrains");
        panelTrains.add(getTrains);
        getTrains.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                callGetTrains();
            }
        });

        JPanel panelBookTrains = new JPanel();
        panelBookTrains.setLayout(new GridLayout(1, 1));

        JButton getBookTrains = new JButton("GetBookTrains");
        panelBookTrains.add(getBookTrains);
        getBookTrains.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                callGetBookTrains();
            }
        });

        JPanel createBookTrainFormPanel = new JPanel();
        createBookTrainFormPanel.setLayout(new GridLayout(1, 3));
        final JTextField numTrain = new JTextField();
        final JTextField numberPlaces = new JTextField();
        JButton createBookTrains = new JButton("CreateBookTrain");
        createBookTrains.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                createBookTrains(numTrain.getText(), numberPlaces.getText());
            }
        });
        createBookTrainFormPanel.add(createBookTrains);
        createBookTrainFormPanel.add(numTrain);
        createBookTrainFormPanel.add(numberPlaces);

        this.add(panelTrains);
        this.add(panelBookTrains);
        this.add(createBookTrainFormPanel);

        this.pack();
        this.setVisible(true);
    }

    public static void main(String[] args) {
        new BookTrainClientMain();
    }
}
  • Ajouter une méthode initializeService() qui permet d'initialiser l'accès au service web REST. Adapter l'URL selon l'emplacement déterminé par l'exercice 2.
  • Ajouter également un attribut target de type WebTarget.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public class BookTrainClientMain extends JFrame {

    private WebTarget target;

    private void initializeService() {
        Client client = ClientBuilder.newClient();
        target = client.target("http://localhost:9992").path("rest");
    }

    ...
}
  • Ajouter une méthode callGetTrains()qui permet de lister l'ensemble des trains.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
public class BookTrainClientMain extends JFrame {

    private void callGetTrains() {
        List<Train> result = target.path("trains")
                .request(MediaType.APPLICATION_XML_TYPE).get(new GenericType<List<Train>>() {
                });

        for (Train current : result) {
            System.out.println(current.getNumTrain() + " - "
                    + current.getVilleDepart() + " - "
                    + current.getVilleArrivee() + " - "
                    + current.getHeureDepart());
        }
    }

    ...
}
  • Ajouter une méthode createBookTrains(String numTrain, String numberPlaces)qui permet de créer une réservation d'un train. Compléter le code ci-dessous de façon à prendre en compte les paramètres de requêtes et l'appel à une méthode HTTP POST. Pour rappel, le service de création retourne un numéro de réservation (type String)
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
public class BookTrainClientMain extends JFrame {

    private void createBookTrains(String numTrain, String numberPlaces) {
        String numBook = target.path("trains").path("booktrains")
                .queryParam("numTrain", numTrain)
                .queryParam("numberPlaces", numberPlaces).request()
                .post(null, String.class);
        System.out.println(numBook);
    }

    ...
}
  • Ajouter une méthode callGetBookTrains() qui permet de récupérer l'ensemble des réservations qui ont été créées. Compléter le code ci-dessous.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
public class BookTrainClientMain extends JFrame {

    private void callGetBookTrains() {
        List<BookTrain> result = target.path("trains").path("booktrains")
                .request(MediaType.APPLICATION_XML_TYPE).get()
                .readEntity(new GenericType<List<BookTrain>>() {
                });

        for (BookTrain current : result) {
            System.out.println(current.getNumBook() + " - "
                    + current.getCurrenTrain().getNumTrain() + " - "
                    + current.getNumberPlaces());
        }
    }

    ...
}
  • Exécuter le programme en vous assurant que le service web REST défini dans l'exercice 2 est déployé et opérationnel.

Solution de l'exercice 3 : BookTrainRestWebServiceExercice3-sol.zipBookTrainRestWebServiceExercice3-sol.zip

V. Exercice 4 : déployer sous Tomcat (ou autre conteneur si existant)

VI-A. But

  • Packager un service web REST dans une archive War.
  • Déployer un service web.
  • Gérer les problèmes de dépendances.

VI-B. Description

Dans cet exercice nous allons déployer le service web REST BookTrainRestWebService sur le serveur d'application Java Tomcat.

VI-C. Étapes à suivre

Remarquez que le contenu des fichiers Java est identique au projet BookTrainRestWebServiceExercice1 excepté la disparition du fichier BookTrainMain. En effet, à partir de ce projet nous allons déployer sur un serveur d'application qui jouera le rôle de conteneur de service web.

  • Le fichier web.xml est utilisé pour configurer l'application web. Ainsi pour accéder à l'application vous devrez utiliser le contexte suivant : /booktrainrestwebservice. Compléter le fichier à partir de la configuration donnée ci-dessous.
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
...
<web-app>
    <display-name>BookTrainRestWebServiceExercice4</display-name>
    <servlet>
        <servlet-name>MyApplication</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>soa.jaxrslabs.booktrainrestwebserviceexcercice4</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyApplication</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>
  • Depuis Eclipse, exécuter la configuration d'exécution appelée generate War (clean and package).
  • Copier le fichier target/booktrainrestwebservice.war dans le répertoire webapp de Tomcat. En considérant que vous avez installé Tomcat 7, le chemin complet sous Linux (basé sur Debian) est celui-ci /var/lib/tomcat7/webapps.
  • Démarrer le service Tomcat service tomcat7 start.
  • Contrôler les logs Tomcat pour s'assurer qu'aucune exception ne s'est produite (/var/log/tomcat7). Si vous rencontrez un problème « Unsupported major.minor version 52.0 », la version de Java utilisée par Tomcat est plus basse que celle utilisée pour la compilation de vos classes. Solution 1 : modifier le JAVA_HOME depuis le fichier /etc/default/tomcat7 pour donner une JVM de niveau égale ou supérieure à celle utilisée pour la compilation. Solution 2 : compiler vos classes en spécifiant un numéro de JVM égal ou inférieur.
  • Afficher le WADL via cette URL : http://localhost:8080/booktrainrestwebservice/rest/application.wadl

VI. Conclusion et remerciements

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2016 Mickael Baron. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.