SOAP with Attachments API for Java bietet eine standardisierte Möglichkeit, XML-Dokumente von der Java-Plattform aus über das Internet zu versenden. ZDNet zeigt, wie es geht.
Sollen SOAP-Messaging-Anwendungen direkt geschrieben werden, lässt sich SAAJ anstatt JAX-WS[1] verwenden, einer allgemeineren Java-API zur Erstellung von Web-Services. Bei manchen Web-Services erweist sich SAAJ als nützlich, um direkt auf dieser niedrigeren Messaging-Ebene zu programmieren. SAAJ ermöglicht das Erstellen und den Versand von Nachrichten gemäß den Spezifikationen für SOAP 1.1 und 1.2 und den Aufzeichnungen zu SOAP with Attachments.
Will man beispielsweise einen Web-Service aufrufen, der ein Bestelldokument verwendet und einen Beleg herausgibt, lässt sich dieser Dokumentenaustausch ganz einfach als ein einzelner Nachrichtenaustausch mit Anfrage und Antwort konzipieren. Statt entfernte Methodenaufrufe durchzuführen, kann der Entwickler somit XML-Nachrichten erstellen, diese direkt an einen Web-Service senden und eine eventuelle XML-Antwort des Dienstes verarbeiten.
SAAJ bietet eine praktische Bibliothek für das Erstellen und Lesen von SOAP-Nachrichten. Außerdem können damit SOAP-Nachrichten über das Netzwerk versendet und empfangen werden. Die Spezifikation SAAJ 1.3[2] definiert das Paket javax.xml.soap. Es enthält die API zum Erstellen und Bestücken einer SOAP-Nachricht.
Warum werden Anhänge für SOAP benötigt?
SOAP-Nachrichten erfordern eine ganze Menge an Verarbeitungsleistung und Speicher. Alle Teile einer SOAP-Nachricht müssen den XML-Regeln in Bezug auf zulässige Zeichen und Zeichenfolgen entsprechen. Deshalb können Binärdaten nicht direkt eingeschlossen werden.
Außerdem parsen SOAP-Implementierungen gewöhnlich die gesamte Nachricht. Erst dann entscheiden sie, wie sie mit den Inhalten verfahren. Daher könnten große Datenfelder leicht den verfügbaren Speicherplatz übersteigen. Aus diesen Gründen benötigt SOAP ein Verfahren, um umfangreiche Nutz- und Binärdaten als Anhang anstatt innerhalb des Nachrichtenumschlags (Envelope) zu transportieren.
Das naheliegendste Verfahren hierfür ist das gleiche, das auch für Anhänge an E-Mail-Nachrichten eingesetzt wird: der mehrteilige MIME-Ansatz. Dabei wird eine Sammlung aus einzelnen Nachrichtenteilen anhand Header- und Trennzeichen identifiziert. Der erste Teil ist immer ein kompletter SOAP-Umschlag. Die nachfolgenden Teile hängen von der Anwendung ab. Die SAAJ-API verfügt über eine so genannte Node-Schnittstelle. Sie bildet die Basisklasse für alle Klassen und Schnittstellen, die XML-Elemente in einer SOAP-Nachricht darstellen.
Es gibt zwei primäre Arten von SOAP-Nachrichten: Nachrichten mit und ohne Anhänge. Stark vereinfacht sieht die Struktur einer SOAP-Nachricht folgendermaßen aus: SOAPPart enthält den SOAPEnvelope, worin wiederum (optional) der SOAPHeader und ein Textkörper enthalten sind. Folglich besitzen die grundlegenden Teile einer SOAP-Nachricht jeweils entsprechende Java-Klassen in SAAJ.
Die SAAJ-API liefert die SOAPMessage-Klasse zur Darstellung einer SOAP-Nachricht. Sie bietet die SOAPPart-Klasse zur Darstellung des SOAP-Teils und die SOAPEnvelope-Schnittstelle zur Darstellung des SOAP-Umschlags. Viele SAAJ-APIs erweitern DOM-Schnittstellen. In einer SAAJ-Nachricht ist die SOAPPart-Klasse auch ein DOM-Dokument.
Im Envelope-Element muss eine SOAP-Nachricht ein Body-Element besitzen, optional auch ein Header-Element. SAAJ bietet die Objekte SOAPBody und SOAPHeader zur Bearbeitung des Inhalts dieser Elemente. SAAJ stellt zwar das Verfahren zur Verfügung, aber die Inhalte der Objekte SOAPBody und SOAPHeader muss der Entwickler erstellen.
Ein SOAPMessage-Objekt kann eines oder mehrere zusätzliche AttachmentPart-Objekte enthalten, oder auch gar keines. Die MIME-Inhaltstypen sind beliebig, zum Beispiel ein XML-Dokument, eine Textdatei oder ein Bild. Wenn kein Anhang vorhanden ist, wird die Nachricht als reines XML-Dokument übertragen. Werden ein oder mehrere Anhänge hinzugefügt, löst dies automatisch eine Übertragung in Form einer Sammlung aus MIME-Teilen aus. Anhänge werden unter Verwendung der AttachmentPart-Klasse hinzugefügt, die eine Datenquelle (meist einen Input-Stream) und einen MIME-Inhaltstyp erfordert. Da die Java-Standardbibliothek zahlreiche Möglichkeiten zum Erstellen eines Input-Streams bietet, ist dieser Ansatz äußerst flexibel.
Die Abbildung unten zeigt die grundsätzliche Struktur einer SOAP-Nachricht mit zwei Anhängen. Die SAAJ-API stellt die AttachmentPart-Klasse bereit, um den Anhangsteil einer SOAP-Nachricht darzustellen. Ein SOAPMessage-Objekt umfasst automatisch ein SOAPPart-Objekt und seine erforderlichen Unterelemente. Allerdings muss der Entwickler diese selbst erstellen und hinzufügen, da AttachmentPart-Objekte optional sind.
![]() |
Als Erstes muss mithilfe eines MessageFactory-Objekts eine Nachricht erstellt werden. Die SAAJ-API bietet eine Standard-Implementierung der MessageFactory-Klasse, so dass problemlos eine Instanz erzeugt werden kann. Wenn man keine Argumente für die newInstance-Methode festlegt, erstellt diese eine Message-Factory für SOAP-1.1-Nachrichten. Um eine Message-Factory zu erstellen, die das Verarbeiten von SOAP-1.2-Nachrichten ermöglicht, wird der folgenden Methoden-Aufruf eingegeben:
MessageFactory factory = MessageFactory.newInstance (SOAPConstants.SOAP_1_2_PROTOCOL); SOAPMessage message = factory.createMessage();
Ruft man createMessage ohne Argumente auf, umfasst die automatisch erstellte Nachricht folgende Bestandteile: ein SOAPPart-Objekt, das ein SOAPEnvelope-Objekt enthält, welches wiederum ein leeres SOAPHeader-Objekt und ein leeres SOAPBody-Objekt aufweist.
Das SOAPHeader-Objekt ist optional, und man kann es löschen, wenn es nicht benötigt wird. Soll es beibehalten werden, muss es vor dem SOAPBody-Objekt stehen. Das SOAPBody-Objekt kann entweder den Inhalt der Nachricht enthalten oder eine Fehlermeldung, die Statusinformationen oder Details über ein Problem mit der Nachricht liefert.
Der nächste Schritt beim Erstellen einer Nachricht besteht im Zugriff auf ihre Teile, um Inhalte hinzufügen zu können:
SOAPHeader header = message.getSOAPHeader(); SOAPBody body = message.getSOAPBody();
Um Inhalte zum Textkörper hinzuzufügen, erstellt man normalerweise ein oder mehrere SOAPBodyElement-Objekte zur Aufnahme des Inhalts. Es lassen sich Unterelemente zu den SOAPBodyElement-Objekten erstellen, indem man die addChildElement-Methode benutzt. Für jedes Element oder Kind-Element werden dann Inhalte mithilfe der addTextNode-Methode hinzugefügt. Für jedes neue Element muss zur eindeutigen Identifizierung ein zugeordnetes javax.xml.namespace.QName-Objekt erstellt werden. QName-Objekte, die SOAPBodyElement- oder SOAPHeaderElement-Objekten zugeordnet werden, müssen voll qualifiziert sein.
Der folgende Code-Ausschnitt fragt den Textkörper des SOAPBody-Objekts aus der Nachricht ab, erstellt ein QName-Objekt für das zusätzliche Element und fügt ein neues SOAPBodyElement-Objekt zum Körper hinzu:
Um das neue Element mit Inhalten zu füllen, muss mittels der Methode addChildElement ein Kind-Element erstellt werden. Anschließend füllt man das Element mittels der Methode addTextNode mit Text. Der gesamte Vorgang wird wie das Erstellen von DOM-Dokumenten ausgeführt, was den Rahmen dieses Artikels allerdings sprengen würde. Weitere Informationen über das Erstellen von DOM-Dokumenten findet man bei den Java-XML-APIs (JAXP, JAX-RPC, JAXM und so weiter).
Ein AttachmentPart-Objekt kann jeden Inhaltstyp enthalten, auch XML. Da der SOAP-Teil nur XML enthalten darf, muss man also ein AttachmentPart-Objekt für jegliche Inhalte verwenden, die nicht im XML-Format vorliegen. Inhalte lassen sich mithilfe der AttachmentPart-Methode setContent dem Anhang hinzufügen. Diese Methode benötigt zwei Parameter: ein Java-Objekt für den Inhalt und ein String-Objekt für den MIME-Inhaltstyp, der zur Codierung des Objekts benutzt wird.
Inhalte im SOAPBody-Teil der Nachricht besitzen automatisch einen Content-Type-Header mit dem Wert "text/xml", da der Inhalt in XML sein muss. Dagegen muss der Inhaltstyp in einem AttachmentPart-Objekt angegeben werden, da ja jeder Typ möglich ist. Weitere Informationen über das Erstellen komplexerer Anhänge, etwa mit Binärdaten, finden sich unter SAAJ API JavaDocs[3]. Alle SOAP-Nachrichten werden über eine Verbindung gesendet und empfangen. SAAJ-API bildet die Verbindung durch ein SOAPConnection-Objekt ab, das vom Sender direkt an sein Ziel geht.
Der folgende Code-Ausschnitt erstellt die SOAPConnection-Objektverbindung. Nachdem die Nachricht erstellt und bestückt ist, wird die Objektverbindung zum Versenden der Nachricht genutzt. Wie bereits erwähnt, werden alle über ein SOAPConnection-Objekt laufenden Nachrichten mit der call-Methode gesendet, die die Nachricht sendet und blockiert, bis eine Antwort eingeht. Daher ist der Rückgabewert der call-Methode das SOAPMessage-Objekt, das die Antwort auf die gesendete Nachricht darstellt. Der Anfrageparameter ist die gesendete Nachricht selbst. Der Endpunkt steht für das Sendeziel.
Ein für den Versand von Anfrage-Antwort-Nachrichten implementierter Web-Service muss eine Antwort für jede Nachricht ausgeben, die er erhält. Die Antwort ist ein SOAPMessage-Objekt, ebenso wie die Anfrage. Die ersten Schritte zur Inhaltsabfrage einer Nachricht stimmen mit denen zum Einfügen von Inhalten überein. Um das SOAPBody-Objekt zu erhalten, wird das Message-Objekt benutzt. Alternativ lässt sich durch die SOAPPart- und SOAPEnvelope-Objekte auf das SOAPBody-Objekt zugreifen. Solange SOAPMessage die DOM-Struktur erbt, kann man das erhaltene XML-Dokument mit der DOM-API betrachten.
Wo gibt es SAAJ?
Die J2EE-Version 1.4 enthält die Version 1.2 von SAAJ. Sie verarbeitet nur SOAP-1.1-Nachrichten. Die neueste Enterprise Edition 5 enthält dagegen SAAJ in Version 1.3. Will man nicht die gesamte Enterprise Edition nutzen, findet sich auch in der neuesten Ausgabe des Java Web-Service-Entwickler-Pakets[4] eine Implementierung von SAAJ 1.3 mit kompletter Dokumentation und Beispielen. Das Open-Source-Projekt GlassFish[5] enthält ebenfalls SAAJ 1.3.
Weitere Quellen für SAAJ:
- SAAJ Standard Implementation Project[6]
- Java-Web-Service-Anleitung[7]
- Metro Web Service Stack Implementation[8]
URLs in diesem Artikel:
[1] = http:/
[2] = https:/
[3] = https:/
[4] = http:/
[5] = https:/
[6] = https:/
[7] = http:/
[8] = https:/
