J2EE 1.4 facilite le développement de services Web

À l'issue de sa présentation sur les services Web J2EE (Java 2 Platform, Enterprise Edition) à JavaOne de l'année dernière, l'architecte IBM Jim Knutson a fait remarquer que «chaque service Web a besoin d'un endroit pour être un service». Il a ensuite suggéré que l'endroit le plus idéal pour être un service Web était à l'intérieur de l'infrastructure J2EE. Un peu plus d'un an plus tard, la version finale de J2EE 1.4 est imminente, et sa promesse la plus importante est de tenir la vision des services Web J2EE.

Les fonctionnalités de service Web de J2EE 1.4 s'adressent à la fois aux côtés serveur et client des services Web. Les fonctionnalités étendent J2EE pour permettre aux composants Java d'entreprise existants côté serveur de devenir des services Web et spécifient comment un conteneur client J2EE peut appeler des services Web. Les technologies pour ces deux objectifs existent depuis un certain temps, et les nouvelles spécifications J2EE reposent sur ces API existantes pour la prise en charge des services Web. Les nouvelles spécifications ajoutent aux technologies existantes un ensemble d'exigences d'interopérabilité et un modèle de programmation et de déploiement pour l'intégration de services Web.

Il existe deux spécifications qui décrivent explicitement ces fonctionnalités ajoutées: la demande de spécification Java 151, le JSR parapluie pour J2EE 1.4 et JSR 109, les services Web pour J2EE. Au moment d'écrire ces lignes, JSR 109 a atteint son stade final dans le JCP (Java Community Process), tandis que JSR 151 est dans la dernière phase de vote. En outre, le JCP a modifié la version finale de JSR 101, API Java pour l'appel de procédure à distance basé sur XML (JAX-RPC), afin de prendre en charge les exigences d'interopérabilité J2EE 1.4.

Les serveurs d'applications J2EE de niveau 1.3 peuvent également implémenter de nombreuses fonctionnalités prescrites par ces JSR. En effet, de nombreux fournisseurs de serveurs d'applications ont pris en charge diverses fonctionnalités de développement et de déploiement de services Web dans leurs produits existants depuis un certain temps déjà. Les JSR 109 et 151 codifient certaines pratiques existantes et décrivent de nouveaux mécanismes dans l'espoir de créer un modèle universel d'intégration de services J2EE-Web. Les serveurs d'applications de nouvelle génération suivront probablement ce modèle unifié et standardisé.

Après un bref aperçu des nouvelles fonctionnalités J2EE liées aux services Web, cet article passe en revue les nouveaux modèles de programmation client et serveur, y compris les nouveaux rôles de déploiement J2EE et de gestion des services associés à la prise en charge des services Web.

Extensions J2EE liées aux services Web

Les ajouts les plus importants et les plus conséquents à J2EE sont peut-être les nouvelles exigences d'interopérabilité. Les exigences prescrivent la prise en charge de SOAP (Simple Object Access Protocol) 1.1 dans la couche de présentation J2EE pour faciliter l'échange de messages XML. Les conteneurs compatibles J2EE 1.4 doivent également prendre en charge le profil de base WS-I (Web Services Interoperability Consortium). Étant donné que l'échange de messages XML dans J2EE dépend de JAX-RPC, les spécifications JAX-RPC exigent désormais également la prise en charge du profil de base WS-I.

Le résultat est qu'une application basée sur J2EE 1.4 peut être appelée en tant que service Web, même à partir d'applications non écrites dans le langage de programmation Java. Bien qu'il s'agisse d'une étape évolutive pour J2EE, étant donné que la plate-forme a depuis longtemps adopté les systèmes non basés sur Java, c'est probablement le moyen le plus direct de faciliter l'interaction avec les technologies Windows qui reposent sur .Net.

Le client d'un service basé sur J2EE n'a pas besoin de savoir comment un service est implémenté. Au contraire, ce client peut utiliser le service en s'appuyant entièrement sur la définition WSDL (Web Services Description Language) du service. (Les colonnes précédentes des services Web JavaWorld expliquent comment découvrir des services en fonction de leurs définitions WSDL, et comment créer et utiliser des définitions WSDL. Voir Ressources pour les liens.) Bien que les spécifications J2EE n'énoncent pas les mécanismes exacts d'une telle interaction, J2EE 1.4 ' L'adoption du profil de base WS-I, que Microsoft prétend également suivre, rendra probablement l'interaction J2EE-.Net commune.

Pour faciliter l'accès aux définitions WSDL, J2EE 1.4 ajoute la prise en charge de la norme JAXR (Java API for XML Registries). Les bibliothèques JAXR sont désormais une partie obligatoire du client d'application J2EE, des EJB (Enterprise JavaBeans) et des conteneurs Web (mais pas du conteneur d'applet). Étant donné que WS-I Basic Profile impose la prise en charge de UDDI (Universal Description, Discovery, and Integration) 2.0, les clients J2EE, ainsi que les composants et servlets EJB, peuvent interagir avec les registres de services Web publics. («Web Services Take Float with JAXR» ( JavaWorld, mai 2002) propose un didacticiel sur JAXR.) La figure 1 illustre les bibliothèques supplémentaires liées aux services Web prises en charge par J2EE 1.4.

En effet, J2EE considère qu'un service Web est une implémentation d'une ou plusieurs interfaces définies par un document WSDL. Les opérations décrites dans WSDL sont d'abord mappées aux méthodes Java en suivant les règles de mappage WSDL-Java de la spécification JAX-RPC. Une fois qu'une interface Java correspondant à un fichier WSDL est définie, vous pouvez implémenter les méthodes de cette interface de l'une des deux manières suivantes: en tant que bean session sans état s'exécutant dans le conteneur EJB ou en tant que classe Java s'exécutant dans le conteneur de servlet J2EE. Enfin, vous faites en sorte que le conteneur respectif écoute les demandes SOAP entrantes et mappez ces demandes à l'implémentation respective (EJB ou servlet). Pour traiter les appels SOAP entrants, J2EE 1.4 requiert le runtime JAX-RPC en tant que service de conteneur J2EE supplémentaire.

Conformément à l'architecture J2EE, le conteneur d'une implémentation de service médie l'accès à un service Web: si vous exposez un composant EJB ou un servlet en tant que service Web J2EE, les clients de votre service ne peuvent appeler ce service qu'indirectement, via le conteneur. Cela permet à une implémentation de service de bénéficier de la sécurité du conteneur, de la gestion des threads et même des garanties de qualité de service. En outre, les conteneurs vous permettent de prendre des décisions importantes sur les services Web, telles que les contraintes de sécurité, au moment du déploiement. Enfin, le modèle basé sur le conteneur de J2EE rend le déploiement de service Web portable: vous pouvez développer un service Web basé sur Java à l'aide de n'importe quel outil J2EE et vous attendre à ce que ce service s'exécute dans toute autre implémentation de conteneur conforme.

Un client de service Web, en revanche, ne se rend pas compte de la présence d'un conteneur de service Web. Au lieu de cela, le client voit un port représentant une instance de point de terminaison réseau d'un service Web. Ce point de terminaison suit le modèle d' interface de point de terminaison de service (SEI) JAX-RPC et fournit une implémentation de l'interface du service. Un client voit chaque service Web J2EE comme une combinaison SEI et port. Un seul conteneur J2EE peut héberger de nombreuses combinaisons de ce type, comme l'illustre la figure 2. Chaque combinaison SEI / port est une instance d'un service Web.

Notez que le client dans cette architecture peut être soit un client J2EE, s'exécutant à l'intérieur du conteneur client J2EE, soit un client non J2EE. Tout client conforme au profil de base WS-I peut utiliser un service Web J2EE, mais chaque client peut suivre des modèles de programmation différents. La spécification des services Web J2EE décrit un modèle de programmation pour les clients qui s'exécutent à l'intérieur du conteneur client d'application J2EE et un autre modèle (le modèle de programmation serveur) pour les implémentations de service Web qui s'exécutent dans les conteneurs EJB ou servlet.

Le modèle de programmation client du service Web J2EE

L'essence du modèle de programmation client de service Web est de rationaliser l'utilisation des API définies dans les JSR 67 (API Java pour la messagerie XML, JAXM), 93 (JAXR) et 101 (JAX-RPC), et de fournir un cadre complet pour en utilisant ces API ensemble dans le conteneur client J2EE.

Conformément au modèle de programmation client J2EE, un client de service Web est distant et offre une transparence locale / distante. Le fournisseur de port de service Web et le conteneur dans lequel le port s'exécute définissent la manière dont un client voit un service Web. Le client accède toujours au port et ne reçoit jamais une référence directe à l'implémentation d'un service Web. Un client de service Web J2EE ne sait pas comment un port fonctionne et ne doit se préoccuper que des méthodes définies par un port. Ces méthodes constituent l'interface publique d'un service Web. De plus, un client doit considérer l'accès à un port de service Web comme sans état lors des appels de service. En ce qui concerne le client, un port n'a pas d'identité unique - un client n'a aucun moyen de déterminer s'il communique avec des ports identiques à travers les appels de service.

Le client accède à un port en fonction de l'interface de service du port. Les services Web J2EE s'appuient sur JAX-RPC pour définir la relation entre un port et son interface de service. JAX-RPC crée cette relation en fonction des règles de traitement WSDL. Ainsi, la définition WSDL du service Web régit finalement le comportement du port. Basé sur la définition JAX-RPC, l'interface de service peut être soit une interface générique implémentant directement l' javax.xml.rpc.Serviceinterface, soit un «service généré», qui est un sous-type de cette interface. Ce dernier type d'interface est spécifique au type d'un service Web.

Dans le modèle de programmation J2EE, le client obtient une référence à l' Serviceobjet d'un service Web via une opération de recherche JNDI (Java Naming and Directory Interface). La recherche JNDI se produit par un nom logique, ou une référence de service, pour le service Web. Comme pour toutes les ressources basées sur un répertoire, un client doit déclarer les ressources dont il a besoin dans son descripteur de déploiement (plus d'informations à ce sujet plus tard).

La spécification des services Web Java (JSR 109) recommande que tous les services Web soient inclus dans le sous- servicecontexte JNDI . Le conteneur client lie l'interface de service décrite par cette référence sous le java:comp/envcontexte de dénomination de l'environnement client. En déclarant une référence de service dans le descripteur de déploiement du client, le conteneur client garantit que le service référencé est disponible dans les ressources compatibles JNDI. L'extrait de code suivant montre comment obtenir une référence à un service Web basé sur J2EE via une recherche JNDI:

InitialContext ctx = nouveau InitialContext (); Service myService = (Service) ctx.lookup ("java: comp / env / services / MyWebService");

Le code ci-dessus obtient un objet de service générique: un objet sans type spécifique. Un service généré par JAX-RPC est accédé de la même manière, cette fois en transposant le service au type d'interface du service Web spécifique:

InitialContext ctx = nouveau InitialContext (); MyWebService myService = (MyWebService) ctx.lookup ("java: / comp / env / services / MyWebService");

Notez que ce code suppose que la MyWebServiceréférence se lie à un objet qui implémente l' MyWebServiceinterface. Comme la liaison de service est facilitée au moment du déploiement d'un service Web, les outils J2EE sont censés garantir cette cohérence. Tous les serveurs d'applications compatibles J2EE 1.4 doivent prendre en charge la recherche de services basée sur JNDI.

Une fois qu'un client a obtenu l' Serviceobjet d' un service Web , il peut utiliser cet objet pour récupérer une javax.xml.rpc.Callinstance qui effectue l'appel de service réel. Le client dispose de trois options pour obtenir un Call: via un stub, un proxy de service dynamique ou une DII (Dynamic Invocation Interface). Je n'aborderai pas dans cet article les différences entre ces méthodes car, quelle que soit la façon dont un Callest créé, qui Callrenvoie directement au port du service - le seul objet dont le client doit être conscient lors de l'appel du service Web. Tous les conteneurs compatibles J2EE 1.4 doivent prendre en charge les Serviceméthodes d'interface, et ainsi permettre à un client d'obtenir une référence à un Callobjet pour un service Web et au port de ce service, via Call.

Notez que contrairement à l'utilisation de JAX-RPC en dehors de J2EE, un client ne doit pas utiliser la ServiceFactoryclasse JAX-RPC pour obtenir un nouveau service. Au lieu de cela, le client doit avoir accès au à Servicepartir d'une source JNDI, car la référence à un service récupéré à partir de JNDI aura tous les paramètres et configurations nécessaires pour appeler l'instance de service particulière. Du point de vue du client, cette différence est quelque peu analogue à la façon dont un client J2EE récupère un JDBC DataSourcevia l'interface JNDI pour accéder à une base de données, au lieu de configurer manuellement une Connectioninstance JDBC .

Avec cet Callobjet en place, le client suit la sémantique JAX-RPC de l'appel de procédure à distance. Par exemple, le client peut utiliser la invoke()méthode Callpour interagir avec le service Web. (Pour un exemple d'appel de service de style JAX-RPC, voir «J'aime votre type: décrire et appeler les services Web en fonction du type de service» ( JavaWorld, septembre 2002).)

Le modèle de programmation du serveur de service Web

Un service Web basé sur J2EE peut suivre l'une des deux implémentations possibles: Si le service est implémenté en tant que classe Java standard, il doit être conforme aux exigences du conteneur de servlet JAX-RPC. Ou, si le service est défini pour s'exécuter dans le conteneur EJB, il doit alors suivre le modèle de programmation requis pour les beans session EJB sans état. Quelle que soit la méthode d'implémentation, chaque conteneur fournit à l'implémentation du service Web la prise en charge du cycle de vie, la gestion de la concurrence et une infrastructure de sécurité.

La responsabilité principale du conteneur de serveur J2EE est de mapper et de distribuer les requêtes SOAP, dans le cas EJB, aux beans session sans état et, dans le cas du conteneur de servlet, aux méthodes des classes de points de terminaison de service JAX-RPC. Alors que la spécification JAX-RPC définit un modèle de programmation pour cette dernière option, les services Web J2EE JSR (JSR 109) présentent un modèle analogue pour les beans de session EJB sans état.