IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Studio Java Discussion :

Problème Android studio / org.apache.xerces / web service / Tomcat 9


Sujet :

Android Studio Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 66
    Par défaut Problème Android studio / org.apache.xerces / web service / Tomcat 9
    Bonjour à tous

    Je suis en train de créer une application sur Android qui se connecte à un web service JSON / REST sur un serveur Tomcat 9. J'utilise JEE8.
    Le service web qui est sur le serveur Tomcat 9 va ensuite mettre à jour des lignes dans des tables d'une base de données d'un serveur MySQL 5.7.
    Tout est en local sur ma machine de développement.

    J'ai tout d'abord codé le service web qui communique avec la base de données sous Eclipse Oxygen sous forme d'un 'Dynamic Web Project'.
    Après avoir inclut les jars nécessaire dans la librairie du WEB-INF, j'ai testé et tout se passe bien : le service web est accessible et met à jour la base de données.

    Ensuite, il m'a fallut créer l'application Android. J'ai donc créé un projet Android Studio 3.0.1.
    Pour plus de sûreté, j'ai inclus comme librairies tous les jars que j'avais dans le répertoire "lib" du dossier "WEB-INF" de mon service web de manière à ne pas avoir de "classNotFound" ...
    Les librairies qui commencent par une majuscules sont les miennes dont j'ai besoin pour assurer le fonctionnel de l'appli.

    Nom : JARS.png
Affichages : 432
Taille : 17,8 Ko

    Désormais lorsque je lance mon appli et que je teste un appel à mon web service sous Apache 9, j'ai une exception qui se produit :

    E/AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl" on path: DexPathList[[....
    Nom : NOT_FOUND.png
Affichages : 469
Taille : 107,7 Ko

    J'ai été étonné car je n'avais pas besoin de ce Xercès lorsque je faisais mes tests sous Eclipse ...
    J’imaginais naïvement qu'il me fallait importer une librairie de plus dans mon dossier "lib" : j'ai donc ajouté xercesImpl-2.0.0.jar.

    Nom : XERCES.png
Affichages : 412
Taille : 19,4 Ko

    Seulement, en compilant mon projet et bien avant de lancer l’exécution j'obtiens une erreur :

    Nom : GRADDLE.png
Affichages : 410
Taille : 41,3 Ko

    Je suis donc bloqué : si je ne met pas le jar Xerces ça plante parce qu'il n'est pas là, si je met le jar Xerces ça plante parce qu'il ne peut pas compiler ...
    J'ai tenté d'ajouter la ligne multiDexEnabled true dans le fichier graddle mais sans succès ...

    Là j'avoue que je suis coincé et je suis loin d'être un expert en Android ...

    Quelqu’un a t il fait face à ce problème et a trouvé une solution ?

    Merci de votre aide.

  2. #2
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Le but c'est quoi ?

    1- consommer un webservice depuis ton appli android ?
    ou
    2- avoir un serveur web sur ton appli qui expose un webservice ?

    Si la réponse est 1 , tu peux supprimer toutes tes lib , elle ne servent à rien. Il suffit d'utiliser HttpURLConnection (out tout autre client http) pour faire des requêtes sur ton webservice.
    Si la réponse est 2 , je doute que l'ensemble de tes lib soient compatible android , puisque toute l'api java n'est pas disponible.
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 66
    Par défaut
    Bonjour,

    Merci de votre aide : j'avais peur d'être tout seul dans le noir

    Tout d'abord, l'appli sur Android doit en fait consommer des méthodes d'un classe montée en service qui est située sur un serveur Tomcat 9.
    Pour l'instant ce serveur web est sur la même machine que mon émulateur Android d'où je fais les tests.
    Cependant, c'est plus que simplement consommer un service, c'est aussi récupérer des objets à travers une déserialisation JSON.

    Je m'explique.

    Par exemple, j'ai une méthode de ma classe de service qui sert à l'enregistrement de nouveaux profils. Mon application Android doit transmettre au service des paramètres (par exemple nom et prénom) et en échange, le service lui envoi une instance d'un classe (par exemple Profil). C'est pour cela que j'avais imaginé que je pourrais avoir besoin de Jersey/Jackson coté client pour assurer la déserialisation et obtenit mon objet (que j'exploite ensuite dans l'appli Android).

    Je sais pas si HttpURLConnection pourrait faire cela. J'avoue que je suis novice en Android

    Merci de votre aide.

  4. #4
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Citation Envoyé par XAMLdev Voir le message
    Cependant, c'est plus que simplement consommer un service, c'est aussi récupérer des objets à travers une déserialisation JSON.
    Non c'est exactement consommer un webservice .

    - Tu fais une requête HTTP via un client HTTP (par défaut HttpURLConnection est disponible , mais tu peux en installer un autre si ca te chante)
    - Cette requête te retourne un JSON qu'il faut ensuite parser.
    => Tu peux faire ca manuellement avec les classes dédiées à la manipulation json
    => Ou via un parser comme , gson, jackson, etc ...

    Donc très clairement tout tes jars ne servent strictement à rien.

    De plus quand c'est possible , on ajoute les dépendance via le fichier gradle et non directement des jar.
    Pour jackson ca va ressembler a quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    implementation 'com.fasterxml.jackson.core:jackson-core:2.9.4'
    implementation 'com.fasterxml.jackson.core:jackson-annotations:2.9.4'
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.4'
    Tu peux également utiliser retrofit qui est une lib qui gère la communication avec les webservice de bout en bout.
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 66
    Par défaut
    Bonjour,

    J'ai suivit vos conseils : j'ai utilisé les objets de HttpURLConnection qui sont disponibles dans le package java.net.

    J'ai utilisé les trois packages de Jackson (bind, code et annotations).

    Pour ceux qui suivent cette conversation ils sont ici : https://github.com/FasterXML/jackson.

    Je teste tout d'abord mon code dans Eclipse plus facile à faire tourner qu'Android Studio et l'émulateur.

    J'ai réussit à passer des paramètres simples (des String) au service qui m'a renvoyé des sérialisations JSON d'instances d'objets.

    Grace à l'objet ObjectMapper de Jackson comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     
    ObjectMapper objectMapper =  new ObjectMapper();
     
    MaClasse monInstance = objectMapper.readValue(jsonString, MaClasse.class);
    jsonString est une String obtenue après l’exécution d'une connexion HttpURLConnection.

    J'ai cependant un soucis pour la dernière méthode de mon service plus complexe.

    Comme j'ai changé de technologie, je ne sais pas faire ce qui se faisait avant.

    Je m'explique :

    Avant pour appeler la dernière méthode de mon service, j'utilisais le client Jersey comme suit :

    Dans le code de mon client console Java :

    Comme import :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    import javax.ws.rs.client.Client;
    import javax.ws.rs.client.ClientBuilder;
    import javax.ws.rs.client.Entity;
    import javax.ws.rs.core.Form;
    import javax.ws.rs.core.GenericType;
    import javax.ws.rs.core.MediaType;
    Comme code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    TypeDeMaClasseDeRetour objet =  
    		_client
    		.target("URL de mon service")
    		  .path("Nom de la méthode de mon service")
    		  .queryParam("Nom du paramètre 1", "Valeur du paramètre 1")
    		  .queryParam("Nom du paramètre 2", "Valeur du paramètre 2")
    		  .request(MediaType.APPLICATION_JSON)
    		  .post( Entity.entity(list, MediaType.APPLICATION_JSON), TypeDeMaClasseDeRetour.class);
    Avec list : une classe POJO de type MaListe contenant une liste d'objets et quelques propriétés ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    public class MaListe 
    {
    	private List<MonType> _list;
     
    	.....
    }
    Dans le code de mon service :

    La méthode appellée par le code précedent etait comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    	@SuppressWarnings("finally")
    	@POST
    	@Path("/add")
    	@Produces(MediaType.APPLICATION_JSON)
    	@Consumes(MediaType.APPLICATION_JSON)	
    	public TypeDeMaClasseDeRetour add (MaListe list, @QueryParam("Nom du paramètre 1")  String param1, @QueryParam("Nom du paramètre 2") String param2)
    	{	
    		.....	  
     
    	}
    Ça fonctionnait bien sous Eclipse /Java.

    Désormais ça fonctionne plus du tout.

    J'utilise un code trouvé sur stackOverflow pour HttpURLConnection (parce que je connaissais pas) ici : https://stackoverflow.com/questions/...ver-in-android

    En gros, le code construit un chaîne avec les paramètres (clé / valeur) comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    _parametersBuffer.setLength(0);
     
    int i = 0;
     
    for (String key : params.keySet()) 
    {
    	try 
    	{
    		if (i != 0)
    		{
    			_parametersBuffer.append("&");
    		}
     
    		_parametersBuffer.append(key).append("=").append(URLEncoder.encode(params.get(key), CHARSET));
     
    	} 
    	catch (UnsupportedEncodingException e) 
    	{
    		e.printStackTrace();
    	}
     
    	i++;
    }
    On obtient des String du genre mail=max%40max.com&nickname=Max

    Puis fait un POST comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
     try 
     {
    	 _urlObj = new URL(url);
     
    	 _connection = (HttpURLConnection) _urlObj.openConnection();
    	 _connection.setDoOutput(true);
    	 _connection.setRequestMethod("POST");
    	 _connection.setRequestProperty("Accept-Charset", CHARSET);
    	 _connection.setReadTimeout(READ_TIME_OUT);
    	 _connection.setConnectTimeout(CONNECTION_TIME_OUT);
    	 _connection.connect();
     
    	 _wr = new DataOutputStream(_connection.getOutputStream());
    	 _wr.writeBytes(_parametersBuffer != null ?_parametersBuffer.toString(): null);
     
    	 _wr.flush();
    	 _wr.close();
     
     } 
     catch (IOException e) 
     {
    	 e.printStackTrace();
     }
    D'abord dans la déclaration de mon service, je n'ai pas nommé le paramètre liste de type MaListe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @SuppressWarnings("finally")
    @POST
    @Path("/add")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)	
    public TypeDeMaClasseDeRetour add (MaListe list, @QueryParam("Nom du paramètre 1")  String param1, @QueryParam("Nom du paramètre 2") String param2)
    {	
    	.....	  
    	
    }
    Les annotations sont soit @QueryParam("Nom du paramètre") ou @FormParam("Nom du paramètre"), je ne sais pas quoi prendre puisque je n'en avais pas besoin avant.

    Ensuite, quand j'appelle mon service j'obtiens une belle exception (que mon paramètre soit nommé, ou pas) :

    java.io.IOException: Server returned HTTP response code: 415 for URL: http://localhost:8080/WebServices/Service/add

    En fait, le code passe la sérialisation JSON de ma liste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    String jsonList = objectMapper.writeValueAsString(maListe);
    qui ressemble à ça :

    {"_list":[{"_t":"Bouillon","_u":"Fr"},{"_t":"Potage","_u":"Fr"},{"_t":"Marmite","_u":"Fr"},{"_t":"Soupe","_u":"Fr"}],"last":{"_t":"Soupe","_u":"Fr"}}
    dans une chaîne plus vaste de tous les paramètres qui ressemble à ça :
    mail=max%40max.com&nickname=Max&list=%7B%22_list%22%3A%5B%7B%22_t%22%3A%22Bouillon%22%2C%22_u%22%3A%22Fr%22%7D%2C%7B%22_t%22%3A%22Potage%22%2C%22_u%22%3A%22Fr%22%7D%2C%7B%22_t%22%3A%22Marmite%22%2C%22_u%22%3A%22Fr%22%7D%2C%7B%22_t%22%3A%22Soupe%22%2C%22_u%22%3A%22Fr%22%7D%5D%2C%22last%22%3A%7B%22_t%22%3A%22Soupe%22%2C%22_u%22%3A%22Fr%22%7D%7D
    et je pense que c'est pas bon du tout .... mais je ne sais pas comment corriger.

    J'ai besoin d'une aspirine, je suis pas loin d'y arriver avec un coup de pouce

    Merci de votre aide

  6. #6
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Va falloir te forcer à passer aux outils Android. C'est pas parce que tu vas tester un truc sous eclipse en desktop que ca va fonctionner sous Android.

    J'ai le sentiment que tu as mis en place un webservice sans vraiment comprendre ce que tu fais et/ou maitriser les notions de base sous jacentes (http, de/serialisation json, etc ...) du coup tu es perdu quand il sagit de consommer ce ws.

    Je connais pas Jackson , donc je pourrais pas t'aider de ce coté là.

    L'url que tu décrit à la fin de ton message c'est juste le json qui est urlencodé , c'est donc normal.
    Mais peut être que ton webservice n'attends pas le json dans des queryparam , peut être qu'il doit être dans le corps de la requête.
    Tu es le seul à savoir ce qu'attends ton ws.

    Si tu as le json , que tu es capable de construire une requete et de l'envoyer , tu as fait le plus dur.

    Il faut juste savoir :
    - La méthode de la requête (POST,GET,PUT, etc ...)
    - Les éventuels paramètres et comment les envoyer (dans l'url, ou le corps)
    - Les eventuels headers nécessaire (si le ws attends du json y'a des chances qu'il faille ajouter quelque chose comme conn.setRequestProperty("Content-Type","application/json"); )
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 66
    Par défaut
    Va falloir te forcer à passer aux outils Android. C'est pas parce que tu vas tester un truc sous eclipse en desktop que ca va fonctionner sous Android.

    J'ai le sentiment que tu as mis en place un webservice sans vraiment comprendre ce que tu fais et/ou maitriser les notions de base sous jacentes (http, de/serialisation json, etc ...) du coup tu es perdu quand il sagit de consommer ce ws.
    Je suis pas développeur web : je suis back end. J'ai fais très peu de web, il y a un moment et c'était en ASP.Net (tout y est automatisé), on se prend pas la tête comme ça.

    On utilisait un outil en WYSIWYG pour détecter le service web à l'aide de son URL depuis Visual Studio et ensuite le wizard enclenche toute la mécanique de découverte avec la création des classes proxy et la configuration en 3 secondes ...

    Il y a en plan une application desktop qui fera du back office ... donc j'ai intérêt a avoir du code ambivalent (qui marche sous Eclipse et Android Studio)

    Je connais pas Jackson , donc je pourrais pas t'aider de ce coté là.
    J'utilise juste un objet qui fais la conversion POJO => JSON et vice versa c'est tout http://www.baeldung.com/jackson-object-mapper-tutorial.


    Il faut juste savoir :
    - La méthode de la requête (POST,GET,PUT, etc ...)
    - Les éventuels paramètres et comment les envoyer (dans l'url, ou le corps)
    - Les eventuels headers nécessaire (si le ws attends du json y'a des chances qu'il faille ajouter quelque chose comme conn.setRequestProperty("Content-Type","application/json"); )
    Ce que j'essais de faire c'est de poster mes données en JSON vers le service web.
    J'ai nommé mes paramètres, la chaine résultante est du JSON valide.
    J'ouvre ma connection, je la paramètre correctement, j'inscris ma requête dans la corps.
    Je transmet à un service web qui attent des paramètres en JSON, sous fome POST.

    Voici le code que j'utilise (désormais en suivant vos conseils), j'ai tout mis en dur comme un sagouin ! :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
     
     
    private static void makePost()
    	{
    		static final String CHARSET = "UTF-8";
    		static final int READ_TIME_OUT = 10000;
    		static final int CONNECTION_TIME_OUT =15000;
     
    		String url = "http://localhost:8080/WebServices/Texte/GameService/addRelations";
     
    		Tuple<String,String> languageTerm = new Tuple<>("Tomate", "Fr");
    		List<Tuple<String, String>> languageTerms = new ArrayList<>();
     
    		languageTerms.add(new Tuple<>("Jus", "Fr"));
    		languageTerms.add(new Tuple<>("Purée", "Fr"));
    		languageTerms.add(new Tuple<>("Bolognaise", "Fr"));
     
    		String nickname = "Max";
    		String mail = "max@max.com";
     
    		HttpURLConnection connection = null;
     
    		 try 
             {
    			JSONObject jsonObject = new JSONObject();
    			ObjectMapper objectMapper = new ObjectMapper();
     
    			jsonObject.put("languageTerm", objectMapper.writeValueAsString(languageTerm));
    			jsonObject.put("languageTerms", objectMapper.writeValueAsString(languageTerms));
    			jsonObject.put("nickname", nickname);
    			jsonObject.put("mail", mail);
     
    			JSONArray jsonArray = new JSONArray();			
     
    			jsonArray.put(jsonObject);
     
    			String data = jsonObject.toString();
     
    			System.out.println("JSON data :");
    			System.out.println(data);
     
    			URL  urlObj = new URL(url);
     
    			connection = (HttpURLConnection) urlObj.openConnection();
    			connection.setRequestMethod("POST");                                 // Je poste 
    			connection.setRequestProperty("Content-Type","application/json");    // du JSON
                connection.setRequestProperty("Accept", "application/json");         // et attend du JSON  
                connection.setAllowUserInteraction(false);
                connection.setReadTimeout(READ_TIME_OUT);
                connection.setConnectTimeout(CONNECTION_TIME_OUT);
                connection.setRequestProperty("Content-length", data.getBytes().length + "");
                connection.setDoInput(true);
                connection.setDoOutput(true);
                connection.setUseCaches(false);
     
                connection.setRequestProperty("Accept-Charset", CHARSET);
                connection.setRequestProperty("user-agent","Agent/1");
     
                OutputStream outputStream = connection.getOutputStream();
                outputStream.write(data.getBytes("UTF-8"));
                outputStream.close();
     
                connection.connect();
     
                 int statusCode = connection.getResponseCode();
     
                 System.out.println("statusCode : " +  statusCode);
     
                 switch (statusCode) 
                 {             
    	             case 200:
    	             case 201:
     
    	            	StringBuilder _result = null;
     
    	 			    InputStream in = new BufferedInputStream(connection.getInputStream());
    	 			    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
     
    	 			    _result = new StringBuilder();
     
    	 			    String line;
     
    	 			    while ((line = reader.readLine()) != null) 
    	 			    {
    	 			        _result.append(line);
    	 			    }
     
    	 			    System.out.println("Response ! : " + _result.toString());
     
    	                return;                 
                 }
             } 
    		 catch (MalformedURLException ex) 
    		 {
    			 System.out.println( "Error in http connection" + ex.toString());
    		 } 
    		 catch (IOException ex) 
    		 {
    			 System.out.println( "Error in http connection" + ex.toString());
    		 } 
    		 catch (Exception ex) 
    		 {
    			 System.out.println("Error in http connection" + ex.toString());
    		 } 
    		 finally 
    		 {
    		        if (connection != null) 
    		        {
    		            try 
    		            {
    		                connection.disconnect();
    		            } 
    		            catch (Exception ex) 
    		            {
    		            	System.out.println("Error in http connection" + ex.toString());
    		            }
    		        }
    		 } 
    	}

    Disons que j'ai un service qui est une classe Java qui se nomme "GameService".
    Ce service est repére dans le réseau par son nom qui est "GameService"

    Une des méthodes de cette classe se nomme "addRelations".
    Elle est répérée sur le web par som nom qui est aussi "addRelations".
    La méthode addRelations est configurée pour recevoir et produire des données JSON.
    Elle fonctionne en mode POST.

    La méthode addRelations prend quatre paramètres :

    - le paramètre languageTerm nommé "languageTerm" de type Tuple<String,String> annoté @FormParam
    - le paramètre languageTerms nommé "languageTerms" de type List<Tuple<String, String>> annoté @FormParam
    - le paramètre nickname nommé "nickname" de type String annoté @FormParam
    - le paramètre mail nommé "mail" de type String annoté @FormParam

    La méthode addRelations renvoie une instance de type Summary.

    Le service tourne sur Tomcat 9.

    Voilà à quoi il ressemble :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
     
    @Path("/GameService")
     
    public class GameService 
    {
    	@SuppressWarnings("finally")
    	@POST
    	@Path("/addRelations")
    	@Produces(MediaType.APPLICATION_JSON)
    	@Consumes(MediaType.APPLICATION_JSON)	
    	public Summary addRelations (
    			@FormParam("languageTerm") Tuple<String,String> languageTerm, 
    			@FormParam("languageTerms") List<Tuple<String, String>> languageTerms, 
    			@FormParam("nickname")  String nickname, 
    			@FormParam("mail") String mail)
    	{	
    		System.out.println("coucou"); // pour voir si ya un truc ...
    		.....
    	}	
    }
    Le type Tuple est comme suit (j’explicite pas le type Summary parce que c'est pas la peine) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
     
    public class Tuple<T, U> 
    {
    	//Fields
     
    	private  T _t;
    	private  U _u;
     
    	//Properties
     
    	public T get_t()
    	{
    		return _t;
    	}
     
    	public void set_t(T t) {
    		_t = t;
    	}
     
    	public U get_u()
    	{
    		return _u;
    	}
     
    	public void set_u(U u) {
    		_u = u;
    	}
     
    	//Ctors
     
    	public Tuple()
    	{
    	  _t = null;
    	  _u = null;
    	}
     
    	public Tuple(T t, U u)
    	{
    		_t = t;
    	    _u = u;
    	}
    }
    A un moment donné je dumpe la valeur de la serializtion en JSON de mes paramètres avant de l'écrire dans le corps de la requête (ligne 40 du code de la méthode makePost) :

    {"languageTerm":"{\"_t\":\"Tomate\",\"_u\":\"Fr\"}","languageTerms":"[{\"_t\":\"Jus\",\"_u\":\"Fr\"},{\"_t\":\"Purée\",\"_u\":\"Fr\"},{\"_t\":\"Bolognaise\",\"_u\":\"Fr\"}]","mail":"max@max.com","nickname":"Max"}
    Ce qui donne après validation (outil en ligne) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    {
    	"languageTerm": "{\"_t\":\"Tomate\",\"_u\":\"Fr\"}",
    	"languageTerms": "[{\"_t\":\"Jus\",\"_u\":\"Fr\"},{\"_t\":\"Purée\",\"_u\":\"Fr\"},{\"_t\":\"Bolognaise\",\"_u\":\"Fr\"}]",
    	"mail": "max@max.com",
    	"nickname": "Max"
    }
    Le JSON est donc correct avant écriture dans le corps de la requête ...

    Or lorque j'appelle la méthode makePost() dans un main sous Eclipse, la console Apache me dit :

    SEVERE: Servlet.service() for servlet [GameOfTermsRestWebService] in context with path [/WebServices] threw exception [java.lang.IllegalStateException: The @FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded] with root cause
    java.lang.IllegalStateException: The @FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded.
    Là ... je comprend pas ...
    Si l'annotaion @FormParam ne marche qu'avec du "application/x-www-form-urlencoded" et donc pas du "application/json".
    Cela veut dire que je ne peut pas utiliser JSON avec POST dans le corps puisque la seule annotation restante disponible pour nommer mes paramètres dans le service (afin qu'ils soient reconnus) est @QueryParam. Or @QueryParam ne marche qu'avec une query string et donc pas dans le corps.



    Si je m'amuse à faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    data = URLEncoder.encode(data, CHARSET);
    Ce qui donne :

    %7B%22languageTerm%22%3A%22%7B%5C%22_t%5C%22%3A%5C%22Tomate%5C%22%2C%5C%22_u%5C%22%3A%5C%22Fr%5C%22%7D%22%2C%22languageTerms%22%3A%22%5B%7B%5C%22_t%5C%22%3A%5C%22Jus%5C%22%2C%5C%22_u%5C%22%3A%5C%22Fr%5C%22%7D%2C%7B%5C%22_t%5C%22%3A%5C%22Pur%C3%A9e%5C%22%2C%5C%22_u%5C%22%3A%5C%22Fr%5C%22%7D%2C%7B%5C%22_t%5C%22%3A%5C%22Bolognaise%5C%22%2C%5C%22_u%5C%22%3A%5C%22Fr%5C%22%7D%5D%22%2C%22mail%22%3A%22max%40max.com%22%2C%22nickname%22%3A%22Max%22%7D
    au lieu de :

    {"languageTerm":"{\"_t\":\"Tomate\",\"_u\":\"Fr\"}","languageTerms":"[{\"_t\":\"Jus\",\"_u\":\"Fr\"},{\"_t\":\"Purée\",\"_u\":\"Fr\"},{\"_t\":\"Bolognaise\",\"_u\":\"Fr\"}]","mail":"max@max.com","nickname":"Max"}
    avant d'injecter data dans le corps de la requête ...

    J'obtiens :

    SEVERE: Servlet.service() for servlet [GameOfTermsRestWebService] in context with path [/WebServices] threw exception [java.lang.IllegalStateException: The @FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded] with root cause
    java.lang.IllegalStateException: The @FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded
    Là je sais pas ....

    Merci de votre aide.

  8. #8
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Je suis pas développeur web : je suis back end
    Les webservice c'est pas réservé au développeur web , mais passons

    Il y a en plan une application desktop qui fera du back office ... donc j'ai intérêt a avoir du code ambivalent (qui marche sous Eclipse et Android Studio)
    C'est possible , mais pas garantit, puisque l'API java Android n'est pas tout à fait la même que la version desktop/server.

    Or lorque j'appelle la méthode makePost() dans un main sous Eclipse, la console Apache me dit :
    Il te dit que tu n'utilise pas les bon headers dans ta requête.
    il faut donc à minima rajouter à ta requête:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    Voir également ce fil de discussion qui explique comment envoyer à un serveur qui attends ce type de données
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 66
    Par défaut
    Les webservice c'est pas réservé au développeur web , mais passons
    C'est vrai, mais je suis dans la situation de faire les trois acteurs : le producteur, le consommateur et le déployeur.
    Dans ce cas de figure, il faut être développeur web car produire, consommer et déployer un service web implique de bien connaître les protocoles d'échanges de données web et les paramétrages des serveurs web.

    Si j’étais juste le concepteur du service, mon travail serait terminé puisque le service est interrogeable depuis un client java Jersey/Jax-RS.

    A la charge du consommateur de produire son code client pour son interface et consommer mon service web, ici Android.

    A la charge du déployeur de placer le code dans un serveur de production et de paramétrer tout ce qui s'en suit.

    Finalement, c'est bien plus confortable de produire des services web que de les consommer ou de les déployer

Discussions similaires

  1. Problème de connexion entre Android et MySQL via les Web Services
    Par amalmanel dans le forum API standards et tierces
    Réponses: 1
    Dernier message: 22/03/2012, 02h36
  2. Dépendance vers org.apache.xerces.
    Par yann2 dans le forum Akrogen
    Réponses: 2
    Dernier message: 14/06/2007, 10h16
  3. Où trouver le package org.apache.xerces ?
    Par Invité dans le forum Eclipse Java
    Réponses: 4
    Dernier message: 28/12/2006, 19h01
  4. Réponses: 2
    Dernier message: 21/09/2006, 17h05
  5. [SAX] Utilisation du package contenant org.apache.xerces.par
    Par Sphost dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 17/01/2005, 11h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo