JAXM – Java API for XML Messaging Ein Referat von Daniel Kalkowski Felix Knecht Berno Löwer Matthias Maschke Christian Saga Gliederung - - Einleitung o Konzept o Unterschiede der Nachrichtenarten o Standalone vs. Provider o JAX-RPC vs. JAXM Aufbau von SOAP-Nachrichten API für das Erstellen von SOAP-Nachrichten API für das Versenden von SOAP-Nachrichten o Mit Provider o Standalone o Exception-Klasse JAXM – Das Konzept Bei JAXM geht es um den Austausch von Standarddokumenten. Für JAXM werden zwei Packages benötigt. Zum einen gibt es das Package javax.xml.soap. Dieses Package dient zum erstellen von SOAP-Nachrichten mit und ohne Attachments. Außerdem stellt dieses Package Profile bereit. Profile sind auf SOAP aufbauende Protokolle wie zum Beispiel ebXML. Zum anderen gibt es das javax.xml.messaging Packages, welches für den Aufbau von Verbindungen und das Versenden der SOAP-Nachrichten über diese Verbindungen zuständig ist. Es baut auf SAAJ 1.1 (SOAP with Attachments API) auf. JAXM – Konzeptmodell JAXM ist eine leichtgewichtige MessagingAPI zur Entwicklung von XML basierten Business-Applikationen. Diese Applikationen dienen überwiegend zum Austausch von elektronischen Geschäftsdokumenten zwischen Unternehmen. Die Austausch-Szenarios, die auf JAXM basieren, sind immer Dokumenten- zentriert und fallen in fünf große Kategorien, die in den folgenden Abschnitten beschrieben werden. Fire And Forget Bei dieser Übertragungsmethode versendet der Sender die Nachricht an den Empfänger ohne danach auf eine Antwort oder eine Bestätigung zu warten. Der Sender kann also direkt nach dem Versenden der Nachricht weiterarbeiten. Diese Übertragungsmethode ist relativ unsicher, da für den Sender nicht sichergestellt ist, dass die Nachricht korrekt übertragen und verarbeitet wurde. Synchrones Update Bei dieser Übertragungsmethode versendet der Sender eine Nachricht an den Empfänger und wartet auf eine Bestätigung der Nachricht durch den Empfänger. Der Sender kann also in der Zeit zwischen Versand der Nachricht und dem Empfang der Bestätigung keine anderen Aufgaben wahrnehmen. Er blockiert. Eine korrekte Übertragung der Daten und eine Bearbeitung kann dadurch für den Sender sichergestellt werden, da er eine Bestätigung erhält. Synchrone Anfrage Bei dieser Übertragungsmethode sendet der Sender eine Nachricht an den Empfänger und erhält nach Verarbeitung der Nachricht durch den Empfänger eine vollwertige Antwort zurück (im Gegensatz zur einfachen Bestätigung wie beim Synchronen Update). Diese Antwortnachricht muss nicht direkt mit der gesendeten Anfrage zu tun haben. Asynchrones Update mit Bestätigung Bei dieser Übertragungsmethode kann der Sender nach dem Versand der Nachricht weiterarbeiten während der Empfänger die Nachricht bearbeitet. Wenn der Empfänger fertig ist, sendet er eine einfache Bestätigung an den Sender, die dieser dann verarbeiten kann. Asynchrone Anforderung Bei dieser Übertragungsmethode kann der Sender wie beim asynchronen Update mit Bestätigung nach dem Versand der Nachricht weiterarbeiten während der Empfänger die Nachricht bearbeitet. Wenn der Empfänger fertig ist, sendet er eine vollwertige Nachricht an den Sender, die dieser dann verarbeiten kann. Diese Antwortnachricht kann auch mehrere Tage nach dem Versand der Anfrage versendet werden und muss keinen direkten Bezug zu der gesendeten Anfrage haben. SOAP vs. JAXM Clients Im Standalone- Betrieb kommuniziert der Sender direkt mit dem Empfänger. Er versendet seine Nachrichten direkt an den Empfänger und erhält von diesem direkt eine Antwort. In Verbindung mit einem Message-Provider kann der Sender die Nachricht seinem Provider übergeben, der sie dann an den Provider des Empfängers übergibt. Dieser übergibt die Nachricht dann an den Empfänger. Der Empfänger über gibt seine Antwortnachricht an seinen Provider, der sie dann an den Provider des Senders übergibt. Dieser leitet sie dann an den Sender weiter. Dieses Verfahren hat den Vorteil, dass weder der Sender noch der Empfänger permanent laufen bzw. empfangsbereit sein müssen. Sie erhalten die für sie bestimmten Nachrichten von ihrem Provider, wenn sie dazu bereit sind. Dieses Verfahren entspricht in seiner Vorgehensweise dem Versand und Empfang von e-Mails über SMTP und POP3. Provider Ein JAXM-Provider ist ein Programm, das entweder auf dem gleichen oder auf einem anderen Rechner als der Client läuft. Dieses Programm versendet und Empfängt Nachrichten für den Client. Dies bedeutet, dass Nachrichten, die eintreffen währende der Client nicht läuft, nicht verloren gehen. Sie werden beim Provider gespeichert, bis der Client wieder läuft bzw. eine Verbindung zum Provider aufgebaut hat und sie abholt. Der Provider kümmert sich beim Versand der Nachrichten auch um das Routing und unterstützt dabei Actors (Stationen zwischen den Providern von Sender und Empfänger à siehe SOAP-Referat). Er ermöglicht auch den Nachrichtenversand an mehrere Empfänger und zeitlich verzögertes Senden, wobei der sendende Client nicht auf den Versand warten muss, sondern beendet werden kann. Ferner kann ein Provider auch den Nachrichtenversand und –empfang protokollieren (Logging). Außerdem kann der Provider die zu versendenden Nachrichten auf andere Profile (z.B. ebXML) umsetzten. Diese Umsetztung erfolgt für den Client transparent. Er braucht sich also weder darum zu kümmern noch bemerkt er davon etwas. JAX-RPC vs. JAXM Der Vorteil von JAX-RPC gegenüber JAXM ist, dass JAX-RPC in der Handhabung wesentlich einfacher ist als JAXM, da man sich bei JAX-RPC nicht wie bei JAXM selbst um den Aufbau der SOAP-Nachrichten kümmern muss. Dies wird von der API übernommen. Ein Nachteil von JAX-RPC gegenüber JAXM ist, dass JAX-RPC ausschließlich auf Funktionsaufrufe ausgelegt ist, während JAXM zur Übertragung von Daten, auch Binärdaten wie z.b. Bildern, dient. Diese Daten können als Attachments an die SOAP-Nachrichten angehängt werden. Ein weiterer Unterschied zwischen AJXM und JAX-RPC ist, dass eine Nachricht bei JAXM mehrere Empfänger haben kann. Bei JAX-RPC nur einen. Ferner ist bei JAX-RPC die Versendung der Nachrichten nicht gesichert. Erstellen einer SOAP-Nachricht mittels Java-APIs Zum Erstellen von SOAP-Nachrichten in Java benötigt man nur ein Package: javax.xml.soap. Dieses Package ist im Java Web Services Developer Pack enthalten (http://java.sun.com). Eine normale SOAP-Nachricht besteht aus einem SOAP-Part, der den SOAP-Envelope enthält. Dieser enthält den SOAP-Header und den SOAP-Body. Eine SOAP-Nachricht mit Attachment, wie sie mit JAXM erstellt und versandt werden kann, enthält neben dem normalen SOAP-Part einen oder mehrere Attachment-Parts nach dem SOAP-Part. Jeder Attachment-Part hat einen MIME-Header uns einen Content (Inhalt). Dieser Inhalt kann XML sein, muss aber nicht. Er kann mit entsprechenden Angaben im Mime-Header auch Binärdaten (z.B. ein Bild) enthalten. Beispiele: <?xml version="1.0" encoding="UTF-8"?> <soap-env:Envelope xmlns:soap-env= "http://schemas.xmlsoap.org/soap/envelope/" > <soap-env:Header/> <soap-env:Body> <Students> <Vorname>Christian</Vorname> <Vorlesung>Projektseminar</Vorlesung> <Note>1</Note> </Students> </soap-env:Body> </soap-env:Envelope> ------=_Part_3_20245380.1037743827898 Content-Type: text/xml <?xml version="1.0" encoding="UTF-8"?> <soap-env:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soap-env:Header/> <soap-env:Body> <ztrade:GetLastTradePrice xmlns:ztrade="http://wombat.ztrade.com"> <ztrade:symbol>SUNW</ztrade:symbol> </ztrade:GetLastTradePrice> </soap-env:Body> </soap-env:Envelope> ------=_Part_3_20245380.1037743827898 Content-Type: text/html <html> <body> This is a simple example of a roundtrip JAXM message exchange. <p> Click <a href="sender">here</a> to send the message </body> </html> ------=_Part_3_20245380.1037743827898-- Aufbau einer SOAP-Nachricht SOAP message A. SOAP part 1. SOAP envelope a. SOAP header (optional) b. SOAP body B. Attachment part (optional) Sowohl der SOAP-Header, als auch der Attachment-Part können null-, ein- oder mehrmals vorhanden sein. Nur der SOAP-Body darf nicht fehlen. Auf SOAP aufsetzende Protokolle Um mit auf SOAP aufsetzenden Protokolle wie ebXML und SOAP-RP arbeiten zu können, hat SUN entsprechende Packages zur Verfügung gestellt: com.sun.xml.messaging.jaxm.ebxml com.sun.xml.messaging.jaxm.soaprp Auf diese Protokolle wird hier nicht näher eingegangen. Aufbau einer SOAP-Nachricht ohne Attachment Um eine neue Message zu erzeugen, benötigt man zuerst eine Instanz der MessageFactory. Diese erhält man mit MessageFactory.newInstance(). Mit dieser MessageFactory mf.createMessage(). erzeugt man dann ein SOAPMessage-Objekt Über den Aufruf msg.getSOAPPart() erhält man den in der Message enthaltenen soapPart als Objekt. Von diesem Objekt erhält man mit soapPart.getEnvelope() den SOAP-Enevelope und mit envelope.getBody() den darin enthaltenen SOAP-Body. Jetzt kann man mit body.addChildElement(envelope.CreateName ("GetStudent")).addTextNode(param) dem Body ein Element mit enthaltenem Text hinzufügen. Mit msg.saveChanges() speichert man alle Änderungen (hier das neue Element im SOAP-Body) in dem SOAPMessage-Objekt. Jetzt kann die SOAP-Nachricht versandt werden. Der Zugriff auf die einzelnen Teile einer SOAPMessage geschieht also von außen nach innen entlang der XML-Struktur der SOAPMessage. Aufbau einer SOAP-Nachricht ohne Attachment Beispiel: Quellcodeausschnitt: public void createMessage(String param) { try { mf = MessageFactory.newInstance(); msg = mf.createMessage(); soapPart=msg.getSOAPPart(); envelope = soapPart.getEnvelope(); body = envelope.getBody(); body.addChildElement(envelope. createName("GetStudent")). addTextNode(param); msg.saveChanges(); msg.writeTo(System.out); } catch (Exception ex) { System.err.println("Fehler:"+ ex); } } Erstelltes XML für die Nachricht: <?xml version="1.0" encoding="UTF-8"?> <soap-env:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soap-env:Header/> <soap-env:Body> <GetStudent> 2 </GetStudent> </soap-env:Body> </soap-env:Envelope> Hinzufügen eines Attachments Zum Anhängen einer Datei als Attachment an eine SOAPMessage benutzt man einen DataHandler: URL url = new URL("http://wombats.com/img.jpg"); AttachmentPart ap1 = message.createAttachmentPart(new DataHandler(url)); message.addAttachmentPart(ap1); Um einen String als Attachment anzuhängen, benötigt man den DataHandler nicht: AttachmentPart ap2 = message.createAttachmentPart("hello", "text/plain; charset=ISO-8859-1"); message.addAttachmentPart(ap2); JAVA Messaging mit XML API Zum Versenden der SOAP-Nachrichten benötigt man das Package javax.xml.messaging. Dieses Package enthält die Klassen Endpoint und ProviderConnectionFactory und die Interfaces OnewayListener, ProviderConnection und ProviderMetaData für Verbindungen mit Provider. Für Verbindungen ohne Provider (Standalone) gibt es die Klasse URLEndpoint und das Interface ReqRespListener. Für beide Arten von Verbindungen gibt es noch JAXMException als Exception-Klasse. ProviderConnectionFactory Deklaration: public abstract class ProviderConnectionFactory Konstruktor: public ProviderConnectionFactory() Methoden: public abstract javax.xml.messaging.ProviderConnection createConnection() Mit dieser Methode werden ProviderConnections erzeugt. public static javax.xml.messaging.ProviderConnectionFactory newInstance() Mit dieser Methode wird eine Instanz der ProviderConnectionFactory erzeugt. Diese Factory bietet die Möglichkeit Verbindungen zu einem MessageProvider herzustellen. Um die ProviderConnectionFactory zu verwenden, werden nur zwei Zeilen Code benötigt: ProviderConnectionFactory pcf = ProviderConnectionFactory.newInstance(); ProviderConnection con = pcf.createConnection(); ProviderConnection Deklaration: public interface ProviderConnection Methoden: public public public public void close() javax.xml.soap.MessageFactory createMessageFactory(String) javax.xml.messaging.ProviderMetaData getMetaData() void send() Die ProviderConnection ist eine aktive Verbindung eines Clients zu einem Provider. Sie enthält alle Methoden um Nachrichten zu versenden. OnewayListener Deklaration: public interface OnewayListener Methoden: public void onMessage(SOAPMessage) Der OnewayListener muss bei Verbindungen über einen Message-Provider eingerichtet werden, da die Nachrichten über den Provider nach dem Prinzip fire-and- forget versandt werden. Will man auf einen Response reagieren muss dieser Listener nun eingerichtet werden. ProviderMetaData Deklaration: public interface ProviderMetaData Methoden: public public public public int getMajorVersion() int getMinorVersion() java.lang.String getName() java.lang.String getSupportedProfiles() Bei bestehender Connection zu einem Provider kann der Client verschiedene Informationen über den Message-Provider abrufen. Beispiel: ProviderMetaData pmd = con.getMetaData(); String name = pmd.getName(); int majorVersion = pmd.getProviderMajorVersion(); int minorVersion = pmd.getProviderMinorVersion(); Endpoint Deklaration: public class Endpoint Konstruktor: public Endpoint (String) Methoden: public java.lang.String toString() Der Endpoint repräsentiert eine Adresse eines Servicepartners. Diese wird im SOAP-Header der Nachricht dem Provider übergeben. ReqRespListener Deklaration: public interface ReqRespListener Methoden: public.javax.xml.soap.SOAPMessage onMessage(SOAPMessage) Bei Standalone Connections wird der Sender nach dem call Aufruf geblockt, bis ein Response eintrifft. Der ReqRespListener regelt die Verarbeitung der Response Message. Wird kein Response erwartet, muss trotzdem ein ReqRespListener eingesetzt werden und eine leere Nachricht an onMessage geschickt werden, um die Blockierung durch call aufzulösen. URLEndpoint Deklaration: public class URLEndpoint extends Endpoint Konstruktor: public URLEndpoint(String) Methoden: public.java.lang.String getURL() URLEndpoint ist eine Unterklasse von Endpoint und erfüllt die selben Aufgaben (Adressauflösung). Nur ist URLEndpoint speziell für Standalone–Verbind ungen gedacht. JAXMException Deklaration: public class JAXMException extends SOAPException Konstruktor: public public public public JAXMException() JAXMException(String) JAXMException(String, Throwable) JAXMException(Throwable) Methoden: getCause() getMessage() initCause(Throwable) Diese Methoden von JAXMException sind vom Interface SOAPException abgeleitet. Folgende Methoden sind von class java.lang.Throwable abgeleitet: fillInStackTrace getLocalizedMessage printStackTrace printStackTrace printStackTrace toString JAXMException Es gibt auch vorgefertigte Exceptions, die an verschiedenen Stellen „geworfen“ werden. Zum Beispiel in der Methode send(), wenn die Nachricht nicht versandt werden kann. Hier braucht man sich nicht um die Erstellung und das werfen von Exceptions zu kümmern. Die Exception muss nur noch „gefangen“ werden und verarbeitet werden. try {...} catch(throwable e) {...} Quellangaben - Java Web Services Tutorial 1.0 (http://java.sun.com/webservices/tutorial.html) Java Web Services Documentation (http://java.sun.com/webservices/docs.html) Java Web Services Developer Pack API Specification (http://java.sun.com/webservices/docs/1.0/api/index.html) JAXM Specifications (http://java.sun.com/xml/downloads/jaxm.html) Sun Web Services Developer Code Camp (http://fr.sun.com/developpeurs/sdc/webservices/)