Client Java REST

Cette partie est la suite de la partie implémentant l’architecture REST dans l’article suivant : REST

Parmi toutes les API Java intégrées dans le JDK, il existe le paquetage java.net pour effectuer des requêtes HTTP standard ; c’est-à-dire sans l’intervention d’une bibliothèque externe.

L’usage des classes de ce paquetage implique la configuration de vos requêtes HTTP de la méthode utilisée et nécessite la conversion manuelle d’un flux de données à une chaîne de caractère.

D’autre part, afin respecter la norme RESTful nous devons implémenter les méthodes PUT et DELETE de façon particulière (cf: code et les commentaires).

Pour résumé, si nous désirons effectuer une requête HTTP vous devez initialiser la requête de la manière suivante :

   public String get(String pMethode) throws IOException, JSONException {   
    String url = URL;
    InputStream is = null;
    String parameters = "";
    if(!pMethode.equals("POST")&&(jsonObj!=null)){
      url+=jsonObj.getInt("id");
    }
    if(jsonObj != null){
      if(pMethode.equals("PUT")) {
        jsonObj.remove("id");
      }
      parameters  = "data="+URLEncoder.encode(jsonObj.toString(), "utf-8");
    }   

    try {
       final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
       conn.setRequestMethod(pMethode);                      
            
       // Pour les methode POST et PUT on envoie les parametre avec l'OutputStreamWriter
       if(pMethode.equals("POST")||pMethode.equals("PUT")){  	
         conn.setDoInput(true);
         conn.setDoOutput(true);
         OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
         out.write(parameters);// here i sent the parameter
         out.close();
       }else{
         conn.setDoInput(true);
         conn.connect();
       }
           
       is = conn.getInputStream();
       // Lit le InputStream et l'enregistre dans une string
       return readIt(is);
    } finally {
       // Pour etre sur que le InputStream soit ferme apres avoir quitter l'application
      if (is != null) {
        is.close();
      }
    }
  }

À la lecture de ce code, cela peut vous sembler pas bien complexe à utiliser mais sachez qu’il s’agit ici du minimum syndical. Dès lors que vous voudrez effectuer des requêtes dans un projet sérieux, il vous faudra réagir à des codes HTTP et traiter son contenu en fonction de ce même code. Chose qui n’est pas traitée dans cet exemple, nous le verrons dans l’article suivant.
Vous remarquez aussi l’usage de la méthode readIt(InputStream) qui permet de lire un InputStream et d’en sauvegarder son contenu dans une String. Cette méthode n’existe pas dans le JDK mais il existe plusieurs façons de mettre en œuvre cette conversion. Voici la mienne :

private String readIt(InputStream is) throws IOException {	
  BufferedReader r = new BufferedReader(new InputStreamReader(is));
  StringBuilder response = new StringBuilder();			
  String line;								
  while ((line = r.readLine()) != null) {				
    response.append(line).append('\n');				
  }										
  return response.toString();						
}

Cette section n’est ici qu’à titre informatif et parce que vous pourriez rencontrer ce genre de code dans d’autres projets puisqu’il s’agit de la version la plus basique possible pour faire les requêtes RESTful.

1. Extraction des données JSON

Rappelez-vous, le serveur applicatif va chercher en base de données une liste de produits et renvoyer le résultat dans un fichier JSON. Il faut donc pouvoir extraire les données de ce fichier et les placer dans une classe pour pouvoir les afficher ou les manipuler dans l’application. Pour y parvenir, nous allons déléguer la responsabilité d’extraire les données à une classe Product. Cela permettra de ne plus se préoccuper de l’extraction des « objets » d’un produit dans le fichier JSON.

Avant cela, nous allons en apprendre plus sur les classes principales, à savoir JSONArray et JSONObject qui font partie la librairie : java-json.jar
Je vous recommande d’ajouter un répertoire « lib » a votre projet et d’inclure cette librairie a vos imports.

Pour extraire un tableau d’un fichier JSON, vous devez utiliser la classe JSONArray qui possède 4 constructeurs :
– public JSONArray () : Création d’un tableau JSON vide.

– public JSONArray (Collection copyFrom) : Création d’un tableau JSON en copiant toutes les valeurs de la collection donnée.

– public JSONArray (JSONTokener readFrom) : Création d’un tableau JSON en copiant toutes les valeurs du tableau contenu dans le tokener.

– public JSONArray (String json) : Création d’un tableau JSON suivant un fichier JSON.

Puisque notre requête HTTP lit un InputStream et sauvegarde son contenu dans une String, le dernier constructeur est celui qui convient le mieux à notre exemple. Concrètement, ce constructeur va créer un JSONArray et va contenir toutes les valeurs, les objets ou les tableaux contenus dans le tableau racine. Notez que si le serveur applicatif avait renvoyé non pas un tableau mais un objet, il aurait fallu utiliser un des constructeurs de JSONObject.

Une fois que vous avez votre tableau JSON, une série de méthodes existe pour en extraire les différentes valeurs. Nous avons déjà vu les différentes valeurs contenues dans un fichier JSON, il existe une méthode d’extraction pour chacun de ces types :

– public boolean getBoolean (int index) : Récupérer une valeur booléenne.
– public double getDouble (int index) : Récupérer un double.

– public int getInt (int index) : Récupérer un entier.

– public long getLong (int index) : Récupérer un long.

– public String getString (int index) : Récupérer une chaine de caractères.

– public JSONArray getJSONArray (int index) : Récupérer un tableau JSON.

– public JSONObject getJSONObject (int index) : Récupérer un objet JSON.

2. Extraire les données

La théorie est terminée, nous allons passer à la pratique. L’exemple étant assez simple, il n’y aura qu’une seule classe qui aura la responsabilité d’extraire un JSONObject et de renseigner les valeurs que contient cet objet dans les attributs de la classe, que nous appellerons une classe nommée Product.

package org.libreapps.rest.obj;

import org.json.JSONObject;

public class Product  {
    private long id;
    private String name;
    private String type;
    private double price;

    public Product(JSONObject jObject) {
        id = jObject.optLong("id");
        name = jObject.optString("name");
        type = jObject.optString("type");
        price = jObject.optDouble("price");
    }
    
    public long getId() { return id; }
    public String getName() { return name; }
    public String getType() { return type; }
    public double getPrice() { return price; }
}

Cependant, avant d’obtenir les objets des produits, il faut itérer sur le tableau JSON qui se trouve à la racine du fichier JSON. Pour ce faire, nous allons récupérer la chaîne de caractères du JSON, nous allons la placer dans un JSONArray et nous allons itérer dessus.

private ArrayList<Product> parse(final String json) {	
  try {								
    ArrayList<Product> listPdt = new ArrayList<Product>();	
    final JSONArray jProductArray = new JSONArray(json);
    for (int i = 0; i < jProductArray.length(); i++) {
      listPdt.add(new Product(jProductArray.optJSONObject(i)));
    }									
    return listPdt;						
  } catch (JSONException e) {					
    e.printStackTrace();
  }									
  return null;							
}

Cette méthode ainsi que les méthodes readIt() et get() sont à mettre dans un « Thread » afin de pouvoir l’exécuter en parallèle de notre Lanceur.java comme dans l’exemple suivant :

public class ConnectionRest extends Thread{
  private String url = "<URL SERVEUR>";
  private String methode;
  private JSONObject jsonObj = null;

  public ConnectionRest(String pMethode){
    super();
    methode = pMethode;
  }
	
  public void run(){
    try {
      if(methode.equals("GET")){ 
        ArrayList<Product> listProduct = parse(get(methode));
        for (int i=0;i < listProduct.size();i++){
          System.out.println(listProduct.get(i).getName()+" "+listProduct.get(i).getType()+" "+listProduct.get(i).getPrice()+"\n");
        }  
      }else {
	get(methode);
      }      
    } catch (IOException | JSONException e) {
      e.printStackTrace();
    }
  }	

  public void setObj(JSONObject obj) {
    this.jsonObj = obj;
  }
}

La suite : JTable REST


    Source :
    https://github.com/stleary/JSON-java/archive/master.zip
    https://zestedesavoir.com/tutoriels/1140/communication-entre-android-et-php-mysql/