I. Introduction▲
Il peut arriver d'appeler une fonctionnalité disponible sur un domaine distant du nôtre afin d'importer des données ou d'exécuter un traitement. Par exemple, nous pouvons vouloir accéder aux informations de l'utilisateur disponible sur le domaine A ou alors de modifier ses informations. De même qu'à titre informatif, énormément de sites internet proposent leur propre service web tels que TwitterTwitter, FacebookFacebook ou encore AppleApple (iTunes). Depuis l'API d'iTunes, vous avez la possibilité de faire une recherche avec des mots-clés (paramètre term) en spécifiant le store (paramètre country), le nombre de résultats désirés (paramètre limit) ou encore le type de résultat affiché (paramètre entity) (films, musiques, livres, etc.). Dans ce tutoriel, nous allons étudier comment appeler un service web externe à partir de Salesforce. Il faut savoir que généralement, les services web répondent avec un format JSON ou XML, mais ce n'est pas le cas de Salesforce, il examine la réponse et génère automatiquement une classe avec ses propriétés contenant le résultat de la requête ainsi que le client adéquat.
Pour ce faire, nous allons avoir besoin d'un fichier WSDL que nous allons par la suite transmettre à Salesforce pour qu'il puisse générer tout seul la classe Apex grâce à WSDL2Apex qui servira de client.
Avant d'aller plus loin, je vous propose quelques rappels sur les termes qui vont être abordés tout au long de ce tutoriel :
SalesforceSalesforce est un CRM (Customer Relationship Manager) orienté SaaSSaaS (Software as a Service) et PaaSPaaS (Platform as a Service) permettant la gestion des relations clients d'une entreprise ;
XMLXML (Extensible Markup Language) signifiant Langage de Balisages Extensibles est un format de fichier permettant de définir différents espaces de noms pour y placer différents langages de programmation accompagnés de leurs spécificités (vocabulaire et grammaire) ;
JSONJSON (JavaScript Object Notation) est un format de données permettant de représenter des données comme le permet XML ;
WSDLWSDL (Web Services Description Language) est comme son nom l'indique, un fichier au format XML décrivant le web service, c'est-à-dire les méthodes que vous pouvez appeler avec les paramètres attendus, la valeur de retour ainsi que les types de ces valeurs et l'URL d'appel de ce web service pour faire simple ;
Apex, est un langage de programmation côté serveur permettant de modifier la logique métier et le traitement des données.
II. Prérequis▲
Avant toute chose, vous devez disposer d'une instance afin de pouvoir suivre ce tutoriel. Si ce n'est pas le cas, je vous invite à vous rendre à cette adresseadresse. Salesforce met à disposition plusieurs types d'instances qui proposent différentes fonctionnalités et donc, à différents prix (prix par licence utilisateur par mois). La seule instance que vous pourrez généreusement obtenir de la part de Salesforce est celle de développement (celle que je vous propose via le lien du dessus) qui, comme son nom l'indique, sert à tester et développer des services. Je vous laisse juger par vous-même la grille tarifairegrille tarifiare sur les diverses instances que propose le CRM.
III. Bien construire son WSDL▲
Maintenant que nous possédons notre instance Salesforce (vous pouvez vous y connecter à l'adresse login.salesforce.comlogin.salesforce.com), nous devons avoir notre WSDL en notre possession afin de le transmettre à Salesforce, mais pas de souci, je vous en propose un (disponible à la fin de ce tutoriel dans les ressources). Le service web que nous allons invoquer propose les mêmes services qu'une simple calculatrice, nous allons pouvoir :
- additionner ;
- soustraire ;
- multiplier ;
- diviser.
Malgré ma faible expérience en ce qui concerne les WSDL, j'ai jusqu'à ce jour été confronté à de multiples reprises à des refus de la part du CRM de Salesforce pour valider mes WSDL suite à leur mauvaise structure (Salesforce juge mal construit) et j'ai dû par conséquent, les modifier moi-même. Je vais vous citer plusieurs messages d'erreur que vous pouvez rencontrer avec leurs explications et leurs solutions. À noter qu'un message d'erreur peut avoir plusieurs causes et plusieurs solutions.
Voici donc quelques messages d'erreur que vous êtes susceptible d'obtenir :
Unable to find schema for element; {http://tempuri.org/}GetConsumerData
Comme son nom l'indique, le schéma (la description) pour l'élément GetConsumerData n'est pas connu de Salesforce (il ne le trouve pas dans votre WSDL). Vous pouvez vérifier que votre élément est bien disposé dans le même namespace que son appelant, ou vérifier que vous n'avez pas un schéma imbriqué dans un second schéma.
Error: Failed to parse wsdl: Found schema import from location http://127.0.0.1/?xsd=xsd0. External schema import not supported
Cela signifie que la définition de vos schémas ne doit pas être accessible via une URL, le WSDL doit donc être « plat » et pour cela, vous devez copier le contenu du schéma via l'URL et ensuite le coller à l'intérieur du WSDL.
Error: Failed to parse wsdl: Found more than one wsdl:binding
Votre WSDL contient sûrement plusieurs balises wsdl:binding, vous devez soit supprimer le contenu de la deuxième (ou de la première suivant votre besoin) soit de supprimer celui comportant les éléments soap12 puisque cela n'est pas supporté par Salesforce.
Error: Failed to parse wsdl: schema:targetNamespace can not be null
Vous avez besoin d'ajouter un paramètre targetNamespace ainsi qu'une value à l'intérieur de l'élément schéma. Vous pouvez choisir n'importe quel espace de nom, http://toto.com ferait très bien l'affaire.
Error: Failed to parse wsdl: Unsupported Schema element found http://www.w3.org/2001/XMLSchema:attribute. At: 310:64
Vous devez sûrement avoir ces attributs quelque part dans votre WSDL :
<
xs
:
attribute
name
=
"FactoryType"
type
=
"xs:QName"
/>
<
xs
:
attribute
name
=
"Id"
type
=
"xs:ID"
/>
<
xs
:
attribute
name
=
"Ref"
type
=
"xs:IDREF"
/>
Vous pouvez les remplacer par ceux-ci :
<
xs
:
element
name
=
"FactoryType"
nillable
=
"true"
type
=
"xs:string"
/>
<
xs
:
element
name
=
"Id"
nillable
=
"true"
type
=
"xs:string"
/>
<
xs
:
element
name
=
"Ref"
nillable
=
"true"
type
=
"xs:string"
/>
Je partage également un articlearticle de Daniel Ballinger qui m'a fortement été utile à comprendre certains de ces messages d'erreur.
IV. Autoriser votre site dans Salesforce▲
Afin que vous puissiez faire appel au web service, vous devez faire connaître son domaine à Salesforce, dans notre cas, il s'agit de http://ws1.parasoft.com/glue/calculator. Connectez-vous à votre instance Salesforce et rendez-vous à ce chemin « Setup => Administration Setup => Remote Site Settings ». Une fois à destination, cliquez sur « New Remote Site » et renseignez les champs obligatoires demandés (le nom et l'URL du domaine) puis cochez la checkbox pour rendre ce domaine actif et enfin, validez le tout.
N'oubliez pas de spécifier le numéro du port si celui-ci est différent de 80, par exemple : http://ws1.parasoft.com/glue/calculator:1024
Salesforce n'accepte pas tous les ports, veillez bien à ce que celui-ci soit l'un de ceux-ci :
- 80 (HTTP) ;
- 443 (HTTPS) ;
- [1024 - 65535] (pas besoin d'être administrateur pour pouvoir les utiliser).
V. Générer le client à l'aide de votre WSDL▲
Une fois notre domaine accepté par Salesforce, il est temps de lui transmettre notre WSDL pour qu'il puisse générer tout seul le client (une classe Apex) grâce à WSDL2Apex. Rendez-vous à « Setup => App Setup => Develop => Apex Classes ». Ensuite, cliquez sur « Generate from WSDL » et donnez votre WSDL à Salesforce pour qu'il le parse et qu'il s'assure qu'il est valide (bien formé), il ne doit pas être plus gros que 1MB.
Dans le cas où il ne parvient pas à le parser correctement, vous obtiendrez un message d'erreur (voir chapitre III. Bien construire son WSDL). Maintenant que le WSDL est bien parsé, Salesforce vous proposera de choisir les noms de vos sous-classes (il vous demandera autant de noms que votre document comporte de namespaces), mais il vous en proposera automatiquement en fonction de vos espaces de noms.
Maintenant que vous avez choisi vos noms, il ne vous reste plus qu'à valider. Si par bonheur tout se passe bien, votre client sera automatiquement généré, mais dans le cas contraire, vous obtiendrez un message d'erreur avec, en prime, le code qui aurait dû être généré dans un champ de type « textarea » (je vous rappelle que je vous mets à disposition en bas de l'article, le WSDL que j'utilise pour ce tutoriel et il est accepté sans souci par Salesforce).
Si dans votre WSDL, vous utilisez des noms réservés en tant que nom pour des éléments, par exemple long ou int, Salesforce les renommera automatiquement en rajoutant un __x, ce qui donne long__x pour long, vous l'aurez bien compris.
VI. Appel du service web▲
Tout le travail est presque fini, il ne nous reste plus qu'à appeler notre web service, nous allons joindre la méthode additionner en lui fournissant comme demandé, deux paramètres de type double : 5.2 et 3.7. La méthode devrait donc nous retourner en principe 8.9.
Double double1 = 5.2;
Double double2 = 3.7;
CalculatorWebService.ICalculator myWebService = new CalculatorWebService.ICalculator();
myWebService.timeout_x = 120000;
Double result = myWebService.add(double1, double2);
System.debug('******');
System.debug(result);
System.debug('******');
Par défaut, Salesforce règle un timeout (attribut timeout__x(en millisecondes)correspondant au nom de la classe de votre balise binding) de 10 secondes, mais il est tout à fait possible de le modifier arbitrairement en spécifiant une valeur allant jusqu'à 120 secondes, c'est ce qui est fait pour l'exemple.
Et voici le résultat :
Nous pouvons constater que le web service nous retourne bien le résultat de 8.9 comme prévu.
VII. Conclusion▲
Nous arrivons à la fin de ce tutoriel, vous avez pu constater que d'un côté, Salesforce est très capricieux en ce qui concerne le fait d'accepter un WSDL, mais d'un autre côté, une fois que vous avez passé l'étape de son parsage, c'est pratiquement gagné puisqu'il génère tout seul un client grâce à WSDL2Apex, nous pouvons donc penser que c'est un mal pour un bien.
Pour résumer le tout, vous devez :
- renseigner le domaine de votre service web à Salesforce pour que vous puissiez l'appeler ;
- fournir un WSDL à Salesforce qu'il va par la suite parser, analyser et s'en inspirer pour générer le client (une à plusieurs classes Apex) ;
- appeler votre service web.
VIII. Ressources▲
Comme je vous l'avais promis, je vous fournis le WSDL (iciWSDL) utilisé durant cet article pour que vous soyez certain- qu'il est accepté et que vous puissiez vérifier, par vous-même, ce que j'ai dit.
De plus, voici quelques liens qui concernent la documentation officielle de Salesforce sur ce qu'il faut savoir à propos des web services, cela peut vous être utile :
. Appeler un webservice externe depuis SalesforceAppeler un webservice externe depuis Salesforce
. Création d'un client à partir d'un WSDLCréation d'un client à partir d'un WSDL
IX. Remerciements▲
Je souhaite remercier tous ceux qui ont permis à cet article de voir le jour, je parle de vermine et de Viduc.