SAAJ: sans condition

Au moment d'écrire ces lignes, la plupart des services Web consistent en de simples échanges de messages: un client contacte un service Web et envoie un message à ce service. Le service Web, à son tour, traite cette demande, puis renvoie une réponse au client. Ce modèle simple de requête / réponse modélise la manière dont le protocole HTTP facilite les interactions client / serveur Web. Comme avec HTTP, les échanges de messages de service Web doivent souvent inclure un contenu binaire, tel que des images, des documents ou des clips audio. Cet article présente l'envoi et la réception de contenu de service Web binaire à l'aide de SOAP (Simple Object Access Protocol) avec Attachments API for Java (SAAJ) 1.2.

Avant de plonger dans les subtilités du transfert de contenu de service Web binaire, il convient de souligner qu'un simple service Web de type requête / réponse contraste avec les services qui façonnent l'interaction client / serveur sous forme d'appels de procédure à distance, ou RPC. Dans un RPC, un serveur expose une interface qui ressemble à une API. À son tour, un client appelle un tel service en effectuant des appels à distance sur l'API du service, en passant les paramètres requis et en recevant les valeurs produites par l'appel.

Le RPC basé sur XML ressemble à la façon dont vous appelez des objets dans un système orienté objet (OO). En effet, lorsque vous travaillez avec l'API Java pour RPC basé sur XML (JAX-RPC), vous vous rendez rarement compte que vous travaillez avec des documents XML, pas des objets Java. JAX-RPC vous permet de considérer les services Web comme des objets distants, comme vous le feriez avec Java RMI (Remote Method Invocation). Le runtime JAX-RPC traduit les appels de méthode OO de haut niveau en documents XML attendus par le service Web distant. Alors que les services Web de style RPC fournissent souvent un modèle de programmation plus pratique, les appels RPC doivent également s'appuyer sur une couche de messagerie de niveau inférieur pour échanger les messages XML qui composent l'appel distant.

Pour certains services Web, il est souvent utile de programmer directement sur cette couche de messagerie de niveau inférieur. Par exemple, si vous souhaitez appeler un service Web qui consomme un document de bon de commande et renvoie un accusé de réception, vous pouvez facilement modéliser cet échange de documents comme un échange de message de demande / réponse unique. Au lieu de faire des appels de méthode à distance, vous construisez des messages XML, envoyez ces messages directement à un service Web et traitez la réponse XML du service, le cas échéant. Puisque SOAP définit le format de message commun pour les messages de service Web, vous devez créer des messages conformes à SOAP et, une fois que le service répond, analyser ces messages de réponse SOAP dans un format que votre programme comprend.

SAAJ fournit une bibliothèque pratique pour construire et lire des messages SOAP, et vous permet également d'envoyer et de recevoir des messages SOAP sur le réseau. SAAJ définit l'espace de noms javax.xml.soap. Les classes qui résident dans ce package faisaient initialement partie de l'API Java pour la messagerie XML (JAXM), mais ont été récemment séparées en leur propre API. JAXM s'appuie sur SAAJ pour la construction et la manipulation des messages SOAP, et ajoute la fiabilité des messages et d'autres fonctionnalités spécifiques à la messagerie XML. Alors que SAAJ est un composant obligatoire de J2EE (Java 2 Platform, Enterprise Edition) 1.4, JAXM ne l'est pas. Cet article se concentre sur l'un des aspects les plus utiles de SAAJ: la possibilité de joindre du contenu binaire à un message SOAP.

Les avantages des pièces jointes

Alors que le centre de conception de SOAP se concentre sur l'encapsulation de documents XML dans un message, la fonction de pièce jointe de SOAP étend un message SOAP pour inclure, en plus de la partie SOAP standard, zéro ou plusieurs pièces jointes, comme le montre la figure 1. Chaque pièce jointe est définie par un type MIME et peut prendre tout contenu représenté sous forme de flux d'octets.

La fonction de pièce jointe de SOAP s'avère particulièrement utile lorsqu'un client souhaite transmettre des données binaires, telles qu'une image ou des données audio, à un service Web. Sans pièces jointes SOAP, l'envoi d'un morceau de données binaires s'avérerait plus difficile. Par exemple, le message SOAP d'un client peut transmettre l'adresse URL du fichier binaire. Le client devra alors exploiter un serveur HTTP pour permettre au service Web de récupérer ce fichier. Cela représenterait un fardeau excessif pour tout client de service Web, en particulier pour les clients fonctionnant sur des appareils à ressources limitées tels que des appareils photo numériques ou des scanners. La capacité de pièce jointe de SOAP permet à tout client de service Web capable de transmettre des messages SOAP d'incorporer des fichiers binaires directement dans un message SOAP.

Les pièces jointes SOAP, par exemple, s'avèrent utiles lors de l'interaction avec les sites Web du portail. Prenons l'exemple d'un réseau d'agences immobilières qui a besoin de diffuser des descriptions et des photographies de maisons à vendre sur un portail de recherche immobilière centralisé. Si le portail exploite un servlet permettant la publication de messages SOAP avec des pièces jointes, une agence immobilière pourrait mettre à jour ses listes avec quelques messages SOAP, y compris des photos de ces maisons. Le corps du message SOAP peut intégrer la description de la propriété et les pièces jointes SOAP peuvent contenir les fichiers image. Dans ce scénario, lorsqu'un servlet d'un opérateur de portail reçoit un tel message, il renvoie un document d'accusé de réception, indiquant la disponibilité de la publication sur le portail. La figure 2 illustre un tel service Web.

L'anatomie de SOAP avec le message des pièces jointes

Les messages SOAP avec pièces jointes W3C (World Wide Web Consortium) Remarque (voir Ressources) n'ajoute pas de nouvelles fonctionnalités à SOAP. Il définit plutôt comment tirer parti des types MIME dans un message SOAP pour définir les pièces jointes, et comment référencer ces pièces jointes à partir du corps SOAP.

Le type MIME multipart/relateddéfinit des documents composés de plusieurs parties liées. Les messages SOAP avec pièces jointes doivent suivre le multipart/relatedtype MIME. L'exemple ci-dessous montre un multipart/relatedmessage SOAP, lié au protocole HTTP, avec deux pièces jointes:

POST / propertyListing Hôte HTTP / 1.1: www.realproperties.com Content-Type: Multipart / Related; limite = limite_MIME; type = texte / xml; Content-Length: NNNN --MIME_boundary Content-Type: texte / xml; charset = UTF-8 Content-Transfer-Encoding: 8bit Content-ID: Really Nice Homes, Inc. Ajouter 1234 Main St Pleasantville CA 94323 250000 --MIME_boundary Content-Type: image / jpeg Content-ID: .... JPEG DATA ..... --MIME_boundary Content-Type: image / jpeg Content-ID: .... JPEG DATA ..... --MIME_boundary--

Le message en plusieurs parties ci-dessus comprend une série d'en-têtes MIME et des données associées. À la racine du document se trouve le corps SOAP. Étant donné que le corps SOAP ne contient que des données XML, le type MIME du message entier est text/xml. À la suite de l'enveloppe SOAP se trouvent deux pièces jointes, chacune correspondant à un fichier image envoyé avec le message.

Un ID de contenu identifie chaque pièce jointe. La note W3C permet à un ID de contenu ou à un emplacement de contenu de référencer les pièces jointes, mais elle donne la préférence au premier. Ces ID de contenu agissent comme des références URI (Uniform Resource Identifier) ​​aux pièces jointes; les règles de codage SOAP 1.1 définissent comment référencer une ressource dans un message SOAP via un URI qui peut référencer n'importe quel contenu, pas seulement XML (voir la section 5 de SOAP 1.1 dans Ressources). Un processeur SOAP résout ces références URI pendant qu'il traite le message. Sur la base de l'exemple ci-dessus, le processeur SOAP associe l'élément frontImageà la section de données avec Content ID [email protected]dans le message SOAP.

Créer et envoyer un message SOAP avec des pièces jointes

SAAJ vous permet de créer et de modifier n'importe quelle partie d'un message SOAP, y compris les pièces jointes. La plupart des SAAJ sont basés sur des classes abstraites et des interfaces telles que chaque fournisseur peut implémenter SAAJ dans ses propres produits. L'implémentation de référence de Sun Microsystems est fournie avec le Java Web Services Developer Pack (JWSDP).

Les messages SOAP ne représentant qu'une forme particulière de documents XML, JAAS s'appuie sur l'API DOM (Document Object Model) pour le traitement XML. La plupart des composants de message SOAP descendent de l' javax.xml.soap.Nodeinterface, qui, à son tour, est une org.w3c.dom.Nodesous - classe. Sous-classes SAAJ Nodepour ajouter des constructions spécifiques à SOAP. Par exemple, un particulier Node, SOAPElementreprésente un élément de message SOAP.

Un résultat direct de la dépendance de SAAJ sur les interfaces et les classes abstraites est que vous accomplissez la plupart des tâches liées à SOAP via des méthodes d'usine. Pour connecter votre application à l'API SAAJ, vous créez d'abord un fichier à SOAPConnectionpartir d'un fichier SOAPConnectionFactory. Pour créer et modifier des messages SOAP, vous pouvez également initialiser a MessageFactoryet a SOAPFactory. MessageFactoryvous permet de créer des messages SOAP et SOAPFactoryfournit les méthodes pour créer des parties individuelles d'un message SOAP:

SOAPConnectionFactory spConFactory = SOAPConnectionFactory.newInstance (); SOAPConnection con = spConFactory.createConnection (); SOAPFactory soapFactory = SOAPFactory.newInstance ();

Avec ces outils en place, vous pouvez créer un message SOAP qu'un client d'une agence immobilière utiliserait pour envoyer une mise à jour de liste à un site Web portail.

SAAJ propose plusieurs façons de créer un nouveau message SOAP. L'exemple suivant montre la méthode la plus simple qui crée un message SOAP vide avec une enveloppe, un en-tête et un corps dans cette enveloppe. Puisque vous n'avez pas besoin d'un en-tête SOAP dans ce message, vous pouvez supprimer cet élément du message:

SOAPMessage message = factory.createMessage (); SOAPHeader header = message.getSOAPHeader (); header.detachNode ();

L'ajout de la structure XML au corps du message s'avère simple:

SOAPBody body = message.getSOAPBody (); Nom listingElementName = soapFactory.createName ("propertyListing", "realProperty", "//schemas.realhouses.com/listingSubmission"); SOAPBodyElement listingElement = body.addBodyElement (listingElementName); Nom attname = soapFactory.createName ("id"); listingElement.addAttribute (attname, "propriété_1234"); SOAPElement listingAgency = listingElement.addChildElement ("listingAgency"); listingAgency.addTextNode ("Really Nice Homes, Inc"); SOAPElement listingType = listingElement.addChildElement ("listingType"); listingType.addTextNode ("ajouter"); SOAPElement propertyAddress = listingElement.addChildElement ("propertyAddress"); SOAPElement street = propertyAddress.addChildElement ("rue"); street.addTextNode ("1234 Main St "); SOAPElement city = propertyAddress.addChildElement (" city "); city.addTextNode (" Pleasantville "); SOAPElement state = propertyAddress.addChildElement (" state "); state.addTextNode (" CA "); SOAPElement zip = propertyAddress.addChildElement ("zip"); zip.addTextNode ("94521"); SOAPElement listPrice = listingElement.addChildElement ("listPrice"); listPrice.addTextNode ("25000");addChildElement ("listPrice"); listPrice.addTextNode ("25000");addChildElement ("listPrice"); listPrice.addTextNode ("25000");

Notez que vous ajoutez l'ID unique de la propriété en tant qu'attribut à l' propertyListingélément. En outre, vous qualifiez l' propertyListingélément avec un QNamenom ou prenant en charge l'espace de noms.

Vous pouvez ajouter des pièces jointes au message SOAP de plusieurs manières. Dans cet exemple, vous créez d'abord des éléments pour désigner les images avant et intérieure de la propriété répertoriée. Chacun a un hrefattribut désignant l'ID de contenu de la pièce jointe:

String frontImageID = "propriété[email protected]"; SOAPElement frontImRef = listingElement.addChildElement ("frontImage"); Nom hrefAttName = soapFactory.createName ("href"); frontImRef.addAttribute (hrefAttName, frontImageID); String interiorID = "[email protected]"; SOAPElement interiorImRef = listingElement.addChildElement ("interiorImage"); interiorImRef.addAttribute (hrefAttName, ID intérieur);

Pour joindre facilement les fichiers image requis au message, utilisez un javax.activation.DataHandlerobjet de JavaBeans Activation Framework. DataHandlerpeut détecter automatiquement le type de données qui lui est passé, et il peut donc attribuer automatiquement le type de contenu MIME approprié à la pièce jointe:

URL url = nouvelle URL ("fichier: ///export/files/pic1.jpg"); DataHandler dataHandler = nouveau DataHandler (url); AttachmentPart att = message.createAttachmentPart (dataHandler); att.setContentId (frontImageID); message.addAttachmentPart (att);

Sinon, vous pourrez peut-être passer un Object, avec le type MIME correct, à createAttachmentPart(). Cette méthode ressemble à la première. En interne, l'implémentation SAAJ recherchera probablement un DataContentHandlerpour gérer le type MIME spécifié. S'il ne trouve pas de gestionnaire approprié, createAttachmentPart()lancera un IllegalArgumentException:

URL url2 = nouvelle URL ("fichier: ///export/files/pic2.jpg"); Image im = Toolkit.getDefaultToolkit (). CreateImage (url2); AttachmentPart att2 = message.createAttachmentPart (im, "image / jpeg"); att2.setContentId (ID intérieur); message.addAttachmentPart (att2);