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

Services Web Java Discussion :

Consommer un web service très simplement et dynamiquement


Sujet :

Services Web Java

  1. #1
    Membre actif Avatar de Chen norris
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    216
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 216
    Points : 248
    Points
    248
    Par défaut Consommer un web service très simplement et dynamiquement
    Bonjour à tous,

    Avant toute chose, je tiens à m'excuser par avance pour ce que certains qualifieront sans doute de troll (même si le problème que je pose me semble bien réel et concret).
    ___

    En Javascript, lorsque je souhaite appeler un web service, je fais un appel Ajax du genre ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    $.ajax({
    	url: "url de mon web service",
    	data: {
    		param1: valeur1,
    		param2: valeur2,
    		param3: valeur3
    	}),
    	success: function(data) {
    	},
    	type: "post"
    });
    C'est un exemple se basant sur Jquery mais je pourrais très bien en faire un avec un autre framework, ça serait tout aussi simple.

    Maintenant, en Java, lorsque je souhaite appeler un web service, je dois commencer par écrire un nombre incalculable de classes dans un charabia incompréhensible (on a des stubs, des services, des noms qualifiés, des descripteurs d'opérations, des descripteurs de paramètres, des méthodes de sérialisation et de désérialisation, … et j'en passe). Toutes ces notions parlent peut-être aux connaisseurs mais pour des développeurs dont le simple objectif est d'appeler un web service, je ne comprends pas pourquoi une telle complexité (cf le paragraphe précédent sur comment appeler un web service en Javascript). Alors certes, il existe des utilitaires du genre wsdl2java qui permettent de générer tout ce contenu sauf que cela ne m'intéresse absolument pas principalement pour les deux raisons suivantes :
    • Le code généré est juste dégu***asse (excusez-moi du terme),
    • C'est statique.

    C'est ce second point qui me bloque complètement car dans mon cas bien particulier, je dois faire appel à différentes versions d'un même web service de manière dynamique (suivant le cas dans lequel je me trouve, je dois appeler telle ou telle version). La version se situant dans l'URL de mon web service, il est impossible de me baser sur des classes auto-générées qui contiennent en dur l'URL de mon web service. Si à l'avenir une nouvelle version du web service que j'appelle faisait son apparition, je ne veux pas avoir à tout regénérer à la main pour gérer cette n-ième version.

    À court terme, je cherche donc désespérément une manière simple et efficace d'appeler un web service en Java. Je souhaite m'affranchir de toutes ces notions bizarroïdes qu'on retrouve dans le code auto-généré par wsdl2java et me retrouver avec au final quelque chose de simple, un peu comme ce qu'on peut retrouver en Javascript : une URL, des paramètres et une instruction pour appeler le tout. Je m'en suis déjà un peu approché avec la méthode générique suivante :
    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
     
    public Object invoke(String methodName, QName returnType, List<WebServiceParameter> parameters,
    		String soapActionURI) throws ServiceException, MalformedURLException, RemoteException {
    	Service service = new Service();
    	Call call = (Call) service.createCall();
     
    	// Définition des propriétés de l'appel
    	call.setEncodingStyle(null);
    	call.setOperationName(new QName(targetNamespace, methodName));
    	call.setProperty(Call.SEND_TYPE_ATTR, Boolean.FALSE);
    	call.setReturnType(returnType);
    	call.setSOAPActionURI(soapActionURI);
    	call.setSOAPVersion(SOAPConstants.SOAP11_CONSTANTS);
    	call.setTargetEndpointAddress(new URL(endPoint));
    	call.setUseSOAPAction(true);
     
    	// Ajout des paramètres
    	List<Object> methodParameters = new LinkedList<Object>();
    	for (WebServiceParameter p : parameters) {
    		call.addParameter(new QName(targetNamespace, p.name), p.type, ParameterMode.IN);
    		methodParameters.add(p.value);
    	}
     
    	// Appel de la méthode et renvoi du résultat
    	return call.invoke(methodParameters.toArray());
    }
    Ce code fonctionne d'ailleurs pour un web service avec des paramètres simples mais voilà, dès que je me retrouve avec des paramètres de type complexe, je suis de nouveau bloqué (je n'ai plus exactement une simple liste de paramètres mais des paramètres contenant eux-mêmes des paramètres). Savez-vous comment à partir de ce que j'ai déjà développé je peux prendre en compte des paramètres de type complexe et de manière simple ?

    D'une manière plus générale, au fil de mes multiples recherches sur le net, je suis tombé majoritairement sur les tutos/posts/articles/… suivants :
    • comment déployer un web service : 70% des cas mais manque de pot, ce n'est pas ce que je cherche à faire (je remercie au passage les auteurs de tous ces tutos qui sont pour la plupart extrêmement complets et bien expliqués),
    • comment auto-générer des classes avec wsdl2java pour consommer un web service : 25% des cas mais là encore, ce n'est pas une solution viable pour moi,
    • et les 5% restants qui m'intéressent où j'ai clairement l'impression d'être dans une jungle tant les techniques/bidouilles/… peuvent différer d'un cas à l'autre

    Autant il y a maintenant presque 10 ans (si je ne m'abuse), lorsque les web services faisaient tout juste leur apparition dans le monde du Java je pouvais comprendre que ce soit compliqué à mettre en œuvre mais à l'heure actuelle, je ne comprends pas que ce soit toujours aussi complexe. En gros, je cherche à savoir si en Java, il existe enfin une méthode très simple et dynamique pour consommer un web service du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    WebService monWebService = new WebService(url);
    List<WebServiceParameter> parametres = new ArrayList<WebServiceParameter>();
    parametres.addParam(param1);
    parametres.addParam(param2);
    parametres.addParam(param3);
    Object result = monWebService.invoke(method, parametres);
    Savez-vous s'il existe quelque chose permettant de faire les choses très simplement en Java ?

    Encore une fois, les deux questions que je pose restent très ouvertes et je ne sais pas si elles trouveront des réponses. Je vous remercie en tous cas pour votre aide et pour vos conseils sur le sujet.
    Chen norris
    C/C++, C#, Java, PHP & SQL coder
    Web developer

  2. #2
    Membre actif Avatar de Chen norris
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    216
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 216
    Points : 248
    Points
    248
    Par défaut
    Re-bonjour à tous,

    Après plusieurs jours passés à bien m'arracher les cheveux, j'ai travaillé à l'amélioration de ma méthode générique pour en faire une classe qui me mâche un maximum le travail. Mon problème sur les paramètres de type complexe (ie les paramètres qui contiennent des paramètres) était lié à plusieurs problèmes :
    • Lors de l'ajout de paramètre avec Call.addParameter, la casse est automatiquement changée pour que le nom du paramètre soit en camelCase avec une minuscule au début : un paramètre MonParametre ressortait donc sous le nom monParametre.
    • Les namespaces des sous-paramètres disparaissent sans aucune explication.
    • Des attributs xsi:type apparaissent alors que j'ai pourtant bien positionné à false l'option AxisEngine.PROP_SEND_XSI.


    En fouillant sur le net, je me suis rendu compte qu'Axis n'en faisait qu'à sa tête, que je n'étais pas le seul à rencontrer ces soucis. Ne souhaitant pas perdre mon temps à essayer de comprendre comment ce framework fonctionne exactement (pas envie de mettre mon nez dans du code pour essayer d'en comprendre la logique ; à mon sens, cela va même à l'inverse de la philosophie d'un framework), j'ai opté pour une solution un peu plus brute : retravailler manuellement l'enveloppe SOAP. Pour cela, j'ai procédé en trois étapes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 1 - Récupération de mon enveloppe au format String
    String cleanBody = body.toString();
     
    // 2 - Retouches manuelles sur l'enveloppe à l'aide d'expressions régulières
    // Exemple de retrait de tous les attributs xsi:type
    cleanBody = cleanBody.replaceAll("( xsi:type=\")[^\"]*(\")", "");
    // ... et ainsi de suite pour renommer mes paramètres avec la bonne casse, repositionner les bons namespaces, ...
     
    // 3 - Création d'une toute nouvelle enveloppe SOAP à partir de la chaîne de caractères que j'ai retouchée
    SOAPEnvelope envelope = new SOAPEnvelope();
    envelope.addBodyElement(new SOAPBodyElement(new ByteArrayInputStream(cleanBody.getBytes())));
    Lors de la troisième étape, Axis s'amuse (encore) à rajouter quelques namespaces mais mes appels fonctionnent enfin.
    En parallèle, j'ai aussi développé une petite méthode me permettant de lire une balise à partir de son nom. Côté code appelant, on a donc au final quelque chose de très simple qui ressemble à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CommonWebService monWebService = new CommonWebService("nom.du.web.service");
    List<WebServiceParameter> parametres = new ArrayList<WebServiceParameter>();
    parametres.add(new WebServiceParameter("param1", "namespaceParam1", valeurParam1));
    parametres.add(new WebServiceParameter("param2", "namespaceParam2", valeurParam2));
    try {
    	SOAPEnvelope result = monWebService.invoke("methodeAppelee", parametres);
    	String resultat = monWebService.readFromResult("baliseResultat", result);
    }
    catch (Exception e) {
    	logger.error("Erreur lors de l'appel au web service : ", e);
    }
    Bonne chance à tous ceux qui sont et seront amenés à travailler sur un appel de web service en Java en tous cas, en espérant que mon post permettra de les aiguiller vers la piste qui me paraît la plus simple à suivre et à mettre en œuvre. Si d'ailleurs certains ont des questions d'ordre plus technique sur comment j'ai procédé sur un point en particulier, je répondrai avec plaisir via ce sujet

    Merci à tous pour votre lecture, je marque le sujet comme résolu.
    Chen norris
    C/C++, C#, Java, PHP & SQL coder
    Web developer

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 15/04/2008, 15h52
  2. Réponses: 3
    Dernier message: 06/12/2007, 17h35
  3. deployer et consommer un web service
    Par fétémété dans le forum Services Web
    Réponses: 6
    Dernier message: 23/10/2007, 22h41
  4. Réponses: 7
    Dernier message: 17/10/2007, 17h06
  5. Comment consommer un web service en java
    Par Vins83 dans le forum Services Web
    Réponses: 1
    Dernier message: 16/01/2006, 23h33

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