Recherche sur le blog

mardi 20 décembre 2011

[WinDev] Importer un Web Service

WinDev permet non seulement de créer des Web Services (en WLangage), mais aussi d'en importer d'autres, quel que soit le langage dans lequel ils ont été écrits (Java, C#, WLangage...). Le service généré via Axis2 peut recevoir des requêtes par socket, HTTP et même SOAP. C'est grâce au WSDL que WinDev va générer les types et les opérations adéquates. Une fois notre service déployé, la description WSDL est disponible. Dans le cas de "HelloAxisWorld", il se trouve (par défaut) à l'adresse suivante : http://localhost:8080/axis2/services/HelloAxisWorld?wsdl. Comme vous vous en doutez, cette URL peut varier selon la configuration de votre serveur Apache.

Lorsqu'on analyse le contenu, on peut distinguer plusieurs parties :
  • Les types : Axis2 a généré deux sortes de type pour nous. L'un correspond à ce qui sera envoyé au service Web. Il contient toutes les valeurs qui peuvent être des chaînes, des entiers, des tableaux, etc. Ensembles, ils forment un type complexe. Le second type est utilisé pour la réponse. Ils sont indépendants du langage et des machines mais se conforment à la spécification du XML Schema.
  • Les messages : il en existe deux ici - l'un pour la requête, l'autre pour la réponse. Chaque message contient une ou plusieurs parties, qui peuvent être comparées à des paramètres d'appel à une fonction dans un langage plus traditionnel.
  • Les liaisons (bindings) :  elles définissent le format des messages et le protocole utilisé pour un port.
  • Les ports : ils définissent les différentes manières de se connecter au Web Service. Chaque accès à un "endpoint" est défini par une URL.
Maintenant que c'est un peu plus clair pour vous, voyons ensemble comment importer la description dans l'environnement de WinDev.

Importer

Dans le volet "Explorateur de projets", localisez la catégorie "Webservices" puis effectuez un clic droit sur celle-ci. Choisissez alors l'option "Importer et utiliser un Webservice dans ce projet...". Remarque : si ce volet n'existe pas chez vous, rendez-vous dans le menu "Affichage", "Barre d'outils" puis "Volets". Cochez-le, ensuite déplacez-le où vous le souhaitez dans l'environnement.


Une nouvelle fenêtre s'ouvre : la première étape affiche une introduction. Cliquez alors sur le bouton "Suivant" (en forme de flèche). L'éditeur vous demande alors de saisir l'adresse du WSDL, et éventuellement des informations d'authentification (cela dépend de la configuration du serveur). Comme nous travaillons en WinDev 15, nous n'allons pas utiliser le mode de compatibilité. Lorsqu'on est prêt, on peut confirmer en terminant cet assistant. L'éditeur créera les types et les opérations pour nous.


Après un temps d'attente qui dépendra de la taille de votre service mais aussi du temps de réponse du serveur, les types et les opérations sont créés. Ils apparaissent dans la catégorie "Webservices" de l'explorateur de projet. La structure a respecté la description et on retrouve bien deux types complexes : "hello" et "helloResponse", ainsi que l'unique opération (qui renverra une chaîne de caractères).


Utiliser

Il ne nous reste plus qu'à "consommer" ce service. Et pour cela, il va falloir saisir du code...


Il faut tout d'abord déclarer deux "variables". L'une contiendra la réponse, l'autre est utilisée pour passer les paramètres à l'opération. La seconde contient toutes les valeurs à définir. Dans notre cas, nous devons renseigner un nom (name). Ensuite, on exécute l'opération du Web Service et on stocke le résultat dans notre variable RSHelloResp. On affiche le résultat dans une boite de dialogue de type "Information".

Si on veut être plus propre et aller plus loin, on peut rajouter un traitement d'erreur spécifique. Ici, on affichera simplement la cause de l'échec de l'appel dans une boite de dialogue de type "Erreur". Voici l'exemple :


Et après ?

Après, c'est à vous de jouer. Déployez, testez, amusez-vous à explorer les diverses possibilités qu'offrent Java et WinDev. Si vous ne possédez pas ce puissant AGL, vous pouvez toujours créer des clients dans d'autres langages comme le C# (avec Visual Studio). Bon développement à toutes et à tous.

Dossier Axis2

Partie 1.
Partie 2.

Sources
   
Importation de Webservices (documentation PCSOFT)
Microsoft : Description du langage WSDL
W3Schools
W3C

16 commentaires:

Anonyme a dit…

Bonjour,


j'aurais néanmoins une question si vous me permettez.

Vous passez vos paramètres : ok
Vous lisez votre réponse : ok

Mais comment faites vous pour envoyer ces paramètres à un serveur via un httprequete?

en effet, j'utilise un webservice chronopost mais je reste coincé pour envoyer ces paramètres à leur serveur car même si la requête a pour résultat : 'OK',
le HTTPDonneRésultat renvoi un fichier html dont le contenu n'a rien a voir avec la réponse souhaité

Vincent a dit…

Quel est le contenu du résultat retourné ?

Anonyme a dit…

Bonjour,

Très intéressant comme exemple.

J'ai une question complémentaire. Comment ajouter une entête (Adresse, Password, etc..) quand le service l'exige.

Merci

Vincent a dit…

Je ne me suis pas encore penché sur cette possibilité.
Dès que j'ai le temps, je jette un œil à cela ;
Si vous trouvez avant moi, n'hésitez pas à partager la solution !

ANDAVAKA a dit…

Bjr, j'ai une question à vous poser. Comment peut on passer des paramètres tableaux à un webservice?
Est ce que c'est possible ou bien windev et webdev ne gère pas ça encore?

Vincent a dit…

Il est vrai que mon exemple ne donne pas d'informations, mais dans le cadre d'un de mes webservices, j'ai utilisé des tableaux en Java

(au niveau du code - Java bien sûr - de la procédure du webservice, j'ai par exemple : char[] paramsa).

Lors du passage de paramètres dans WinDev, au lieu d'écrire :

RSHelloParams.Paramsa = "X"

On écrira :

RSHelloParams.Paramsa[1] = "X"
RSHelloParams.Paramsa[2] = "Y"
...

Dans le code Java, j'interroge mon tableau de chaines en commençant par l'indice 0, puisque tout tableau en Java commence toujours par l'indice 0 et non pas 1 !

Si on crée le Web service en Windev, il est possible de typer les paramètres.

Voir la documentation ici : http://doc.pcsoft.fr/fr-FR/?1513001&name=parametre-une-procedure-une-fonction

Sellius a dit…

Bonjour,

J'essaye d'utiliser un webservice avec windev 18, mais pour l'instant je bloque.

J'ai bien importé mon Webservice, avec les types et la fonction qui sont bien redescendus (visible dans l'explorateur de projet).

Le cas est le même que votre exemple (le type complexe en entrée a le même nom que la fonction où il est passé en paramètre).

Seulement, au moment de consommer le webservice (à l'exécution), windev m'affiche un message d'erreur :

"Impossible de convertir un élément de type declencherDemandeTraitement en type declencherDemandeTraitement."

Voilà mon code d'appel au webservice :

________________________________________________________________________________________________________________________________________
resultat est un DeclenchementDemandeTraitementServiceImplService.declencherDemandeTraitementResponse

declencherDemandeTraitementRequest est un DeclenchementDemandeTraitementServiceImplService.declencherDemandeTraitement

declencherDemandeTraitementRequest.datetraitement = "2014-04-08T09:20:00.000"

declencherDemandeTraitementRequest.MGFON_COD = "CAEPB007"
declencherDemandeTraitementRequest.MGMCH_NUM = "SRVTRT1"
declencherDemandeTraitementRequest.MGUTI_COD = "EXPLOIT"
declencherDemandeTraitementRequest.param[1] = "1"
declencherDemandeTraitementRequest.param[2] = "108"
declencherDemandeTraitementRequest.param[3] = l_nom_fichier

resultat = DeclenchementDemandeTraitementServiceImplService.declencherDemandeTraitement(declencherDemandeTraitementRequest)
________________________________________________________________________________________________________________________________________


J'ai utilisé l'auto-completion et les glisser-déposer depuis la définition du webservice, rien n'y fait.

Avez-vous une idée ?

Vincent a dit…

J'ai essayé en WD19 avec mon WS développé en Java/Axis2, voici mon code...

RSMonWebService est un MercatorTest2.getArticlesForRunResponse
RSMonWebServiceParam est un MercatorTest2.getArticlesForRun
RSMonWebServiceParam.server = GP_clAS400.p_sIP
RSMonWebServiceParam.slib = GP_clAS400.p_sLibs
RSMonWebServiceParam.paramsa[1] = "512"
RSMonWebServiceParam.paramsa[2] = ""
RSMonWebServiceParam.paramsa[3] = "N"
RSMonWebServiceParam.paramsa[4] = ""
RSMonWebServiceParam.paramsa[5] = ""
RSMonWebServiceParam.paramsa[6] = ""
RSMonWebServiceParam.paramsa[7] = GP_clAS400.p_sUser
RSMonWebServiceParam.paramsb[1] = 1
RSMonWebServiceParam.paramsb[2] = 1
RSMonWebServiceParam.paramsb[3] = 1
RSMonWebServiceParam.paramsb[4] = 1
RSMonWebServiceParam.paramsb[5] = 1
RSMonWebServiceParam.paramsb[6] = 1
RSMonWebServiceParam.paramsb[7] = 1

RSMonWebService=MercatorTest2.getArticlesForRun(RSMonWebServiceParam)

SI ErreurDétectée ALORS
Erreur("Echec de l'appel au service Web",ErreurInfo())
SINON
Info(RSMonWebService.return)
FIN

Ca fonctionne correctement... J'ai bien une réponse de la part du service... En quoi le vôtre est-il programmé ? Où est-il déployé ? Votre appel semble bien correspondre à ce qui est expliqué dans la documentation officielle : http://doc.pcsoft.fr/fr-FR/?3086001. Du coup, j'ai du mal à comprendre où se situe le problème.

Sellius a dit…
Ce commentaire a été supprimé par un administrateur du blog.
Sellius a dit…

Oups, apparemment, il n'aime pas les chevrons.
Premier WSDL :

wsdl:definitions name="DeclenchementDemandeTraitementServiceImplService" targetNamespace="http://adressewebservice2/" xmlns:ns1="http://adressewebservice/" xmlns:ns2="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://adressewebservice2/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
wsdl:import location="http://adressewebservice_appli/declencherDemandeTraitement?wsdl=DeclenchementDemandeTraitementService.wsdl" namespace="http://adressewebservice/" /
wsdl:binding name="DeclenchementDemandeTraitementServiceImplServiceSoapBinding" type="ns1:DeclenchementDemandeTraitementService"
soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /
wsdl:operation name="declencherDemandeTraitement"
soap:operation soapAction="" style="document" /
wsdl:input name="declencherDemandeTraitement"
soap:body use="literal" /
/wsdl:input
wsdl:output name="declencherDemandeTraitementResponse"
soap:body use="literal" /
/wsdl:output
/wsdl:operation
/wsdl:binding
wsdl:service name="DeclenchementDemandeTraitementServiceImplService"
wsdl:port binding="tns:DeclenchementDemandeTraitementServiceImplServiceSoapBinding" name="DeclenchementDemandeTraitementServiceImplPort"
soap:address location="http://adressewebservice_appli/declencherDemandeTraitement" /
/wsdl:port
/wsdl:service
/wsdl:definitions

Sellius a dit…

Second :

Second :

wsdl:definitions name="DeclenchementDemandeTraitementService" targetNamespace="http://adressewebservice/" xmlns:ns1="http://adressewebservice/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://wwww3.org/2001/XMLSchema">
wsdl:types
xs:schema elementFormDefault="unqualified" targetNamespace="http://adressewebservice/" version="1.0" xmlns:tns="http://adressewebservice/" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xs:element name="declencherDemandeTraitement" type="tns:declencherDemandeTraitement" />
xs:element name="declencherDemandeTraitementResponse" type="tns:declencherDemandeTraitementResponse" />
xs:complexType name="declencherDemandeTraitement"
xs:sequence
xs:element minOccurs="0" name="MGFON_COD" type="xs:string" />
xs:element minOccurs="0" name="MGUTI_COD" type="xs:string" />
xs:element minOccurs="0" name="MGMCH_NUM" type="xs:string" />
xs:element minOccurs="0" name="datetraitement" type="xs:dateTime" />
xs:element maxOccurs="unbounded" minOccurs="0" name="param" type="xs:string" />
/xs:sequence
/xs:complexType
xs:complexType name="declencherDemandeTraitementResponse"
xs:sequence
xs:element minOccurs="0" name="return" type="tns:webServiceResponse" />
/xs:sequence
/xs:complexType
xs:complexType name="webServiceResponse"
xs:sequence
xs:element minOccurs="0" name="element" type="xs:string" />
xs:element maxOccurs="unbounded" minOccurs="0" name="errors" nillable="true" type="tns:webServiceError" />
xs:element minOccurs="0" name="messageError" type="xs:string" />
xs:element minOccurs="0" name="returnCode" type="xs:int" />
/xs:sequence
/xs:complexType
xs:complexType name="webServiceError"
xs:sequence
xs:element minOccurs="0" name="attributes"
xs:complexType
xs:sequence
xs:element maxOccurs="unbounded" minOccurs="0" name="value" type="xs:anyType" />
/xs:sequence
/xs:complexType
/xs:element
xs:element minOccurs="0" name="code" type="xs:string" />
xs:element minOccurs="0" name="message" type="xs:string" />
xs:element minOccurs="0" name="objectInError" type="xs:string" />
xs:element name="severity" type="xs:short" />
/xs:sequence
/xs:complexType
/xs:schema
/wsdl:types
wsdl:message name="declencherDemandeTraitementResponse"
wsdl:part element="ns1:declencherDemandeTraitementResponse" name="parameters" />
/wsdl:message
wsdl:message name="declencherDemandeTraitement"
wsdl:part element="ns1:declencherDemandeTraitement" name="parameters" />
/wsdl:message
wsdl:portType name="DeclenchementDemandeTraitementService"
wsdl:operation name="declencherDemandeTraitement"
wsdl:input message="ns1:declencherDemandeTraitement" name="declencherDemandeTraitement" />
wsdl:output message="ns1:declencherDemandeTraitementResponse" name="declencherDemandeTraitementResponse" />
/wsdl:operation
/wsdl:portType
/wsdl:definitions

Vincent a dit…

Voici le WSDL de mon côté pour l'un de mes services...
http://pastebin.com/3grcNPLV.

Peut-être voir s'il y a des différences entre les deux (le mieux est de copier aussi le vôtre sur pastebin pour avoir plus facile et poster le lien).

Sellius a dit…

Je viens de tester le WDSL dans SOAPui, aucun soucis, les méthodes fonctionnent bien.
Je pense donc que c'est WINDEV qui n'arrive pas à importer correctement le schéma (confusion sur les types).
Comme je ne peux pas toucher au WDSL, je pense que je vais abandonner ce webservice.

Merci de votre aide

romulus001 a dit…

Bonjour, est-il possible d'avoir un exemple d'appel d'un webservice qui envoie et qui reçoit un fichier ZIP (convertit en tableau de bytes) et dont l'appel requiert une identification? J'ai tout expliqué dans ce message : http://www.developpez.net/forums/d1587396/environnements-developpement/windev/envoyer-fichier-webservice/

Vincent a dit…

J'ai répondu sur les forums PC SOFT.
http://forum.pcsoft.fr/fr-FR/pcsoft.fr.windev/195495-appel-web-service-pour-envoyer-recevoir-fichier-zip-195559/read.awp

romulus001 a dit…

Bonjour, merci de m'avoir répondu, cependant, le type proposé n'existe pas...