Da die Webservice-Schnittstelle durch die WSDL klar definiert ist, können frei verfügbare Webservice-Bibliotheken diese Definition verarbeiten und daraus Proxy-Klassen generieren, die die notwendigen SOAP-Anfragen kapseln und dadurch eine effiziente Entwicklung von Clientanwendungen ermöglichen. In diesem Kapitel wird dies anhand Suns Referenzimplemenentierung von JAX-WS und der Bibliothek Apache Axis2 gezeigt.
Im Lieferumfang des Java Development Kit (JDK) Version 1.7 befindet sich das Kommandozeilentool wsimport, mit dem Proxy-Klassen generiert werden können. Ist der Webservice von jadice server wie in Abschnitt „Konfiguration Webservice-Schnittstelle“ beschrieben aktiviert worden, werden mit folgendem Aufruf die notwenden Clientklassen erzeugt:
<jdk1.7>\bin\wsimporthttp://localhost:9000/jadiceServer?wsdl
-keep
-extension
Der Parameter -keep
bewirkt, dass nicht nur die Klassen, sondern auch deren Quelltexte
gespeichert werden. Zur weiteren Entwicklung empfehlt es sich, mit diesen weiter zu
arbeiten. Abbildung 7.2, „Von JAX-WS generierte Klassen“ zeigt die generierten Klassen, die in die Entwicklungsumgebung
eingebunden werden können.
Einstiegspunkte für eine Clientanwendung sind die Klassen JadiceServerJobInvoker
und
JobInvocationService
, über die ein Zugriff auf die SOAP-Schnittstelle erfolgt, und die
Klasse JobConfiguration
über die der Aufruf konfiguriert wird. Eine minimale
Implementierung kann so aussehen:
Beispiel 7.6. Implementierung eines SOAP-Clients mit der JAX-WS Referenzimplemenentierung
// Abstraktion der SOAP-Schnittstelle: JadiceServerJobInvoker invoker = new JadiceServerJobInvoker(); JobInvocationService service = invoker.getJobInvocationServiceImplPort(); // Konfiguration des Jobs JobConfiguration job = new JobConfiguration(); job.setTemplateLocation("resource:/jobtemplates/x2pdf.xml"); // Optional: Setzen einer Property (Timeout als Bsp.) Property timeout = new Property(); timeout.setName("timeout"); timeout.setValue("20000"); job.getProperty().add(timeout); // Anhängen der Eingabedaten // (sofern Template einen StreamInputNode besitzt) Stream inputStream = new Stream(); inputStream.setDocumentData(…); job.getStream().add(inputStream); // Absetzen der SOAP-Anfrage (Methode blockiert) JobResult result = service.run(job); // Ergebnis-Status abfragen ResultStatus status = result.getStatus(); for (Log log : result.getLogEntry()) { // Logeinträge auswerten... } // Ergebnis-Daten abrufen for (Stream stream : result.getStream()) { InputStream is = stream.getDocumentData().getInputStream(); }
Apache Axis2 ist unter http://axis.apache.org/axis2/java/core/ verfügbar und steht unter der Apache License. Ist der Webservice von jadice server wie in Abschnitt „Konfiguration Webservice-Schnittstelle“ beschrieben aktiviert worden, werden mit folgendem Aufruf die notwendigen Clientklassen erzeugt:
<AXIS2_HOME>\bin\wsdl2java-o generatedCode
-p com.levigo.jadice.server.ws.client.axis2.stub
-d jaxbri
-uri http://localhost:9000/jadiceServer?wsdl
Die Verwendung der Parameter -o
für das Ausgabeverzeichnis und -p
für den zu
verwendenden Paketnamen sind optional. Der Parameter -d
bestimmt, welches Databinding für
die Wandlung nach / von XML verwendet werden soll. Standard ist das Apache Axis Data Binding
(ADB). Dieses hat in der aktuellen Fassung jedoch Probleme mit der Deserialisierung von
SOAP/MTOM-Attachments, sodass stattdessen auf die JAX-B Referenzimplemenentierung (jaxbri
)
zurückgegriffen werden sollte.
Einstiegspunkte für eine Clientanwendung sind die Klassen JadiceServerJobInvokerStub
und
Run
, über die ein Zugriff auf die SOAP-Schnittstelle erfolgt, und die Klasse
JobConfiguration
, über die der Aufruf konfiguriert wird. Eine minimale Implementierung kann
so aussehen:
Beispiel 7.7. Implementierung eines SOAP-Clients mit Apache Axis2
// Abstraktion der SOAP-Schnittstelle JadiceServerJobInvokerStub invoker = new JadiceServerJobInvokerStub(); // Konfiguration des Jobs JobConfiguration job = new JobConfiguration(); job.setTemplateLocation("resource:/jobtemplates/x2pdf.xml"); // Optional: Setzen einer Property (Timeout als Bsp.) Property timeout = new Property(); timeout.setName("timeout"); timeout.setValue("20000"); job.getProperty().add(timeout); // Anhängen der Eingabedaten // (sofern Template einen StreamInputNode besitzt) Stream inputStream = new Stream(); inputStream.setDocumentData(…); job.getStream().add(inputStream); // Konfiguration der Anfrage Run run = new Run(); run.setJob(job); // Absetzen der SOAP-Anfrage (Methode blockiert) RunResponse response = invoker.run(run); // Ergebnisobjekt abholen JobResult result = response.getReturn(); // Ergebnis-Status abfragen ResultStatus status = result.getStatus(); for (Log log : result.getLogEntry()) { // Logeinträge auswerten... } // Ergebnis-Daten abrufen for (Stream stream : result.getStream()) { InputStream is = stream.getDocumentData().getInputStream(); }