SAAJ: Keine Bedingungen

Zum Zeitpunkt dieses Schreibens bestehen die meisten Webdienste aus einem einfachen Nachrichtenaustausch: Ein Client kontaktiert einen Webdienst und sendet eine Nachricht an diesen Dienst. Der Webdienst verarbeitet diese Anforderung wiederum und sendet dann eine Antwort an den Client zurück. Dieses einfache Anforderungs- / Antwortmuster modelliert die Art und Weise, wie das HTTP-Protokoll Client / Webserver-Interaktionen erleichtert. Wie bei HTTP muss der Austausch von Webdienstnachrichten häufig binären Inhalt enthalten, z. B. Bilder, Dokumente oder Soundclips. In diesem Artikel wird das Senden und Empfangen von binären Webdienstinhalten mithilfe von SOAP (Simple Object Access Protocol) mit der Anhangs-API für Java (SAAJ) 1.2 vorgestellt.

Bevor Sie sich mit den Feinheiten der Übertragung von binären Webdienstinhalten befassen, sollten Sie darauf hinweisen, dass ein einfacher Webdienst im Anforderungs- / Antwortstil im Gegensatz zu Diensten steht, die die Client / Server-Interaktion als Remoteprozeduraufrufe oder RPCs gestalten. In einem RPC stellt ein Server eine Schnittstelle bereit, die einer API ähnelt. Ein Client ruft wiederum einen solchen Dienst auf, indem er Remote-Aufrufe über die API des Dienstes ausführt, die erforderlichen Parameter übergibt und die vom Aufruf erzeugten Werte empfängt.

XML-basierter RPC ähnelt der Art und Weise, wie Sie Objekte in einem objektorientierten System (OO) aufrufen. Wenn Sie mit der Java-API für XML-basierten RPC (JAX-RPC) arbeiten, werden Sie selten darauf aufmerksam, dass Sie mit XML-Dokumenten arbeiten, nicht mit Java-Objekten. Mit JAX-RPC können Sie sich Webdienste als Remote-Objekte vorstellen, ähnlich wie Sie es mit Java RMI (Remote Method Invocation) tun würden. Die JAX-RPC-Laufzeit übersetzt die übergeordneten OO-Methodenaufrufe in die vom Remote-Webdienst erwarteten XML-Dokumente. Während Webdienste im RPC-Stil häufig ein bequemeres Programmiermodell bieten, müssen RPC-Aufrufe auch auf einer untergeordneten Nachrichtenebene basieren, um die XML-Nachrichten auszutauschen, aus denen der Remote-Aufruf besteht.

Bei einigen Webdiensten ist es häufig nützlich, direkt auf diese untergeordnete Messaging-Ebene zu programmieren. Wenn Sie beispielsweise einen Webdienst aufrufen möchten, der ein Bestelldokument verwendet und eine Quittung zurücksendet, können Sie diesen Dokumentenaustausch problemlos als einzelnen Austausch von Anforderungs- / Antwortnachrichten modellieren. Anstatt Remote-Methodenaufrufe durchzuführen, würden Sie XML-Nachrichten erstellen, diese Nachrichten direkt an einen Webdienst senden und die XML-Antwort des Dienstes verarbeiten, falls vorhanden. Da SOAP das allgemeine Nachrichtenformat für Webdienstnachrichten definiert, müssten Sie SOAP-konforme Nachrichten erstellen und diese SOAP-Antwortnachrichten, sobald der Dienst antwortet, wieder in ein Format analysieren, das Ihr Programm versteht.

SAAJ bietet eine praktische Bibliothek zum Erstellen und Lesen von SOAP-Nachrichten sowie das Senden und Empfangen von SOAP-Nachrichten über das Netzwerk. SAAJ definiert den Namespace javax.xml.soap. Die Klassen in diesem Paket waren ursprünglich Teil der Java-API für XML-Messaging (JAXM), wurden jedoch kürzlich in eine eigene API unterteilt. JAXM verwendet SAAJ für die Erstellung und Bearbeitung von SOAP-Nachrichten und fügt die Zuverlässigkeit von Nachrichten und andere Funktionen hinzu, die für XML-Nachrichten spezifisch sind. Während SAAJ eine erforderliche Komponente von J2EE (Java 2 Platform, Enterprise Edition) 1.4 ist, ist dies bei JAXM nicht der Fall. Dieser Artikel konzentriert sich auf einen der nützlichsten Aspekte von SAAJ: die Möglichkeit, binären Inhalt an eine SOAP-Nachricht anzuhängen.

Die Vorteile von Anhängen

Während sich das SOAP-Designcenter auf die Kapselung von XML-Dokumenten in einer Nachricht konzentriert, erweitert die Anhangsfunktion von SOAP eine SOAP-Nachricht, um zusätzlich zum regulären SOAP-Teil null oder mehr Anhänge aufzunehmen, wie in Abbildung 1 dargestellt. Jeder Anhang wird durch einen MIME-Typ definiert und kann jeden Inhalt annehmen, der als Bytestream dargestellt wird.

Die Anhangsfunktion von SOAP erweist sich als am nützlichsten, wenn ein Client Binärdaten wie Bild- oder Audiodaten an einen Webdienst übertragen möchte. Ohne SOAP-Anhänge wäre das Senden von Binärdaten schwieriger. Beispielsweise könnte die SOAP-Nachricht eines Clients die URL-Adresse der Binärdatei übermitteln. Der Client müsste dann einen HTTP-Server betreiben, damit der Webdienst diese Datei abrufen kann. Dies würde eine unangemessene Belastung für jeden Webdienst-Client darstellen, insbesondere für Clients, die auf Geräten mit begrenzten Ressourcen wie Digitalkameras oder Scannern ausgeführt werden. Mit der Anhangsfunktion von SOAP kann jeder Webdienst-Client, der SOAP-Nachrichten übertragen kann, Binärdateien direkt in eine SOAP-Nachricht einbetten.

So erweisen sich beispielsweise SOAP-Anhänge bei der Interaktion mit Portal-Websites als nützlich. Stellen Sie sich ein Immobilienagenturnetzwerk vor, das Beschreibungen und Fotos von zum Verkauf stehenden Häusern an ein zentrales Immobiliensuchportal verteilen muss. Wenn das Portal ein Servlet betreibt, mit dem SOAP-Nachrichten mit Anhängen gesendet werden können, kann eine Immobilienagentur ihre Einträge mit einigen SOAP-Nachrichten aktualisieren, einschließlich Fotos dieser Häuser. Der SOAP-Nachrichtentext kann die Eigenschaftsbeschreibung einbetten, und SOAP-Anhänge können die Bilddateien enthalten. Wenn in diesem Szenario das Servlet eines Portalbetreibers eine solche Nachricht empfängt, wird ein Bestätigungsdokument zurückgegeben, das die Verfügbarkeit des Posts auf dem Portal angibt. Abbildung 2 zeigt einen solchen Webdienst.

Die Anatomie von SOAP mit Anhängen Nachricht

Der Hinweis zu SOAP-Nachrichten mit Anhängen W3C (World Wide Web Consortium) (siehe Ressourcen) fügt SOAP keine neuen Funktionen hinzu. Vielmehr wird definiert, wie MIME-Typen in einer SOAP-Nachricht zum Definieren von Anhängen genutzt werden und wie diese Anhänge aus dem SOAP-Text heraus referenziert werden.

Der MIME-Typ multipart/relateddefiniert Dokumente, die aus mehreren verwandten Teilen bestehen. SOAP-Nachrichten mit Anhängen müssen dem multipart/relatedMIME-Typ folgen . Das folgende Beispiel zeigt eine multipart/relatedan das HTTP-Protokoll gebundene SOAP-Nachricht mit zwei Anhängen:

POST / propertyListing HTTP / 1.1 Host: www.realproperties.com Inhaltstyp: Multipart / Related; border = MIME_boundary; Typ = Text / XML; Inhaltslänge: NNNN --MIME_boundary Inhaltstyp: text / xml; Zeichensatz = UTF-8-Inhaltsübertragungscodierung: 8-Bit-Inhalts-ID: Really Nice Homes, Inc. Hinzufügen 1234 Main St Pleasantville CA 94323 250000 --MIME_boundary Inhaltstyp: image / jpeg Inhalts-ID: .... JPEG-DATEN ..... --MIME_boundary Inhaltstyp: image / jpeg Inhalts-ID: .... JPEG DATA ..... --MIME_boundary--

Die obige mehrteilige Nachricht umfasst eine Reihe von MIME-Headern und zugehörigen Daten. Im Stammverzeichnis des Dokuments befindet sich der SOAP-Body. Da der SOAP-Body nur XML-Daten enthält, lautet der MIME-Typ der gesamten Nachricht text/xml. Dem SOAP-Umschlag folgen zwei Anhänge, die jeweils einer Bilddatei entsprechen, die zusammen mit der Nachricht gesendet wird.

Eine Inhalts-ID identifiziert jeden Anhang. Mit dem W3C-Hinweis kann entweder eine Inhalts-ID oder ein Inhaltsspeicherort auf die Anhänge verweisen, der erstere wird jedoch bevorzugt. Solche Inhalts-IDs dienen als URI-Verweise (Uniform Resource Identifier) ​​auf Anhänge. Die SOAP 1.1-Codierungsregeln definieren, wie auf eine Ressource in einer SOAP-Nachricht über einen URI verwiesen wird, der auf jeden Inhalt verweisen kann, nicht nur auf XML (siehe Abschnitt 5 von SOAP 1.1 unter Ressourcen). Ein SOAP-Prozessor löst diese URI-Referenzen auf, während er die Nachricht verarbeitet. Basierend auf dem obigen Beispiel ordnet der SOAP-Prozessor das Element frontImagedem Datenabschnitt mit der Inhalts-ID [email protected]in der SOAP-Nachricht zu.

Erstellen und senden Sie eine SOAP-Nachricht mit Anhängen

Mit SAAJ können Sie jeden Teil einer SOAP-Nachricht erstellen und bearbeiten, einschließlich Anhänge. Der größte Teil von SAAJ basiert auf abstrakten Klassen und Schnittstellen, sodass jeder Anbieter SAAJ in seinen eigenen Produkten implementieren kann. Die Referenzimplementierung von Sun Microsystems wird mit dem Java Web Services Developer Pack (JWSDP) geliefert.

Da SOAP-Nachrichten nur eine spezielle Form von XML-Dokumenten darstellen, baut JAAS auf der DOM-API (Document Object Model) für die XML-Verarbeitung auf. Die meisten SOAP-Nachrichtenkomponenten stammen von der javax.xml.soap.NodeSchnittstelle ab, die wiederum eine org.w3c.dom.NodeUnterklasse ist. SAAJ-Unterklassen Nodezum Hinzufügen von SOAP-spezifischen Konstrukten. Zum Beispiel kann eine spezielle Node, SOAPElementstellt eine SOAP - Nachricht - Element.

Ein direktes Ergebnis der Abhängigkeit von SAAJ von Schnittstellen und abstrakten Klassen ist, dass Sie die meisten SOAP-bezogenen Aufgaben über Factory-Methoden ausführen. Um Ihre Anwendung mit der SAAJ-API zu verbinden, erstellen Sie zunächst eine SOAPConnectionaus a SOAPConnectionFactory. Zum Erstellen und Bearbeiten von SOAP-Nachrichten können Sie auch a MessageFactoryund a initialisieren SOAPFactory. MessageFactoryMit dieser Option können Sie SOAP-Nachrichten erstellen und SOAPFactorydie Methoden zum Erstellen einzelner Teile einer SOAP-Nachricht bereitstellen:

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

Mit diesen Tools können Sie eine SOAP-Nachricht erstellen, die ein Kunde einer Immobilienagentur verwenden würde, um ein Listenupdate an eine Portal-Website zu senden.

SAAJ bietet verschiedene Möglichkeiten, um eine neue SOAP-Nachricht zu erstellen. Das folgende Beispiel zeigt die einfachste Methode, mit der eine leere SOAP-Nachricht mit einem Umschlag sowie einem Header und einem Text in diesem Umschlag erstellt wird. Da Sie in dieser Nachricht keinen SOAP-Header benötigen, können Sie dieses Element aus der Nachricht entfernen:

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

Das Hinzufügen der XML-Struktur zum Nachrichtentext ist unkompliziert:

SOAPBody body = message.getSOAPBody (); Name listingElementName = soapFactory.createName ("propertyListing", "realProperty", "//schemas.realhouses.com/listingSubmission"); SOAPBodyElement ListingElement = body.addBodyElement (ListingElementName); Name attname = soapFactory.createName ("id"); ListingElement.addAttribute (attname, "property_1234"); SOAPElement ListingAgency = ListingElement.addChildElement ("ListingAgency"); ListingAgency.addTextNode ("Really Nice Homes, Inc"); SOAPElement ListingType = ListingElement.addChildElement ("ListingType"); listingType.addTextNode ("add"); SOAPElement propertyAddress = ListingElement.addChildElement ("propertyAddress"); SOAPElement street = propertyAddress.addChildElement ("Straße"); 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");

Beachten Sie, dass Sie dem propertyListingElement die eindeutige ID der Eigenschaft als Attribut hinzufügen . Außerdem qualifizieren Sie das propertyListingElement mit einem QNameoder einem Namespace-fähigen Namen.

Sie können der SOAP-Nachricht auf verschiedene Arten Anhänge hinzufügen. In diesem Beispiel erstellen Sie zunächst Elemente, um die Front- und Innenbilder der aufgelisteten Eigenschaft zu kennzeichnen. Jedes hat ein hrefAttribut, das die Inhalts-ID des Anhangs angibt:

String frontImageID = "[email protected]"; SOAPElement frontImRef = ListingElement.addChildElement ("frontImage"); Name hrefAttName = soapFactory.createName ("href"); frontImRef.addAttribute (hrefAttName, frontImageID); String interiorID = "[email protected]"; SOAPElement interiorImRef = ListingElement.addChildElement ("interiorImage"); interiorImRef.addAttribute (hrefAttName, interiorID);

Verwenden Sie ein javax.activation.DataHandlerObjekt aus dem JavaBeans Activation Framework, um die erforderlichen Bilddateien einfach an die Nachricht anzuhängen . DataHandlerkann den an ihn übergebenen Datentyp automatisch erkennen und dem Anhang daher automatisch den entsprechenden MIME-Inhaltstyp zuweisen:

URL url = neue URL ("Datei: ///export/files/pic1.jpg"); DataHandler dataHandler = neuer DataHandler (URL); AttachmentPart att = message.createAttachmentPart (dataHandler); att.setContentId (frontImageID); message.addAttachmentPart (att);

Alternativ können Sie möglicherweise einen Objectzusammen mit dem richtigen MIME-Typ an übergeben createAttachmentPart(). Diese Methode ähnelt der ersten. Intern wird die SAAJ-Implementierung wahrscheinlich nach einem suchen DataContentHandler, um den angegebenen MIME-Typ zu verarbeiten. Wenn es keinen geeigneten Handler findet, createAttachmentPart()wird ein IllegalArgumentException:

URL url2 = neue URL ("Datei: ///export/files/pic2.jpg"); Image im = Toolkit.getDefaultToolkit (). CreateImage (url2); AttachmentPart att2 = message.createAttachmentPart (im, "image / jpeg"); att2.setContentId (interiorID); message.addAttachmentPart (att2);