Interopérabilité des services Web de type «Contract First» (priorité au contrat) entre Microsoft .NET et IBM WebSphere

minceillusionInternet και Εφαρμογές Web

30 Ιουλ 2012 (πριν από 5 χρόνια και 23 μέρες)

645 εμφανίσεις

Interopérabilité des services Web de type «

Contract First

»
(priorité au contrat) entre Microsoft .NET et IBM WebSphere

Eric Cherng

Vertigo Software, Inc.

James Duff

Vertigo Software, Inc.

Dino Chiesa

Microsoft Corporation

28

octobre

2004

Public visé

:



Architectes et développeurs

Télécharger l'exemple d'interopérabilité pour cet article

Introduction

Contenu de l'exemple d
'interopérabilité

Conditions et configuration logicielle requises

Pourquoi des services Web

?

Service Web

1

: Addition

Service Web

2

: Évaluations et rapports

Service Web

3

: Recherche de produits

Conclusion

Recommand
ations/Astuces

Remerciements

Liens utiles

Introduction

Tandis que les services Web attirent de plus en plus d’adeptes, les fournisseurs s’efforcent
d’ajouter de nouveaux standards et fonctionnalités dans leurs infrastructures pour enrichir et
consolider la comm
unication entre systèmes. Les organisations, qui investissent de plus en plus de
temps et d’argent dans la recherche de l’optimisation des services Web et de leurs technologies de
base, doivent connaître les forces et les limites de ces technologies, notam
ment en matière de
savoir
-
faire du développeur, de facilité de maintenance et d’interopérabilité. Le présent article est
consacré à l’interopérabilité

; il définit comme point de départ l’interopérabilité entre Microsoft .NET
Framework et IBM WebSphere via

les services Web. L’objectif de ce livre blanc et de l’exemple qui
l’accompagne est d’expliquer aux développeurs de chaque plate
-
forme comment intégrer l’autre
plate
-
forme. Bien que notre étude soit focalisée sur les plates
-
formes .NET de Microsoft et
Web
Sphere d’IBM, les exemples illustrent des techniques et principes de base pouvant être
réutilisés dans tous les projets exigeant une interopérabilité entre plates
-
formes via des services
Web.


Contenu de l’exemple d’interopérabilité

Cet exemple contient

:

1.

L’exemple de code de service Web

:



Il s'agit de services Web et de clients des services Web écrits en Java et en C#
pour trois interfaces de service différentes

:

1.

Service Web

1

: il s'agit d'un service Web effectuant une simple addition dont
l’objectif e
st de vous familiariser avec les outils et les plates
-
formes utilisés.

2.

Service Web

2

: ce service montre comment faire passer des types d’objet
complexes d’une plate
-
forme à l’autre.

3.

Service Web

3

: ce service met en évidence un modèle de conception pour c
réer
des services Web extensibles, capables de gérer les modifications dans les
mappages de données.



Chaque service Web fait preuve d’une interopérabilité hétérogène. Il suffit de
modifier un paramètre sur le client du service Web pour que celui
-
ci puisse

communiquer soit avec le service Web .NET, soit avec le service WebSphere.



Dans cet exemple simple, il n’est pas nécessaire d’avoir accès à la base de données
pour exécuter un service Web et un client.



Dans ce document, nous étudierons en détail la créati
on du service Web

1 à partir
des principes de base. Nous n’approfondirons pas autant l’analyse des services Web

2
et

3.

2.

Ce livre blanc, qui décrit en détail les différents services Web et leur conception.

Les techniques et concepts abordés dans cet artic
le sont généraux et peuvent donc s’appliquer à
toute connexion entre deux plates
-
formes de fournisseurs différents. Néanmoins, les exemples ont
été développés et testés uniquement avec les kits de développement (SDK) de services Web de
.NET Framework et d’
IBM WebSphere.


Conditions et configuration logicielle requises

Cet article sur l’interopérabilité (et l’exemple associé) considère que le lecteur connaît les bases de
.NET Framework, d’ASP.NET et du serveur d’application WebSphere d’IBM. Le service Web

1
s’adresse aux développeurs qui n’ont jamais créé de services Web ou qui ne connaissent pas l’une
des deux plates
-
formes. Même si vous êtes familiarisé avec les services Web et avec les deux
plates
-
formes en question, nous vous conseillons de consulter au m
oins la partie concernant le
service Web

1 car elle contient des trucs et astuces utiles qui ne figurent pas dans les sections
traitant des services Web

2 et

3.


Configuration logicielle requise

Nous avons utilisé les logiciels suivants pour créer et teste
r les exemples.



Microsoft Windows

XP Professionnel SP1



Microsoft Internet Information Services

5.1



Kit de développement (SDK) de Microsoft

.NET Fra
mework, version

1.1



SDK de Sun Java, version

1.4



Kit de développement pour services Web de WebSphere (WSDK), version

5.1



Kit des développeurs de services Web Java (JWSDP), version

1.3


Si vous n’avez aucun logiciel Java, vous devez impérativement installer les logiciels requis dans
l’ordre suivant

:

1.

SDK Sun

Java

1.4

2.

Eclipse

2.1.3

3.

WSDK

5.1

4.

JWSDP

1.3

5.

Eclipse nécessite le SDK Java, lequel est inclus dans le WSDK mais pour installer le WSDK,
Eclipse doit déjà être installé

!

6.

Vous trouverez des informations complémentaires sur l’installation dans le fichier READ
ME
à télécharger avec les exemples d’interopérabilité.


Pourquoi des services Web

?

Les services Web en tant que technologie applicative existent depuis de nombreuses années. Bien
avant que les organisations et les sociétés ne créent les standards de servi
ces Web, les analystes
d’entreprise, les architectes et les ingénieurs en logiciel avaient compris que les données
d’entreprise étant dispersées sur de nombreux systèmes, il fallait que ces derniers puissent
communiquer entre eux. Les premières tentatives
de liaison des applications entre elles à l’aide des
technologies d’appel de procédure distante (RPC), comme RMI, DCOM et d’autres mécanismes
d’interconnexion spécifiques à certaines plates
-
formes, ont généralement échoué en raison de la
diversité des four
nisseurs et des plates
-
formes utilisées dans les organisations. Ces approches ont
aussi avorté parce que leur usage n’était pas adapté à Internet, d’où la lenteur, voire l’absence de
réponses sur ce réseau. D’autres solutions, qui utilisaient les files d’a
ttente de messages, les
verbes PUT/GET et l’ordonnancement manuel des messages, posaient des problèmes de
maintenance et de productivité en matière de programmation. C’est pourquoi les développeurs ont
opté pour des standards et protocoles courants

: XML e
t HTTP.

Lorsque les ingénieurs se sont lancés dans la création d’applications capables de communiquer
entre elles, ils ont choisi XML parce que ce langage est utilisé et pris en charge par toutes les
plates
-
formes. Le protocole HTTP a été retenu en raison
de son utilisation étendue et de sa
capacité à traverser les pare
-
feu. Les fournisseurs comme Microsoft ou IBM ont commencé à créer
des infrastructures pour soutenir ces efforts de développement et faciliter le travail des
développeurs. Pour cela, ces infr
astructures éliminaient la charge que représentent la sérialisation
et la désérialisation du XML et fournissaient des éléments structurels communs comme le code
requis pour établir des connexions entre systèmes. La naissance des services Web a été accueill
ie
comme une promesse de simplification de l’intégration entre systèmes et applications hétérogènes.
Les fournisseurs, utilisant les services Web comme catalyseur, se rallient maintenant autour du
concept d’architecture orientée services qui permet d’inter
connecter des solutions individuelles,
éventuellement créées (en toute légitimité) à l’aide de protocoles RPC propriétaires comme RMI ou
DCOM. Les données peuvent ainsi circuler en temps réel dans toute l’entreprise.

Les bénéfices et le potentiel en termes

d’intégration sont donc réels, mais dans la pratique, les
développeurs estiment pour la plupart que la création de services Web interopérables est plutôt
complexe. La création de services Web même très simples recèle de nombreux risques comme les
conflits

de types ou l’absence de prise en charge de certaines fonctions. Notre premier exemple
présente un service Web interopérable. Nous vous expliquerons les différentes étapes du processus
de conception et de création d’un tel service.


Service Web

1

: Additi
on

Le premier exemple explique les bases d’un service Web interopérable. Il s’agit d’un service qui
effectue une simple addition. Il accepte deux entiers de la part du client et renvoie la somme de
ces deux nombres.

Le schéma fonctionnel suivant décrit l’
architecture de ce service Web

:


Figure 1. Architecture fonctionnelle du service Web

1.

Qu’est
-
ce qui vient en premier, l’implémentation ou l’interface

?

La technique de création de services Web la plus courante, la plus avérée et la mieux prise en
charg
e par les outils consiste à «

inférer

» une interface de service Web à partir d’une
implémentation existante. Le développeur rédigera le code suivant

:

public int Ajouter(int x, int y) { return x+y; }

Dans ASP.NET, il est très simple d'exposer ce code en
tant que service Web

: il suffit d’ajouter au
code l’attribut
WebMethod
. Cette technique est souvent appelée «

Implementation First

»
(priorité à l’implémentation) ou «

Code First

» (priorité au code) car l’interface de service Web,
décrite de façon formel
le dans un document
WSDL (Web Service Description Language)
, est
dérivée de l’implémentation.


Figure

2. Développement d’un service Web par l
a méthode «

Implementation First

»
(priorité à l’implémentation).

La technique de développement de services Web appelée «

Implementation First

» consiste à écrire
d’abord le code du service Web (voir étape nº

1 de la figure

2). Après compilation, l’infrast
ructure
des services Web utilise ce code pour générer de façon dynamique un fichier WSDL (étape nº

2).
Lorsque les clients demandent la définition du service Web, ils récupèrent le fichier WSDL généré et
créent le proxy client à partir de cette définition
(étape nº

3).

Par exemple, dans ASP.NET, le fichier WSDL peut être généré de façon dynamique à partir d’une
implémentation avec URL comme celle
-
ci

:

http://hostname:port/Service1.asmx?WSDL

Lorsque le runtime de .NET détecte le paramètre WSDL dans la requê
te, il effectue une réflexion
sur le code doté de l’attribut
WebMethod

pour générer de façon dynamique une opération de
description du service sous
-
jacent dans le fichier WSDL.

Cette technique d’implémentation est très simple et fonctionne très bien, mais
elle génère quelques
problèmes, notamment en cas de services Web utilisés pour connecter des systèmes hétérogènes.
Par exemple, si l’on commence par l’implémentation, il n'est pas possible d’inclure dans le service
Web des types spécifiques à une plate
-
for
me. Les types de jeux de données .NET et de vecteurs
Java sont spécifiques à une plate
-
forme et sont difficiles à représenter sur d’autres plates
-
formes.
En effet, il n’existe pas encore de mappage unique et bien défini entre ces types spécifiques et
XML.
Ce n’est pas parce qu’un client .NET est capable de reconnaître dans un Blob de XML un jeu
de données, qu’un client de service Web écrit en Java peut faire la même chose. Nous sommes
donc confrontés à des problèmes d’interopérabilité.

Le schéma XML standar
d W3C définit des types de données intégrés dont, entre autres, les chaînes
(string), les entiers de différentes tailles (integer), les variables booléennes (Boolean), les variables
représentées en virgule flottante (float) en simple et double précision ou

les données de date et
d’heure (DateTime). Chaque plate
-
forme applicative prend également en charge son propre jeu de
types de données. L’intersection entre ces jeux de types de données définit les types qui offriront la
meilleure interopérabilité entre p
lates
-
formes. Si vous commencez par des types appartenant au
schéma XML, il est facile de les mapper vers les types spécifiques à la plate
-
forme, mais si vous
commencez par ces derniers, le mappage inverse n’est pas forcément possible. Par exemple le
mappa
ge des types integer, string, Boolean et float du schéma XML vers les types de données
correspondant dans .NET ou Java est facile. En revanche, les types de vecteurs (Vector) ou de
tables de hachage (Hashtable) sont natifs des différentes plates
-
formes et
ne font donc pas partie
des types officiels du schéma XML. Pour plus d’informations sur les types de données pris en
charge, consultez les
spécifications

(en anglais) des types de données du schéma XML.

Les
runtimes de la plupart des services Web (y compris le runtime intégré à .NET Framework et à
WSDK) sont capables d’effectuer un mappage entre les primitives du schéma XML et les primitives
spécifiques à la plate
-
forme. Ainsi, une chaîne du schéma XML sera m
appée vers le type
System.String

dans .NET et vers le type
java.lang.String

dans Java. Avec les primitives du schéma XML
et les structures et tableaux générés à partir de ces primitives, il est possible de créer des types de
données plus complexes, décrits

dans le schéma XML, qui pourront être mappés de façon très
fidèle d’une plate
-
forme à l’autre. Ces types de données peuvent alors figurer dans les documents
WSDL à utiliser dans le service Web.

Cela représente l’essence de la méthode appelée «

WSDL first

»
(priorité au WSDL)

: si vous
utilisez les types du schéma XML pour définir les types de données utilisés dans le service Web,
vous avez plus de chance de pouvoir mapper ces types de données entre plates
-
formes.

Cette technique qui consiste à créer d’abor
d le fichier WSDL est aussi appelée parfois «

Schema
First

» (priorité au schéma). Si ces deux appellations sont généralement employées
indifféremment, elles renvoient en fait à deux concepts légèrement différents. Dans cet article,
nous souhaitons amener
les architectes et les développeurs à créer le contrat à partir des
définitions WSDL, avant de créer le code sous
-
jacent du service. Pour créer le fichier WSDL, les
développeurs peuvent soit créer des définitions de schéma XML spécifiques à l’interface ave
c
laquelle elles seront utilisées («

WSDL First

»), soit utiliser les schémas XML déjà définis dans leur
domaine d’application («

Schema First

»). Cet article utilisera la terminologie du concept «

WSDL
First

».


Figure 3. Développement d’un service Web p
ar la méthode «

WSDL First

» (priorité au
WSDL).

Le problème avec la technique consistant à créer d’abord le fichier WSDL, c’est que les outils
produits aujourd’hui ne favorisent pas cette pratique. Elle reste néanmoins faisable, mais difficile à
implément
er. Visual Studio comporte un éditeur de schéma et un éditeur XML mais pas d’éditeur
WSDL. Eclipse ne propose pas non plus d’éditeur WSDL. Heureusement, ces deux environnements
offrent une fonctionnalité permettant de générer le squelette de code du servic
e Web en plus du
code du proxy client à partir d'un fichier WSDL.

Vous pouvez utiliser l’outil de votre choix pour créer votre propre fichier WSDL, y compris VI ou le
Bloc
-
notes. Plutôt que d’éditer directement le texte, vous pouvez aussi utiliser pour plu
s de
commodité des outils spécialisés comme XmlSpy d’Altova, dotés de concepteurs WSDL. Toutefois,
cette solution n’est pas forcément appropriée dans la mesure où de nombreux développeurs
restent incapables de «

penser en WSDL

».

Il existe une solution à c
e problème

: concevoir rapidement un prototype d’interface de service
Web en utilisant la technique «

Implementaiton First

». Il suffit d’utiliser les fonctions de génération
dynamique de fichier WSDL d’ASP.NET ou du WSDK d’IBM pour créer un fichier modèle

WSDL. Il
devient alors possible d'entreprendre le développement selon la méthode «

WSDL First

» et de
peaufiner l’interface à sa guise. Ce processus s’exécute de façon itérative jusqu’à obtention du
fichier WSDL final.

Comme l’illustre la figure

3 ci
-
dess
us, la création de services Web à partir de la méthode «

WSDL
First

» comporte trois étapes majeures

:

1.

Créer le fichier WSDL.

2.

Implémenter le document WSDL.

a.

Créer le service Web.

b.

Créer le client du service Web.

Vous pouvez effectuer les sous
-
étapes A et B
de l’étape

2 dans l’ordre de votre choix. Comme elles
dépendent toutes deux du document WSDL, ce qui importe, c’est de créer le document WSDL
avant d’entreprendre A ou B.

Dans la suite de cette section, nous étudierons les étapes du développement du premie
r exemple
de service Web selon le processus «

WSDL First

». Vous trouverez le code source complet de cet
exemple dans le téléchargement qui accompagne cet article.

Création du fichier WSDL à partir de Visual Studio .NET («

Implementation First

»)

Avant d’a
border la création de services Web à partir de l'option «

WSDL First

», qui consiste à
générer d’abord le fichier WSDL, nous étudierons le modèle de développement «

Implementation
First

» de Visual Studio .NET, qui accorde la priorité à l’implémentation. N
ous avons choisi de
commencer par cette méthode car la création d'un fichier WSDL en partant de zéro est une tâche
difficile. Il est beaucoup plus simple avec les outils dont vous disposez de prendre un raccourci et
d’utiliser le fichier WSDL généré par l’
approche «

Implementation First

». Imaginez qu’il vous faille
entrer manuellement le code suivant

:

<?xml version="1.0" encoding="utf
-
8"?>
<definitions xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" x
mlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:s0="http://example.org/"
targetNamespace="h
ttp://example.org/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <types> <s:schema
elementFormDefault="qualified" targetNamespace="http://example.org/"> <s:element name="Add"> <s:complexType>
<s:sequence> <s:element minOccurs="1" maxOccurs="1" name="x" type="
s:int" /> <s:element minOccurs="1"
maxOccurs="1" name="y" type="s:int" /> </s:sequence> </s:complexType> </s:element> <s:element
name="AddResponse"> <s:complexType> <s:sequence> <s:element minOccurs="1" maxOccurs="1" name="AddResult"
type="s:int" /> </s:se
quence> </s:complexType> </s:element> </s:schema> </types> <message name="AddSoapIn"> <part
name="parameters" element="s0:Add" /> </message> <message name="AddSoapOut"> <part name="parameters"
element="s0:AddResponse" /> </message> <portType name="Service1
Port"> <operation name="Add"> <input
message="s0:AddSoapIn" /> <output message="s0:AddSoapOut" /> </operation> </portType> <binding
name="Service1Soap" type="s0:Service1Port"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document"
/> <operation name="Add"> <soap:operation soapAction="http://example.org/Add" style="document" />
<input> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding>
<service name="Service1"> <port name="Serv
ice1Soap" binding="s0:Service1Soap"> <soap:address
location="http://localhost/NetWSServer/Service1.asmx" /> </port> </service> </definitions>

Si pour le développeur WSDL chevronné, cet exercice peut sembler banal, pour le reste d’entre
nous, il supposerai
t d’ingurgiter les 51

pages de spécifications WSDL. C’est pourquoi nous
utiliserons au démarrage la méthode commençant par l’implémentation. Pour les développeurs, la
création d'un service Web en rédigeant du code est en effet la technique la plus simple.

Commencez par créer un projet de
service Web ASP.NET

en C# dans Visual Studio .NET. Appelez
ce projet
WebService1WSDL
.


Figure

4. Boîte de dialogue Nouveau projet dans Visual Studio

.NET.

Ensuite, ouvrez le code du fichier Service1.asmx. Supprimez les co
mmentaires de la méthode
HelloWorld et remplacez cette méthode par la suivante

:

[WebMethod] public int Ajouter(int x, int y) { return
-
1; }


Figure 5. Code d’un service Web selon la méthode «

Implementation First

».

Créez le projet et vérifiez qu’il n’y

a pas d’erreur. Puis, cliquez avec le bouton droit sur
Service1.asmx

et configurez cette page comme page de démarrage. Vous pouvez maintenant
appuyer sur F5 pour afficher la page de test du service Web (figure

6).


Figure

6. Page de test du service Web.

Soulignons que ce soit le fichier ASMX qui constitue le véritable service Web. La page que vous
visionnez est générée par l’infrastructure pour documenter le service Web et pour permettre au
développeur de tester ce service sans avoir à créer manuellement
une application cliente. La
fonctionnalité de test n’est accessible que si vous affichez cette page localement

; elle ne
fonctionne pas pour les services Web utilisant comme paramètres d’entrée des types de données
complexes. Pour des raisons de sécurité,
pensez à désactiver cette page de test après avoir
déployé votre service Web sur une machine de production.

Cliquez ensuite sur le lien
Service Description

(Description du service) situé en haut à droite de
la page. Cette action ouvre une autre page Web af
fichant le WSDL généré pour votre service. La
fonction de génération du WSDL reste disponible tant que vous ne la désactivez pas délibérément.
Enregistrez le fichier WSDL sur votre disque local et nommez
-
le
WebService1.wsdl
.


Figure

7. Fichier WSDL généré

par Framework.

Vous venez de créer un fichier WSDL sans avoir eu à apprendre les spécifications WSDL

!

Autre conseil important ici

: étant donné que nous avons généré le fichier WSDL à partir de ce
projet temporaire, l’emplacement du service Web dans le d
ocument WSDL est préprogrammé de
façon à pointer vers ce projet temporaire. Cela n’a aucune incidence sur le service Web en lui
-
même, mais les clients qui utilisent ce fichier WSDL utiliseront cette référence comme
emplacement du service Web. Il est donc i
mportant de modifier cette valeur avant de déployer le
fichier WSDL sur le site Web. Nous changerons cette référence plus tard, dès que nous connaîtrons
l’emplacement réel de notre service Web.

Si vous avez oublié de modifier cet emplacement et que les app
lications clientes ont déjà été
créées, vous pouvez toujours corriger la référence en modifiant l’emplacement vers lequel pointent
les références des clients. Dans .NET et dans WebSphere, les proxys clients de services Web
permettent de configurer correcte
ment la propriété d’URL. Cela s’avère également utile lorsque
vous passez du développement à la production et que vous ne souhaitez modifier que le point de
terminaison du service.

Comme le service Web que nous créons est simple, le fichier WSDL n’a pas be
soin d’être peaufiné.
L’étape suivante consiste à créer le service Web .NET.

Implémentation du service Web

.NET («

WSDL First

»)

À partir du fichier WSDL généré à l’étape précédente, nous allons maintenant créer un nouveau
service Web .NET.

Pour passer du
fichier WSDL à un fichier de code source, nous utiliserons une application console
appelée
wsdl.exe

pour générer le code. Cet outil analyse le fichier WSDL et tous les autres fichiers
externes pour créer un fichier de code source unique contenant toutes le
s classes, méthodes et
types requis pour implémenter le service Web. Wsdl.exe est installé avec Visual Studio

.NET

2003
(et le SDK de .NET). Pour utiliser cet outil, vous devez ouvrir l’
invite de commande de Visual
Studio

.NET

2003
, située par défaut dans
le menu
Démarrer
, sous
Tous les
programmes/Microsoft Visual Studio

.NET

2003/Outils Visual Studio .NET
, puis aller à
l’endroit ou vous avez enregistré le fichier WSDL.

Pour que wsdl.exe génère le fichier source du service Web, exécutez la commande suivante
.

wsdl.exe /server WebService1.wsdl


Figure

8. Invite de commande de Visual Studio

.NET

2003 exécutant wsdl.exe.

Notez que l’utilitaire génère un message indiquant que le fichier
Service1.cs

a été créé. Ce fichier
sera le point de départ de notre service

Web.

Le fichier généré par wsdl.exe n’est qu’un modèle de la méthode que nous souhaitons
implémenter

; il doit donc être modifié pour fonctionner correctement. La commande wsdl.exe
active génère toujours une classe abstraite pour le service Web lorsqu’el
le est exécutée avec
l’option
/server
. Nous la convertirons en classe concrète en éliminant le mot clé
abstract

et en
fournissant une implémentation pour la méthode
Add
. Nous placerons également la classe dans
l’espace de noms
WebService1
. Nous obtiendrons

le code suivant

:

namespace WebService1 { /// <remarks/>
[System.Web.Services.WebServiceBindingAttribute(Name="Service1Soap",
Namespace="http://tempuri.org/")] public class Service1 :
System.Web.Services.WebService { /// <remarks/>
[System.Web.Services.We
bMethodAttribute()]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"http://tempuri.org/Add", RequestNamespace="http://tempuri.org/",
ResponseNamespace="http://tempuri.org/",
Use=System.Web.Services.Description.SoapBindingUse.Literal, Parameter
Style=
System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public int Add(int x,
int y) { int result; result = x + y; return result; } } }

Peut
-
être vous demandez
-
vous pourquoi ne pas simplement sous
-
classer la classe abstraite
générée au lieu de l
a convertir en classe concrète

? Il existe une bonne raison. L’outil wsdl.exe
génère du code doté d’attributs utilisés par le sérialiseur XML de .NET et le runtime des services
Web pour effectuer le mappage des objets vers le XML et inversement. Dans notre

exemple, un
attribut utilise l’espace de noms http://tempuri.org pour le document XML généré. Ce type
d'attribut n'est pas hérité par les sous
-
classes. Par conséquent, si nous sous
-
classions la classe
abstraite, il nous faudrait couper
-
coller tous ces att
ributs dans notre classe concrète.

Plutôt que de dupliquer manuellement tous ces attributs, il est plus simple de modifier le fichier
directement. Bien sûr, cela signifie que si le fichier WSDL est modifié, il vous faudra générer à
nouveau le code source d
u fichier WSDL. Il convient d’effectuer cette tâche avec soin pour éviter
d’effacer tout le code existant. Vous devrez copier manuellement dans le nouveau fichier le code
d’implémentation du service Web figurant dans l’ancien fichier.

Maintenant que le cod
e source de notre service Web est prêt, nous pouvons créer notre solution
Visual Studio. Créez dans Visual Studio .NET un nouveau projet de
service Web ASP.NET en C#
et appelez le
WebService1
.

Cela fait, copiez le fichier Service1.cs créé précédemment et c
ontenant le code d’implémentation
du service Web dans le répertoire contenant les fichiers du service Web générés par Visual Studio.
Il s’agit généralement de c:
\
inetpub
\
wwwroot
\
WebService1.


Figure

9. Affichage dans l’Explorateur Windows des fichiers du
projet de service Web.

L’exemple de service Web
Service1.asmx

est généré en tant qu’élément de l’Assistant de projet
Visual Studio. Puisque la commande wsdl.exe ne génère que le code d’implémentation du modèle
et non le fichier d’entrée (ASMX), nous préfér
ons réutiliser le fichier Service1.asmx généré par
Visual Studio plutôt que d’en créer un nous
-
même. Cependant, il existe déjà un fichier source
correspondant au fichier Service1.asmx. Pour associer le fichier ASMX à notre code
d’implémentation, il suffit
d’effacer le code d’implémentation généré par Visual Studio
(
Service1.asmx.cs
) et d’attribuer le nom de ce fichier à notre code d’implémentation. Pour cela,
vérifiez que les fichiers Service1.asmx et Service1.asmx.cs ne sont pas ouverts dans Visual Studio,

puis supprimez le fichier Service1.asmx.cs et attribuez le nom Service1.asmx.cs au fichier
Service1.cs.

Pour vérifier que la transplantation du code a bien fonctionné, sélectionnez
Service1.asmx

dans
l’Explorateur de solutions de Visual Studio et cliquez
sur le menu Afficher, puis sur Code. Le code
du modèle doit s’afficher et l’implémentation de la méthode Add que nous avons modifiée
précédemment doit apparaître dans Visual Studio .NET.

Enfin, pour tester le bon fonctionnement du service, cliquez avec le
bouton droit sur
Service1.asmx

puis cliquez sur
Définir comme page de démarrage
. Allez ensuite dans le menu
Déboguer

et cliquez sur
Démarrer
pour créer le projet et ouvrir Service1.asmx dans votre
navigateur. Vérifiez que le service Web fonctionne correcte
ment à l’aide de la page de test.


Figure

10. Page de test du service Web d’addition.


Figure

11. Réponse du service Web à la requête en ajoutant 12 et 45.

Pour empaqueter le service Web .NET, il nous faut maintenant retourner au document WSDL
d'origine
pour effectuer quelques modifications mineures. Comme nous l’avons déjà remarqué, le
document WSDL pointe actuellement vers notre service Web de projet temporaire. Maintenant que
nous avons terminé la création du service Web réel, nous pouvons modifier la
référence de
localisation de façon à ce qu’elle pointe vers ce service. Pour cela, ouvrez le document WSDL
d'origine et remplacez l’attribut
location

de l’élément
soap:address

pour qu’il pointe vers ce
nouveau service Web. Le nouvel élément
soap:address

do
it se présenter comme suit

:

<port name="Service1Soap" binding="s0:Service1Soap"> <soap:address
location="http://localhost/NetWSServer/Service1.asmx" /> </port>


Figure

12. Modification de l’emplacement du service Web dans le fichier WSDL.

La création d’
un service Web .NET selon la méthode «

WSDL First

» est maintenant terminée. Nous
allons à présent créer le client de service Web WSDK qui utilisera ce service Web .NET.

Implémentation du client de service Web WSDK

Maintenant que notre service Web est impl
émenté, nous allons créer un client pour l’utiliser.
Comme le sujet de cet article est l’interopérabilité, nous utiliserons le service Web .NET en
exécutant une page JSP sur le serveur d’application WebSphere d’IBM.

Démarrez Eclipse et créez un nouveau pro
jet Web Dynamique (
Dynamic Web Project
). Appelez
ce projet
WebServiceClient1

et le fichier de projet EAR
WebServiceClient1Ear
.


Figure 13. A
ffichage dans Eclipse du projet WebServiceClient1.

Ensuite, ajoutez le fichier WSDL au projet WebServiceClient1. Pour cela, il suffit de faire glisser le
fichier directement dans le projet situé dans le volet de navigation d’Eclipse.

Nous souhaitons mainte
nant générer un proxy Java pour le service Web. De même que Visual
Studio .NET crée une classe proxy lorsqu’une référence Web est ajoutée à un projet, les outils
WSDK vont créer un jeu de fichiers Java qui permettront d’appeler le service Web plus facileme
nt
que s’il fallait intervenir directement sur les échanges réseau. Puisque nous avons déjà ajouté le
document WSDL au projet, vous pouvez créer le proxy en cliquant avec le bouton droit sur le
document WSDL, en pointant sur le menu
Web Services

(Services
Web) et en cliquant sur
Generate Client
(Générer le client). Cela ouvrira l’Assistant
WSDL to Java Bean Proxy

(WSDL
vers proxy Java Bean) illustré à la figure

14.


Figure

14. Assistant WSDL to Java Bean Proxy.

Dans la première boîte de dialogue, pensez à cocher la case
Test the generated proxy

(Tester le
proxy généré). Cela ouvrira la page JSP (similaire à la page de test générée à partir de
S
ervice1.asmx

à la création d’un service Web dans Visual Studio) qui servira à vérifier les classes
proxy générées. Pour les autres options de l’Assistant, les valeurs par défaut conviennent. Vous
pouvez donc cliquer sur
Finish
(Terminer).

Dès qu’Eclipse a
terminé de générer tous les fichiers nécessaires, la page de test suivante s’affiche
dans la fenêtre principale d’Eclipse.


Figure

15. Affic
hage dans l’IDE d’Eclipse de la page de test JSP.

Cliquez sur
add(int,int)

dans le volet
Methods

(Méthodes) et indiquez deux nombres à additionner
dans le volet
Inputs

(Entrées). La somme de ces deux nombres doit s’afficher dans le volet du bas
Result

(Rés
ultat). En arrière
-
plan, la page JSP appelle la classe proxy du service Web, générée
précédemment par l’Assistant WSDK du service Web, pour appeler notre service Web .NET. Étant
donné que nous avons modifié la référence d'emplacement du service Web dans le

document
WSDL, notre client Java sait exactement où trouver le service Web que nous avons créé lors de
l’étape

2. Si la somme de vos deux nombres est correcte, cela démontre que le proxy Java a été
généré correctement et qu'il communique déjà avec le serv
ice Web .NET.

Il existe une autre méthode pour vérifier la connexion entre un service et un client. Elle consiste à
définir un point d’arrêt dans le code du service Web de Visual Studio .NET puis à exécuter le
service Web en mode de débogage. Côté Java, si

vous exécutez la fonction d’addition dans la page
JSP, Visual Studio .NET devrait normalement interrompre l’exécution du service et s’arrêter au
point que vous avez défini.

À ce stade, nous avons vérifié le bon fonctionnement de la classe de proxy Java gé
nérée par le
WSDL. Nous avons également utilisé la page de test générée par l’Assistant WSDK pour tester les
appels vers le service Web .NET à partir de Java. Puisque ces deux points fonctionnent bien, la
démo concernant le service Web .NET et le client de

service Web Java pour le service Web

1 est
maintenant terminée. Si nous n’avons pas décrit en détail le processus de création d’un client de
service web .NET et du serveur de service Web Java, l’exemple de code accompagnant cet article
inclut des implémen
tations de serveurs et de clients dans .NET et dans Java. Si vous souhaitez les
générer vous
-
même, vous trouverez d’autres didacticiels concernant ces procédures.

Service Web

2

: Évaluations et rapports

Le deuxième exemple repose sur le premier pour créer

un service Web utilisant un schéma de
données beaucoup plus complexe. Notre objectif dans cet exemple est de montrer l’interopérabilité
entre .NET et WebSphere avec des types de données complexes. Dans le schéma de cet exemple
figurent, en plus des types
standards du schéma XML, des types complexes, des types simples, des
énumérations, des restrictions, des tableaux et des types qui héritent d’autres types. Les
différences entre les deux plates
-
formes et les problèmes d’interopérabilité que pose le
dévelop
pement de services Web sont plus manifestes dans cet exemple en raison de sa plus
grande complexité.

Scénario

La société Stuff Sellers vend une gamme variée de produits à différents types d’entreprises.
Chaque entreprise est autorisée à soumettre des appré
ciations des produits qu’elle achète. Le
scénario étudié dans le service Web

2 est celui d’un service d’évaluation permettant aux
utilisateurs de soumettre un rapport pour une évaluation donnée ou d’obtenir une liste de tous les
rapports pour une évaluatio
n donnée identifiée par un nombre. Dans cet exemple, nous pouvons
considérer que les rapports correspondent aux appréciations et que la somme de ces appréciations
permet de générer l’évaluation finale.

Schéma de données

La figure suivante illustre les élém
ents majeurs du schéma de données.


Figure

16. Principaux éléments du schéma de données du service Web

2.

L’élément de plus haut niveau est
Ratings
(évaluations). Chaque élément
Ratings

contient un
tableau d’éléments
ReportSet

(jeu de rapports) encapsulé dans le type
ReportSetArray
(tableau
de jeux de rapports). Chaque élément
ReportSet

contient un tableau d’éléments
Report

(rapport)
encapsulé

dans le type
ReportArray
(tableau de rapports). Ces trois éléments de niveau supérieur
sont des types de données qui héritent du type
MyBase

(ma base). Pour consulter la vraie
définition de schéma XML pour ce schéma de données, reportez
-
vous au fichier
We
bService2SharedTypes.xsd à télécharger avec les exemples.

Comme avec WSDL, il existe deux façons de générer un schéma XML. La première consiste à
concevoir manuellement le schéma en utilisant un concepteur de schéma (dans le cas d’un schéma
XML, Visual Stu
dio inclut un concepteur). La deuxième consiste à inférer le schéma à partir d’un
type .NET existant à l’aide de l’utilitaire
xsd.exe
. Comme avec WSDL, ces deux techniques
peuvent être associées au sein d’un processus itératif permettant de peaufiner le sc
héma jusqu’à
ce qu’il soit parfait.

Dans certains cas, le schéma de données a déjà été défini et existe indépendamment de
l’implémentation ou de l’interface du service Web. Cette situation peut se présenter si vous devez
créer un service Web à partir du mo
dèle de conception d’un système existant. Que vous le
conceviez vous
-
même ou qu’il vous soit fourni, le schéma de données doit être décrit dans un
fichier XSD de schéma XML autonome pour que sa modularité et sa réutilisation puissent être
garanties.

La fig
ure suivante est un diagramme de classes illustrant le schéma XML défini dans le schéma de
données pour ce service Web. Ce schéma est défini dans le même code dans le fichier
WebService2SharedTypes.xsd
. Le code généré à partir du schéma de données (fichier

de
schéma XML) sur chaque plate
-
forme doit suivre une structure de classes similaire à celle décrite
dans ce diagramme.


Figure

17. Diagram
me de classes du schéma de données dans le service Web

2.

Définition du service Web

Dans le premier service Web, nous avons utilisé .NET Framework pour générer le fichier modèle
WSDL initial. Comme notre service Web était simple, cette étape suffisait à cr
éer le WSDL.
Malheureusement, le présent service Web n’est pas aussi simple et une intervention manuelle
s’impose. Pour garantir l’interopérabilité, nous avons dû apporter des modifications au fichier
modèle WSDL, entre autres inclure des références à notr
e schéma de données, changer l’espace de
noms et créer les messages appropriés aux
portTypes

(types de ports).

Le document WSDL de ce service Web définit deux opérations

:
GetRatings

et
SubmitReport
.
GetRatings

renvoie un type
Ratings

si l’ID fourni corres
pond à une évaluation donnée.
L’opération
SubmitReport

permet aux clients de soumettre un nouveau rapport associé à des
éléments
Ratings

et
ReportSet
spécifiques. Vous pouvez consulter la définition WSDL de ces
opérations dans le fichier
WebService2.wsdl

à

télécharger avec les exemples.

Il existe deux façons d’inclure les définitions de schéma XML dans des fichiers WSDL

: vous pouvez
définir le schéma inline dans le fichier WSDL ou référencer vos fichiers de schéma XML dans votre
fichier WSDL à l’aide de l’
élément
xsd:import
. Les définitions inline faisant partie du fichier WSDL,
leur maintenance est simple. Cependant, comme le schéma de données décrit les données et non
l’interface du service Web et qu’il est parfois utilisé indépendamment de cette interfac
e, il est plus
logique de séparer ces deux définitions dans deux fichiers distincts. Si votre service Web est simple
et n’utilise pas trop de types de données complexes, le schéma inline fonctionnera très bien (dans
le cas du service Web

1, par exemple), m
ais il est généralement recommandé de séparer le
schéma de données de la définition du service web.

Dans ce service Web, nous avons décidé d’utiliser la méthode
xsd:import

pour référencer le fichier
de schéma XML externe (WebService2SharedTypes.xsd) à part
ir du fichier WSDL
(WebService2.wsdl). Dans le fichier WSDL, cette méthode se présente comme suit

:

<types> <xs:schema targetNamespace="http://example.org/"> <!
--

Import the Shared
Types
--
> <xs:import namespace="http://example.org/sharedtypes"
schemaLoca
tion="WebService2SharedTypes.xsd"/> <!
--

Import the Message Parameters
--
> <xs:import namespace="http://example.org/interface"
schemaLocation="WebService2Interface.xsd"/> </xs:schema> </types> . . .

Implémentation

Pour créer l’exemple de code du service W
eb dans .NET, exécutez
wsdl.exe

en définissant les
paramètres suivants

:

wsdl.exe WebService2.wsdl WebService2Interface.xsd WebService2SharedTypes.xsd

Notez que pour exécuter wsdl.exe, il faut que le fichier WSDL d’entrée et tous les fichiers XSD
inclus s
oient spécifiés ensemble dans la ligne de commande. Lors de l'importation d'un XSD dans
un WSDL, il est possible de fournir un attribut
schemaLocation
. Selon la spécification WSDL, cet
attribut sert à indiquer l’emplacement du schéma mais cette indication
n’est pas toujours suivie par
les outils qui interprètent le fichier WSDL. Dans notre exemple, wsdl.exe n’utilise pas l’indication
schemaLocation et il est donc nécessaire de spécifier les fichiers de schéma externes dans la ligne
de commande. En revanche,

les outils WSDK d’IBM reconnaissent l’indication schemaLocation et
chargeront les fichiers directement le moment venu.

Soulignons un détail important

: l’élément
ID

de
MyBase

porte le type
xsd:int

et inclut l’attribut
minOccurs=0
. La définition de schéma
XML de
MyBase

se présente comme suit

:

<xs:complexType name="MyBase"> <xs:sequence> <xs:element minOccurs="0"
maxOccurs="1" name="ID" type="xs:int" nillable="true" /> </xs:sequence>
</xs:complexType>

Si
minOccurs=0
, la propriété
ID

peut être exclue du doc
ument XML produit. Cela pose un
problème sur la plate
-
forme .NET. Dans .NET, le type xsd:int est mappé vers le type Int32 qui est
un type de valeur

; or les types de valeur ne peuvent pas être
NULL
. Cela signifie principalement
qu’il est impossible de déte
rminer si la propriété
ID

a été définie puisque toutes les valeurs de
Int32

sont valides. La plate
-
forme .NET Framework résout ce problème en créant une autre
variable appelée
IDSpecified

de type
Boolean
. Cette variable est vérifiée par la logique de
séria
lisation XML de .NET qui détermine si la variable
ID

a été définie, essentiellement en attribuant
à la variable
ID

la valeur
NULL
/
not NULL
. Ainsi, lorsque vous tentez d’accéder à la variable
ID
,
vous devez toujours vérifier ou définir d’abord la variable
I
DSpecified
. Pour plus d’informations
sur ce modèle d’utilisation, consultez la documentation MSDN sur la classe
XmlIgnoreAttribute

(en
anglais).

Une fois traduit en code C#, le type
MyBase

se présente comme suit

:

[System.Xml.Serialization.XmlTypeAttribute(Namespace=
"http://example.org/sharedtypes")]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Report))]
[System.Xml.Seriali
zation.XmlIncludeAttribute(typeof(ReportSet))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Ratings))] public class MyBase
{ public int ID; [System.Xml.Serialization.XmlIgnoreAttribute()] public bool
IDSpecified; }

Ce problème ne se pose pas si l’
on utilise l’exemple WebSphere. En effet, lorsqu’un
xsd:int

est
utilisé avec
minOccurs=0
, les outils WSDK génèrent une variable de type
java.lang.Integer

au
lieu de la variable native Java de type
int
. Le type
java.lang.Integer

est un type de référence et
il est possible pour une variable de ce type de prendre la valeur
NULL

pour indiquer qu’elle n’a pas
été définie. Voici la traduction du type
MyBase

en code Java obtenue avec les outils WSDK

:

public class MyBase implements java.io.Serializable { private j
ava.lang.Integer ID;
public MyBase() { } public java.lang.Integer getID() { return ID; } public void
setID(java.lang.Integer ID) { this.ID = ID; } }

La comparaison entre le code C# généré à partir du schéma XML et le code Java généré pour le
même schéma m
et en exergue une autre différence relative à l’inclusion des attributs de code dans
le code C#. Comme nous l’avons déjà dit, ces attributs sont utilisés par le sérialiseur XML dans
.NET pour faciliter le mappage depuis l’instance de classe vers XML. Java
nécessite également des
«

métadonnées

» similaires. Dans le cas du runtime des services Web dans WSDK, ces
métadonnées sont stockées de façon indépendante dans un fichier XML qui définit les mappages de
types. Pour plus d’informations, consultez la documen
tation WSDK.

Autre point intéressant

: si vous examinez les classes générées par les outils .NET ou WSDK, vous
constaterez peut
-
être que les types de données générés sont différents de ceux que vous auriez
écrits en tant que développeur, sans tenir compte

des questions d’interopérabilité. Regardez la
classe Ratings.java générée par WSDK. Si nous enlevons les éléments de gestion interne du code,
elle se présente comme suit

:

public class Ratings extends org.example.MyBase implements java.io.Serializable {
private java.lang.String description; private int confidenceLevel; private
java.util.Calendar expiration; private org.example.ReportSetArray allReports;
public Ratings() { } public java.lang.String getDescription() { return description;
} public void setDe
scription(java.lang.String description) { this.description =
description; } public int getConfidenceLevel() { return confidenceLevel; } public
void setConfidenceLevel(int confidenceLevel) { this.confidenceLevel =
confidenceLevel; } public java.util.Calenda
r getExpiration() { return expiration; }
public void setExpiration(java.util.Calendar expiration) { this.expiration =
expiration; } public org.example.ReportSetArray getAllReports() { return
allReports; } public void setAllReports(org.example.ReportSetArra
y allReports) {
this.allReports = allReports; } }

Il se peut que les membres des données primitives de type int et string correspondent à ce que
n’importe quel développeur aurait rédigé

: application des conventions JavaBean et empaquetage
des méthodes d’
obtention et de réglage autour d’un membre privé. Mais c’est alors qu’apparaissent
les différences. La valeur de date est gérée par un élément Calendar, et non par un java.util.Date.
Et un élément Array est empaqueté par une classe personnalisée, également

accessible via une
paire de méthodes d’obtention/réglage. Cette classe générée est probablement différente de celle
que vous auriez écrite mais elle fonctionne et présente en outre l’avantage d’être interopérable.
Vous pourriez faire le même constat conce
rnant le code généré par les outils .NET.

Nous avons suivi les grandes étapes du processus décrit dans la section précédente concernant le
service Web

1 pour créer deux projets Visual Studio

: l’un pour le client et l’autre pour le serveur.
De même, nous a
vons créé deux projets WebSphere avec le WSDK. Tous ces clients et serveurs
sont interopérables. Pour voir comment tout cela fonctionne, compilez et exécutez les projets
Visual Studio et Eclipse à télécharger avec les exemples. Avant cela, n’oubliez pas de

lire le fichier
Readme concernant ce téléchargement.

Dans cet exemple, nous avons étudié l’utilisation des types de données complexes dans un service
Web interopérable. Le schéma XML W3C joue un rôle fondamental dans la définition des types de
message et

des éléments de données à échanger. Cette section a expliqué comment développer un
XSD pour un type de données complexe et comment employer ce schéma XML dans un document
WSDL. Elle a également souligné quelques questions adjacentes à connaître, notamment

la
différence entre les types de valeur et les types de référence dans .NET et les conséquences de
cette différence sur la sérialisation XML.

Dans l’exemple suivant, nous allons développer davantage les idées abordées dans cet exemple et
étudier l’intero
pérabilité avec les éléments de données extensibles.

Service Web

3

: Recherche de produits

La plupart des services Web emploient un schéma de données fixe, ce qui signifie que les types de
données transmis sur le réseau sont déjà connus au moment de la con
ception. Mais parfois, les
schémas de données statiques ne permettent pas de répondre aux besoins de l’application.
Considérons le scénario d’entreprise suivant.

Scénario

Comme nous l’avons déjà dit dans le service Web

2, Stuff Sellers vend différents prod
uits aussi
bien aux consommateurs qu’à d’autres entreprises. Comme cette gamme de produits est très
vaste, le directeur nous a demandé de créer un service Web qui faciliterait la recherche de produits
dans la base de données. Cet outil sera utilisé indirec
tement par les consommateurs par le biais de
la vitrine Internet du magasin et directement par les autres entreprises.

Le directeur souhaiterait que ce service Web satisfasse aux trois exigences suivantes

:

1.

Il doit accepter les données dynamiques. Dans
la mesure où la société Stuff Sellers ajoute
souvent de nouveaux types de produits à sa base de données, la définition du service Web
doit être suffisamment flexible pour prendre en charge les nouveaux types sans que cela
n’interrompe le fonctionnement des

clients existants.

2.

Il doit prendre en charge les opérations de base. Les entreprises qui recherchent des
produits Stuff Sellers seront probablement intéressées par des produits présentant une
propriété spécifique. Un magasin de vente au rabais recherchera

des produits coûtant
moins de 50

centimes, par exemple. Le service Web doit donc être capable de renvoyer des
données et permettre au client d’effectuer sans difficulté une simple vérification des
résultats obtenus pour cette propriété.

3.

Il doit être exten
sible. La société Stuff Sellers aura probablement besoin de modifier le
service Web à l’avenir et souhaite donc que ce service puisse prendre en charge facilement
de nouvelles fonctions, avec une incidence minimum sur les clients existants.

Outre ces exig
ences, le directeur souhaiterait que l’interface du service Web soit aussi simple que
possible. Plus précisément, le service Web ne devra avoir qu’un seul point d’entrée.

Si nous analysons les produits vendus actuellement par Stuff Sellers, nous constatons

que tous les
produits sont dotés au minimum d’un nom (
Name
), d’une description
(Description)
, d’un prix
(
Price
) et d’une unité de gestion des stocks (
SKU
). Ces attributs constituent les propriétés de base
de tous nos produits. De plus, chaque produit est
doté de son propre jeu d’attributs unique. Par
exemple, un film DVD est doté d’un code région (
Region
), d’un format de vidéo (
Format
), d’une
langue (
Language
) et d’une date de parution (
ReleaseDate
). Un livre est doté d’une liste d’auteurs
(
Authors
), d’un
éditeur (
Publisher
), d’un code ISBN (
ISBN
) et d’une date de publication
(
PublishedDate
). Par conséquent, le type de produit de base exposera toutes les propriétés
communes à tous les types de produits et acceptera les extensions pour les propriétés spécifi
ques
à certains types de produits.

Schéma de données

Voici un diagramme de classes du schéma de données défini pour le service Web

3.


Figur
e

18. Diagramme de classes du schéma de données du service Web

3.

La définition de type de schéma XML pour
SearchResult

(résultat de la recherche) dans
WebService3SharedTypes.xsd se présente comme suit

:

<xs:complexType name="SearchResult"> <xs:sequence> <
xs:element minOccurs="1"
maxOccurs="1" name="SKU" type="xs:string"/> <xs:element minOccurs="1" maxOccurs="1"
name="Price" type="xs:decimal" /> <xs:element minOccurs="1" maxOccurs="1"
name="Name" type="xs:string"/> <xs:element minOccurs="1" maxOccurs="1"
na
me="Description" type="xs:string" /> <xs:element minOccurs="1" maxOccurs="1"
name="ProductType" type="xs:string" /> <xs:any minOccurs="1" maxOccurs="1"
processContents="lax" /> </xs:sequence> </xs:complexType>

Comme vous pouvez le constater,
SearchResult

est le type parent qui représente tous les
produits trouvés par le service Web.
SearchResult

contient les propriétés communes à tous les
types de produits. De plus,
SearchResult

contient également un élément
xsd:any

qui sert de
caractère générique. Un fich
ier XML conforme à ce schéma peut inclure n’importe quel élément
XML à cet emplacement. Dans le cas qui nous intéresse, l’élément
xsd:any

contiendra l’un des
types de propriété de produit que le service Web peut renvoyer. Nous en avons défini trois dans le

fichier WebService3ExtendedProperties.xsd

:
DvdProperties
,
BookProperties

et
CDProperties
(respectivement, propriétés du DVD, du livre et du CD). Dans la pratique, l’application cliente
accèdera aux propriétés communes en vérifiant SearchResult et accèder
a aux propriétés étendues
de ce produit en vérifiant la variable du membre contenant les types de propriétés spécifiques du
produit.

Plutôt que d’utiliser
xsd:any

dans le schéma pour le mappage des éléments XML, il est également
possible d’employer un élém
ent string (chaîne) dans le schema qui contiendra le XML généré de
façon dynamique. L’utilisation d’une chaîne est similaire à celle du caractère générique. La
différence, c’est que le XML contenu dans la chaîne est défini pour échapper à la transmission e
t
sera donc opaque pour les analyseurs XML, ce qui n’est pas ce que nous souhaitons. Il est plus sain
d’intégrer le XML dynamique dans le document XML que de définir son échappement dans un
élément de chaîne. Dans les deux cas, du travail supplémentaire s’
impose, qu’il s’agisse de générer
le XML côté expédition ou de l’analyser côté réception.

Définition du service Web

Comme dans le deuxième exemple, le document WSDL de ce service Web est composé de deux
fichiers

:
WebService3.wsdl

et
WebService3SharedTypes
.xsd
.
WebService3.wsdl

contient
les déclarations définissant le service Web et
WebService3SharedTypes.xsd

est un fichier de
schéma XML contenant les types de données utilisés par le service Web. Voici un exemple de
capture de message SOAP renvoyé par le se
rvice Web au client.

<?xml version="1.0" encoding="utf
-
8" ?> <soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema
-
instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <SearchRespon
se
xmlns="http://example.org/sharedtypes"> <SearchResult> <SearchResult>
<SKU>B05502HB9I</SKU> <Price>14.99</Price> <Name>Spain's History</Name>
<Description>Short documentary on the history of the Spain.</Description>
<ProductType>DVD</ProductType> <DvdPr
operties
xmlns="http://example.org/resulttypes"> <Region>EUROPE</Region>
<Format>PAL</Format> <Language>Spanish</Language> <ReleaseDate>2000
-
05
-
14</ReleaseDate> </DvdProperties> </SearchResult> <SearchResult>
<SKU>A04D5E87RJ</SKU> <Price>20.00</Price> <Nam
e>Spain's History</Name>
<Description>Companion coffee table book to the documentary "Spain's
History".</Description> <ProductType>Book</ProductType> <BookProperties
xmlns="http://example.org/resulttypes"> <Authors> <Author>Mark Person</Author>
</Authors>
<Publisher>BookPub Central</Publisher> <ISBN>0459756212</ISBN>
<PublishedDate>2003
-
08
-
08</PublishedDate> </BookProperties> </SearchResult>
</SearchResult> </SearchResponse> </soap:Body> </soap:Envelope>

Il existe également un troisième fichier,
WebService
3ExtendedProperties.xsd
, qui n’est pas
importé dans le WSDL mais qui est essentiel pour que le service Web puisse générer une réponse
et que les clients puissent interpréter cette réponse. Ce fichier contient les définitions de la partie
dynamique des donn
ées

: les propriétés étendues des types de produits.

La séparation des types de produits des types utilisés par le service Web présente un avantage

: la
possibilité d’étendre les types de produits sans modifier l’interface. À l’avenir, Stuff Sellers sera
a
mené à étendre son activité et à vendre d’autres types de produits. Comme les résultats de
recherche contiendront ces nouveaux produits, il est indispensable que l’ajout de nouveaux
produits puisse s’effectuer sans difficulté. Dans notre modèle de concepti
on, la prise en charge de
nouveaux types est simple

: il suffit d’étendre l’implémentation du service Web pour qu’il renvoie
ces nouveaux types et d’ étendre le schéma de données défini dans
WebService3ExtendedProperties.xsd
. Dernières étapes

: publier le
nouveau fichier XSD sur le
Web et informer les utilisateurs de cette modification. Il n’est pas nécessaire de modifier le fichier
WSDL.

Les clients du service Web qui ne souhaitent pas utiliser les propriétés étendues ou se contentent
de les transmettre au
x autres services peuvent choisir d’ignorer ces propriétés. À l’exécution, ces
clients n’ont pas besoin de désérialiser le Blob XML dans des objets. Par exemple, si une application
est écrite pour filtrer des produits uniquement en fonction du prix, le typ
e de produit renvoyé n’a
aucune importance. Dans ce cas, le client doit vérifier uniquement la propriété de base
Price

du
type
SearchResult

et peut ignorer en toute sécurité les propriétés étendues.

Grâce à la flexibilité qu’offre l’élément
xsd:any
, le ser
vice Web peut ajouter de nouvelles fonctions
sans que cela n’interrompe le fonctionnement des clients existants. Les nouveaux clients du service
Web pourront utiliser les nouveaux types de produits tandis que les applications existantes se
contenteront de
les ignorer. Même si des types de produits sont éliminés, les clients existants du
service Web continueront de fonctionner correctement

: il leur suffira de ne pas exécuter le code
appartenant aux anciens produits. Cette méthode de conception offre un comp
romis idéal

: les
messages de réponse peuvent être étendus pour les nouvelles applications sans que cela n’altère le
bon fonctionnement des applications existantes.

Implémentation

On appelle «

sérialisation XML

» ou «

liaison XML

» la conversion entre le X
ML et les instances
correspondantes des objets. En général, la conversion de paramètres en appel de service Web et
du XML transmis en demande ou en réponse du service Web est effectuée automatiquement par le
runtime des services Web. Cependant, si l’on uti
lise des extensions de schéma non définies dans le
WSDL (ou les XSD correspondants importés), cette sérialisation et cette désérialisation XML
doivent être effectuées manuellement. La plate
-
forme .NET propose des outils et des interfaces de
programmation p
ermettant cela.

IBM WebSphere ne propose pas d’interface publique permettant d’effectuer manuellement une
sérialisation XML. Le client et le serveur Java doivent être dotés d’une capacité complémentaire
pour effectuer la liaison entre Java et XML. Il s’agi
t de l’API JAXB qui fait partie du kit des
développeurs de services Web Java de de Sun (JWSDP). Le kit JWSDP vous fournira le compilateur
JAXB, capable de générer la classe Java à partir du schéma XML de façon similaire à l’utilitaire
xsd.exe dans .NET. Il

est beaucoup plus simple d’utiliser les classes pour référencer les types de
données que de manipuler directement les éléments XML. Dans JAXB, les classes de type de
données générées sont également responsables des opérations d’ordonnancement (ou
«

marsha
lling

») et de «

sérialisation

» vers les fichiers XML (qui doivent être conformes au XSD),
ainsi que des opérations inverses.

Le SDK de .NET Framework inclut également des outils et une infrastructure de liaison des données
XML avec les classes .NET. L’o
util
Xsd.exe

analyse les fichiers XSD pour créer un fichier de code
source correspondant contenant les classes de définition des types de données. À l’exécution, les
applications peuvent utiliser l’espace de noms
System.Xml.Serialization

des classes pour c
réer un
graphique d’objet à partir du XML transmis et inversement.

Par exemple, à la compilation, pour générer des classes C# à partir du schéma
WebService3ExtendedProperties.xsd, utilisez la commande suivante

:

xsd.exe /classes WebService3ExtendedPropert
ies.xsd

Ensuite, à l’exécution, pour créer le graphique d’objet à partir d’un fichier, utilisez ces quelques
lignes de code

:

FileStream fs = new FileStream(path, FileMode.Open); XmlSerializer s= new
XmlSerializer(typeof(BookPropertiesType)); BookPropert
iesType props; try { props=
(BookPropertiesType) s.Deserialize(fs); } finally { fs.Close(); }

Normalement, pour les types de données utilisés dans les interfaces des services Web, la création
des classes de type de données et la sérialisation sont exécuté
es automatiquement

: la création
des classes est exécutée par l’outil wsdl.exe ou par l’utilitaire «

Ajouter une référence Web

» dans
Visual Studio et la sérialisation, par le runtime des services Web dans .NET. Lorsque vous
transmettez un paramètre à un s
ervice Web, ce paramètre est automatiquement sérialisé en XML
pour pouvoir être transmis sur le réseau. Il est nécessaire ici d’utiliser xsd.exe pour créer les
classes car le schéma
WebService3ExtendedProperties.xsd

n’est pas explicitement inclus dans
la d
éfinition de l’interface du service Web.

Qu’en est
-
il de la sérialisation à l’exécution

? Lorsque l’outil
xsd.exe

analyse un schéma, il mappe
les éléments
xsd:any

vers des champs de type
XmlElement
. En modifiant les classes générées,
en changeant le type
de champ par
System.Object

plutôt que par System.Xml.XmlElement et en
associant au champ les attributs
XmlElementAttribute
, nous pouvons demander à l’infrastructure
de mapper les données XML vers des types de données .NET spécifiques plutôt que vers un
élé
ment générique XmlElement. Par exemple, dans cet extrait de code, le champ Any sera mappé
vers l’une des trois propriétés étendues.

[System.Xml.Serialization.XmlElementAttribute(ElementName="DvdProperties",
Type=typeof(NetWSServer3.DvdPropertiesType),
Name
space="http://example.org/resulttypes")]
[System.Xml.Serialization.XmlElementAttribute(ElementName="BookProperties",
Type=typeof(NetWSServer3.BookPropertiesType),
Namespace="http://example.org/resulttypes")]
[System.Xml.Serialization.XmlElementAttribute(El
ementName="CDProperties",
Type=typeof(NetWSServer3.CDPropertiesType),
Namespace="http://example.org/resulttypes")] public object Any;

Ces modifications des classes générées permettront au runtime de .NET de sérialiser de façon
automatique et implicite les

types d’objet de propriété Product depuis et vers XML. Sans cette
fonctionnalité, le développeur devrait effectuer une sérialisation explicite de ces classes vers XML.
C’est d’ailleurs la solution retenue par WebSphere pour les types de propriété étendus.

(Pour plus
de détails, voir l’exemple de code).

Lors du développement de cet exemple, il a fallu déterminer entre autres s’il fallait faire de
ProductType

une énumération ou une simple chaîne. L’avantage avec l’énumération, c’est que les
différents types

sont indiqués de façon explicite et qu’il n’y a donc pas de confusion possible.
Cependant, nous avons finalement décidé de ne pas utiliser d’énumération à cause des exigences
d’extensibilité

: notre solution doit être suffisamment flexible pour qu’il soit

possible de créer des
types de produits supplémentaires ou d’en éliminer sans que cela n’interrompe le fonctionnement
des clients existants. Si
ProductType

est défini en tant qu’énumération, la transmission de
nouveaux types de produits à d’anciens client
s entraînerait un dysfonctionnement. C’est pourquoi
nous avons utilisé une chaîne, celle
-
ci offrant la possibilité d’étendre les lignes de produits sans
interrompre le fonctionnement des clients du service Web existants.

Comme dans le service Web

2, les ty
pes de données générés ici par les outils seront probablement
différents de ceux qu’aurait rédigés un développeur tentant de modéliser le problème sous forme
de code. Cependant, là encore, le principal avantage de commencer par le WSDL et de générer le
cod
e réside dans l’interopérabilité.

Comme dans le service Web

2, nous avons suivi les grandes étapes du processus présenté dans
l’introduction de cet article pour produire des projets de clients et de serveurs pour Visual Studio et
le kit de développement (S
DK) de services Web WebSphere. Une fois encore, les clients et serveurs
obtenus offrent une interopérabilité totale. Bien, arrêtons les discussions et passez à l'action.
Compilez et exécutez les projets Visual Studio et Eclipse dans les exemples à téléchar
ger pour
vérifier l’extensibilité de ce service Web

3 en action.

Le service Web

3 illustre l’utilisation de types de données complexes inclus de façon statique ou
dynamique dans un document WSDL. La prise en charge des types extensibles permet d’étendre e
t
de modifier l’interface en réduisant au minimum les modifications à apporter au service Web et aux
clients de ce service.

Conclusion

Les trois services Web décrits dans cet article démontrent qu’il est tout à fait possible de créer des
services Web inte
ropérables en utilisant des types de données complexes. La méthode la plus
simple avec les outils de développement, qui commence par l’implémentation («

Implementation
First

»), pose souvent des problèmes d’interopérabilité. En revanche, si l’on définit d’
abord
l’interface du service Web (WSDL) et que l’on génère ensuite les clients et les serveurs à partir de
cette définition d’interface, il est possible d’éviter de nombreux pièges pouvant compromettre
l’interopérabilité. Bien que nous ayons limité notre a
pproche «

WSDL First

» à .NET et à
WebSphere, les concepts illustrés s’appliquent aux problèmes d’interopérabilité entre n’importe
quelles plates
-
formes.

La rédaction manuellement du WSDL n’est pas simple. Cet article a aussi décrit la méthode
consistant à

développer sur le mode itératif et à peaufiner les fichiers WSDL et les définitions de
schéma XML W3C en utilisant les outils de prototype inclus dans Visual Studio .NET et WSDK.

Enfin, cet article fournit des conseils et des indications sur les pièges p
ossibles que recèle la
création de services Web interopérables et extensibles. Si nous poursuivons cet idéal
d’interopérabilité des services Web, peut
-
être le rêve d’un accès omniprésent à n’importe quel
système, indépendamment de la plate
-
forme ou de l’ar
chitecture, deviendra
-
t
-
il réalité.

Voici la liste des recommandations et astuces mentionnées dans cet article.

Recommandations/Astuces

Utilisation des documents WSDL

1.

Lors de la rédaction manuelle du code WSDL, prenez garde au contexte de l’espace de
noms
actuel. La chaîne de l’espace de noms doit être rigoureusement identique dans toutes
les références au même espace de noms.

2.

Si votre service Web doit retourner un type de données complexe pour lequel le mappage
vers et depuis XML n’est pas bien défini, env
isagez de créer votre propre type de données
pour représenter les mêmes données. Cela optimise la portabilité sans empêcher la
transmission des données nécessaires.

3.

Pour garantir la modularité et la réutilisation, utilisez l’importation XSD plutôt que les
définitions de schéma inline. Reportez
-
vous aux exemples du service Web

2 et du service
Web

3.

4.

Prenez garde aux attributs optionnels des types de données dans la définition de schéma
XML. Certains d’entre eux peuvent altérer le mode de génération du code
d
’implémentation. Reportez
-
vous à l’exemple du service Web

2 sur la définition de la
variable
ID
.

5.

WS
-
I (Web Services Interoperability Organization), organisation pour l’interopérabilité des
services Web, est un organisme officiel créé pour promouvoir l’inte
ropérabilité des services
Web entre toutes les plates
-
formes et langues. Cette organisation a créé une spécification
pour l’interopérabilité appelée WS
-
I Basic Profile et fournit des outils permettant de vérifier
si les fichiers WSDL respectent cette spéci
fication.

6.

Lorsqu’une exception se produit dans le service Web, un élément
SOAPFault

est renvoyé
dans le message SOAP. En principe, l’infrastructure du service Web s’empare de l’élément
SOAPFault

et renvoie sa propre classe d’exception. Dans .NET Framework,

SOAPFault

est
pris et empaqueté dans la classe
System.Web.Services.Protocols.SoapException
. Dans WebSphere,
l’exception renvoyée est
com.ibm.ws.webservices.engine.WebServicesFault
. Vous trouverez des
informations complémentaires sur les erreurs dans les p
ropriétés des classes d’exceptions
mentionnées.

7.

Tous les types complexes XSD sont convertis en classes. Comme Java ne prend pas
actuellement en charge les énumérations, les valeurs d’énumérations sont traduites en
constantes public static string dans la cl
asse Java correspondante.

8.

Certaines fonctionnalités du schéma XSD ne sont pas bien représentées sur certaines
plates
-
formes actuelles, par exemple les types d’entiers non signés (unsigned integer) dans
XSD. Si .NET fournit des types non signés, ce n’est pa
s le cas de Java. C’est pourquoi il
n’est pas recommandé de les utiliser dans des services Web interopérables.

9.

L’utilisation des tableaux est risquée si l’on utilise des conditions de limitation. Dans .NET,
si un tableau vide est sérialisé, seul l’élément
d’en
-
tête XML est créé. Si un tableau NULL
est sérialisé, il est totalement ignoré et aucune sérialisation en XML ne sera effectuée. En
revanche, Java sérialise l’élément XML dans les deux cas. La différence, c’est que pour la
case NULL, le runtime des ser
vices Web dans WebSphere balise l’élément XML à l’aide d’un
attribut xsd:nil=true pour indiquer que le tableau porte la valeur Null.

10.

Lorsqu’un client WebSphere désérialise un tableau .NET vide, il crée un tableau avec une
référence NULL. Si un client WebSp
here désérialise un tableau .NET Null, une exception
java.lang.NullPointerException

est insérée.

11.

Lorsqu’un client .NET désérialise un tableau WebSphere vide, il crée un tableau d’une
longueur égale à zéro. Lorsqu’un client .NET désérialise un tableau WebSp
here Null, il
attribue la valeur NULL à la référence du tableau.

Utilisation de Wsdl.exe

Lorsqu’un fichier WSDL référence d’autres fichiers (par exemple, des fichiers XSD), vous devez
fournir de façon explicite l’emplacement de ces fichiers sous forme d’a
rguments dans wsdl.exe.
Pour des raisons de sécurité,
wsdl.exe

ne charge pas automatiquement les fichiers indiqués par
des références
schemaLocation

dans le fichier WSDL. Par exemple, si vous générez le code pour le
service Web

2, vous devrez exécuter la c
ommande suivante

:

wsdl.exe WebService2.wsdl WebService2Interface.xsd WebService2SharedTypes.xsd

Reportez
-
vous au service Web

2 pour plus d’informations sur ce point.

Wsdl.exe

génère par défaut un exemple de code en C#. Si vous souhaitez utiliser un autre

langage (ex.

: VB.NET), insérez l’option
/l

dans la commande

:

wsdl.exe /l:vb WebService1.wsdl

Lorsque l’outil génère un fichier source pour le service Web (à l’aide de l’option
/server
), il crée un
modèle de classe abstraite associé au document WSDL. Il

est recommandé de modifier ce fichier
directement plutôt que de sous
-
classer le fichier généré. Pour plus d’informations à ce sujet,
reportez
-
vous au service Web

2.

Visual Studio .NET

2005 prendra en charge la génération de fichiers source modèles directe
ment à
partir du WSDL dans l’IDE. De plus, si le document WSDL est modifié et qu’il faut générer à
nouveau le fichier modèle, c’est l’IDE qui s’en chargera en s’assurant que tout le code existant dans
l’ancien modèle a bien été reporté dans le nouveau modè
le.

Utilisation de Visual Studio .NET

Lors de la création d’une application de service Web dans Visual Studio .NET, le projet généré
fournit automatiquement une page de test qui s’affiche à l’exécution du service Web à partir du
navigateur. Comme nous déve
loppons des services Web en utilisant la méthode qui consiste à
créer d’abord le fichier WSDL («

WSDL First

»), nous vous recommandons de désactiver ce WSDL
généré automatiquement et de publier votre propre WSDL dans un emplacement public. Pour
désactiver
la page de test et le WSDL générés automatiquement, ajoutez les éléments suivants
dans l’élément
<system.web>

du fichier
web.config

de votre projet

:

<webServices> <protocols> <remove name="Documentation" /> </protocols>
</webServices>

Outre la technique
consistant à utiliser
wsdl.exe

pour créer une classe proxy de service Web, vous
pouvez aussi opter pour une méthode plus conviviale grâce aux outils intégrés dans Visual
Studio.NET. La boîte de dialogue
Ajouter une référence Web
vous demandera d’effectuer
le
pointage vers un fichier WSDL, qui sera utilisé pour générer une classe proxy. L’opération effectuée
en coulisses par la boîte de dialogue consiste essentiellement à appeler
wsdl.exe

à l’arrière plan
pour traiter le fichier WSDL.

Malheureusement, si vou
s tentez de créer un proxy client en utilisant la commande
Ajouter une
référence Web
de Visual Studio

.NET

2002 pour effectuer un pointage vers un document WSDL
utilisant
xsd:import
, vous obtiendrez un bogue. Si c’est le cas, utilisez toujours la commande
wsdl.exe

pour générer le proxy client. Ce bogue a été corrigé dans Visual Studio

.NET

2003,
désormais capable de récupérer tous les fichiers importés et de générer ensuite la classe de proxy
client.

Création du WSDL avec Eclipse

Grâce aux outils fournis da
ns le WSDK, Eclipse offre une fonctionnalité des services Web similaire à
celle de Visual Studio. Dans Eclipse, vous devez créer un fichier Java Bean ou EJB qui servira de
modèle pour le service Web. Vous pouvez également recourir à des utilitaires de lign
e de
commande pour générer les fichiers modèles du service Web. Pour plus d’informations sur cette
procédure, consultez la documentation d’Eclipse.

Remerciements

Nous remercions Simon Guest de Microsoft pour ses comptes
-
rendus et commentaires techniques
ex
cellents, ainsi que Neil Chopra et Mike Hanley de Vertigo Software pour avoir testé et enrichi
certaines idées développées dans cet article.

Liens utiles

Titre

Emplacement

Page d’accueil des
services Web de Microsoft

http://msdn.microsoft.com/webservices/

(en anglais)

Page d’accueil des
services Web d’IBM

http://www.ibm.com/webservices

(en anglais)

Page d’accueil des
services Web de BEA

http://www.bea.com/webservices/

(en anglais)

Organisation WS
-
I

http://www.ws
-
i.org


Version finale de la
spécification WS
-
I Basic
Profile

http://www.ws
-
i.org/Profiles/BasicProfile
-
1.0.html

(en anglais)

Yasser Shohoud

http://msdn.microsoft.com/msdnmag/issues/02/12/WebServicesDesign/

(en
anglai
s)

Will Provost

http://webservices.xml.com/pub/a/ws/2003/07/22/wsdlfirst.html

(en anglais)