Partie 1 : Développement d’un service REST simple

1-2. Analyse des classes fournies

Classe testRS.java :

  • @Path("myRS1") : Définit le chemin de base pour cette ressource REST. Toutes les méthodes de cette classe seront accessibles sous /myRS1
  • @GET : Indique que la méthode sayhello() répond aux requêtes HTTP GET
  • La méthode retourne directement une chaîne de caractères comme réponse

Classe MyApplication.java :

  • @ApplicationPath("/partie1") : Définit le chemin de base de l’application REST. C’est le préfixe commun à toutes les ressources
  • getClasses() : Enregistre les classes de ressources REST (ici testRS.class)
  • Cette classe sert de point d’entrée pour l’application JAX-RS

3. URL du service REST

En combinant les annotations :

  • Chemin de l’application : /partie1 (depuis @ApplicationPath)
  • Chemin de la ressource : /myRS1 (depuis @Path)
  • Nom du WAR : myprojectRStest.war
http://localhost:8080/myprojectRStest/partie1/myRS1

4. Compilation des classes

Commande de compilation :

javac -d WEBCONTENT/WEB-INF/classes -cp $JBOSS_LIB/javax/ws/rs/api/main/jboss-jaxrs-api_2.1_spec-2.0.0.Final.jar src/myRSproject/*.java

Les fichiers .class sont générés dans WEBCONTENT/WEB-INF/classes/myRSproject/.

5. Création du fichier WAR

Placement dans le répertoire WEBCONTENT :

cd WEBCONTENT
jar cvf myprojectRStest.war .

Le fichier myprojectRStest.war est créé avec succès.

6-7. Déploiement sur WildFly

Copie du WAR vers le répertoire de déploiement :

cp myprojectRStest.war $JBOSS_HOME/standalone/deployments/

Vérification dans la console d’administration WildFly (http://localhost:9990/console) :

Le service myprojectRStest.war apparaît dans la liste des déploiements avec le statut Enabled.

8. Test depuis un navigateur

Accès à l’URL :

http://localhost:8080/myprojectRStest/partie1/myRS1

Le service REST fonctionne correctement.

9. Test avec wget

Commande :

wget -qO- http://localhost:8080/myprojectRStest/partie1/myRS1

Le service répond également correctement aux requêtes en ligne de commande.

Partie 2 : Développement et test avancés d’un service REST

a. Ajout de la méthode sayhello2

Modification de testRS.java :

package myRSproject;
 
import javax.ws.rs.GET;
import javax.ws.rs.Path;
 
@Path("myRS1")
public class testRS {
    
    @GET
    @Path("hello1")
    public String sayhello() {
        return " --- Test restful service : sayHello ---";
    }
    
    @GET
    @Path("hello2")
    public String sayhello2() {
        return " --- Test restful service : sayHello2 ---";
    }
}

Modification de MyApplication.java pour changer le nom du WAR :

@ApplicationPath("/partie2")
public class MyApplication extends Application {
    // ...
}

Explication :

  • @Path("hello1") et @Path("hello2") : Ajoutent des sous-chemins aux méthodes
  • Les URLs complètes deviennent :
    • http://localhost:8080/mytestRS2/partie2/myRS1/hello1/
    • http:/**/localhost:8080/mytestRS2/partie2/myRS1/hello2/

Déploiement : Recompilation, création du WAR mytestRS2.war et déploiement sur WildFly.

Tests :

wget -qO- http://localhost:8080/mytestRS2/partie2/myRS1/hello1/
 --- Test restful service : sayHello ---
 
wget -qO- http://localhost:8080/mytestRS2/partie2/myRS1/hello2/
 --- Test restful service : sayHello2 ---

Les deux méthodes sont accessibles sur leurs URLs respectives.

b. Paramètre dans l’URL avec @PathParam

Modification de testRS.java :

package myRSproject;
 
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
 
@Path("myRS1")
public class testRS {
    
    @GET
    @Path("hello1/{nom}")
    public String sayhello(@PathParam("nom") String nom) {
        return " --- Test restful service : Bonjour " + nom;
    }
    
    @GET
    @Path("hello2")
    public String sayhello2() {
        return " --- Test restful service : sayHello2 ---";
    }
}
  • @Path("hello1/{nom}") : Définit un paramètre dynamique dans l’URL
  • @PathParam("nom") : Injecte la valeur capturée dans le paramètre de la méthode
  • L’URL http://localhost:8080/mytestRS3/partie1/myRS1/hello1/Dupont extrait “Dupont” comme valeur de {nom}

Test :

wget -qO- http://localhost:8080/mytestRS3/partie1/myRS1/hello1/Dupont
 --- Test restful service : Bonjour Dupont

Le paramètre est correctement extrait et utilisé.

c. Paramètres de requête avec @QueryParam

Modification de testRS.java :

package myRSproject;
 
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
 
@Path("myRS1")
public class testRS {
    
    @GET
    @Path("hello1/{nom}")
    public String sayhello(@PathParam("nom") String nom,
                          @QueryParam("prenom") String prenom,
                          @QueryParam("ville") String ville) {
        return " --- Test restful service : Bonjour " + nom + " " + prenom + " de " + ville;
    }
    
    @GET
    @Path("hello2")
    public String sayhello2() {
        return " --- Test restful service : sayHello2 ---";
    }
}
  • @QueryParam("prenom") : Extrait le paramètre prenom de la query string
  • @QueryParam("ville") : Extrait le paramètre ville de la query string
  • Les paramètres de requête sont séparés par ? et & dans l’URL

Test :

wget -qO- "http://localhost:8080/mytestRS3/partie1/myRS1/hello1/Dupont?prenom=Bob&ville=Paris"
 --- Test restful service : Bonjour Dupont Bob de Paris

Les paramètres sont correctement extraits de la query string.

d. Méthode POST

Modification de testRS.java :

package myRSproject;
 
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;
 
@Path("myRS1")
public class testRS {
    
    @GET
    @Path("hello1/{nom}")
    public String sayhello(@PathParam("nom") String nom,
                          @QueryParam("prenom") String prenom,
                          @QueryParam("ville") String ville) {
        return " --- Test restful service : Bonjour " + nom + " " + prenom + " de " + ville;
    }
    
    @POST
    @Path("hello2")
    public String sayhello2() {
        return " --- Test restful service : sayHello2 POST ---";
    }
}
  • @POST : La méthode sayhello2() répond maintenant aux requêtes HTTP POST au lieu de GET

Après recompilation et redéploiement, la méthode n’est plus accessible via GET mais uniquement via POST.

e. Test avec SOAP UI

Création d’un nouveau projet REST dans SOAP UI :

http://localhost:8080/mytestRS3/partie1/myRS1/hello2
  • Méthode : POST
  • URL : http://localhost:8080/mytestRS3/partie1/myRS1/hello2
  • Pas de body nécessaire
 --- Test restful service : sayHello2 POST ---

f. Négociation de contenu avec @Produces

Modification complète de testRS.java :

package myRSproject;
 
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.Produces;
 
@Path("myRS1")
public class testRS {
    
    @GET
    @Path("hello1/{nom}")
    @Produces("text/html")
    public String sayhello1(@PathParam("nom") String nom,
                           @QueryParam("prenom") String prenom,
                           @QueryParam("ville") String ville) {
        return "<html><body><h1>--- Test GET - HTML : Bonjour " + nom + " " + prenom + " de " + ville + "</h1></body></html>";
    }
    
    @GET
    @Path("hello1/{nom}")
    @Produces("text/plain")
    public String sayhello2(@PathParam("nom") String nom,
                           @QueryParam("prenom") String prenom,
                           @QueryParam("ville") String ville) {
        return "--- Test GET - PLAIN Text : Bonjour " + nom + " " + prenom + " de " + ville;
    }
    
    @POST
    @Path("hello1/{nom}")
    @Produces("text/html")
    public String sayhello3(@PathParam("nom") String nom,
                           @QueryParam("prenom") String prenom,
                           @QueryParam("ville") String ville) {
        return "<html><body><h1>--- Test POST - HTML : Bonjour " + nom + " " + prenom + " de " + ville + "</h1></body></html>";
    }
    
    @POST
    @Path("hello1/{nom}")
    @Produces("text/plain")
    public String sayhello4(@PathParam("nom") String nom,
                           @QueryParam("prenom") String prenom,
                           @QueryParam("ville") String ville) {
        return "--- Test POST - PLAIN Text : Bonjour " + nom + " " + prenom + " de " + ville;
    }
}

Explication :

  • @Produces("text/html") : La méthode produit du contenu HTML
  • @Produces("text/plain") : La méthode produit du texte brut
  • JAX-RS effectue la négociation de contenu : il sélectionne automatiquement la méthode appropriée selon l’en-tête HTTP Accept de la requête

Tests avec curl :

Test GET avec Accept: text/plain :

curl -H "Accept: text/plain" "http://localhost:8080/mytestRS3/partie1/myRS1/hello1/Martin?prenom=Alice&ville=Lyon"
--- Test GET - PLAIN Text : Bonjour Martin Alice de Lyon

Test GET avec Accept: text/html :

curl -H "Accept: text/html" "http://localhost:8080/mytestRS3/partie1/myRS1/hello1/Martin?prenom=Alice&ville=Lyon"
<html><body><h1>--- Test GET - HTML : Bonjour Martin Alice de Lyon</h1></body></html>

Test POST avec Accept: text/plain :

curl -X POST -H "Accept: text/plain" "http://localhost:8080/mytestRS3/partie1/myRS1/hello1/Martin?prenom=Alice&ville=Lyon"
--- Test POST - PLAIN Text : Bonjour Martin Alice de Lyon

Test POST avec Accept: text/html :

curl -X POST -H "Accept: text/html" "http://localhost:8080/mytestRS3/partie1/myRS1/hello1/Martin?prenom=Alice&ville=Lyon"
<html><body><h1>--- Test POST - HTML : Bonjour Martin Alice de Lyon</h1></body></html>

La négociation de contenu fonctionne parfaitement ! JAX-RS sélectionne automatiquement la bonne méthode selon la méthode HTTP (GET/POST) et le type de contenu demandé (text/plain ou text/html).

Partie 3 : Développement d’un client Java REST

4-5. Analyse du client testCL.java

package myclient;
 
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.*;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
 
public class testCL {
    
    public static void main(String[] args){
        System.out.println("START MAIN ===================== ");
        
        // Création du client JAX-RS
        Client cl = ClientBuilder.newBuilder().build();
        
        // Appel du service REST
        String res = cl.target("http://127.0.0.1:8080/mytestRS3/partie1/myRS1/hello1/Bob?prenom=toto&ville=aubiere")
                       .request(MediaType.TEXT_PLAIN)
                       .get(String.class);
        
        System.out.println(" Result: " + res);
        
        // Fermeture du client
        cl.close();
    }
}

Explication du code :

  • ClientBuilder.newBuilder().build() : Crée une instance de client JAX-RS
  • cl.target(url) : Définit l’URL cible du service REST
  • .request(MediaType.TEXT_PLAIN) : Spécifie qu’on accepte du texte brut (en-tête Accept)
  • .get(String.class) : Effectue une requête GET et récupère la réponse comme String
  • cl.close() : Libère les ressources du client

6. Compilation et exécution

Compilation :

javac -d . -cp lib/jaxrs-ri/lib/*:lib/jaxrs-ri/ext/*:lib/jaxrs-ri/api/*:. ../src/myclient/*.java

Exécution :

java -cp .:lib/jaxrs-ri/lib/*:lib/jaxrs-ri/ext/*:lib/jaxrs-ri/api/*:lib/javax.activation-api-1.2.0.jar myclient/testCL

Résultat :

START MAIN ===================== 
 Result: --- Test GET - PLAIN Text : Bonjour Bob toto de aubiere

Le client Java invoque avec succès le service REST

7. Extension du client pour tester les 4 méthodes

testCLComplete.java :

package myclient;
 
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
 
public class testCLComplete {
    
    public static void main(String[] args){
        System.out.println("========== TEST CLIENT REST ==========\n");
        
        Client cl = ClientBuilder.newBuilder().build();
        String baseUrl = "http://127.0.0.1:8080/mytestRS3/partie1/myRS1/hello1/Durand?prenom=Sophie&ville=Toulouse";
        
        // Test 1 : GET avec text/html
        System.out.println("--- Test 1 : GET avec Accept: text/html ---");
        String res1 = cl.target(baseUrl)
                        .request(MediaType.TEXT_HTML)
                        .get(String.class);
        System.out.println("Résultat : " + res1 + "\n");
        
        // Test 2 : GET avec text/plain
        System.out.println("--- Test 2 : GET avec Accept: text/plain ---");
        String res2 = cl.target(baseUrl)
                        .request(MediaType.TEXT_PLAIN)
                        .get(String.class);
        System.out.println("Résultat : " + res2 + "\n");
        
        // Test 3 : POST avec text/html
        System.out.println("--- Test 3 : POST avec Accept: text/html ---");
        Response response3 = cl.target(baseUrl)
                               .request(MediaType.TEXT_HTML)
                               .post(Entity.text(""));
        String res3 = response3.readEntity(String.class);
        System.out.println("Résultat : " + res3 + "\n");
        
        // Test 4 : POST avec text/plain
        System.out.println("--- Test 4 : POST avec Accept: text/plain ---");
        Response response4 = cl.target(baseUrl)
                               .request(MediaType.TEXT_PLAIN)
                               .post(Entity.text(""));
        String res4 = response4.readEntity(String.class);
        System.out.println("Résultat : " + res4 + "\n");
        
        cl.close();
        System.out.println("========== FIN DES TESTS ==========");
    }
}

8. Compilation et test du client complet

Compilation :

javac -d . -cp lib/jaxrs-ri/lib/*:lib/jaxrs-ri/ext/*:lib/jaxrs-ri/api/*:. ../src/myclient/*.java

Exécution :

java -cp .:lib/jaxrs-ri/lib/*:lib/jaxrs-ri/ext/*:lib/jaxrs-ri/api/*:lib/javax.activation-api-1.2.0.jar myclient/testCLComplete

Résultat :

========== TEST CLIENT REST ==========

--- Test 1 : GET avec Accept: text/html ---
Résultat : <html><body><h1>--- Test GET - HTML : Bonjour Durand Sophie de Toulouse</h1></body></html>

--- Test 2 : GET avec Accept: text/plain ---
Résultat : --- Test GET - PLAIN Text : Bonjour Durand Sophie de Toulouse

--- Test 3 : POST avec Accept: text/html ---
Résultat : <html><body><h1>--- Test POST - HTML : Bonjour Durand Sophie de Toulouse</h1></body></html>

--- Test 4 : POST avec Accept: text/plain ---
Résultat : --- Test POST - PLAIN Text : Bonjour Durand Sophie de Toulouse

========== FIN DES TESTS ==========

Tous les tests passent avec succès. Le client Java peut invoquer les 4 méthodes du service REST en utilisant différentes combinaisons de méthodes HTTP (GET/POST) et de types de contenu (text/html, text/plain).