← Zur Uebersicht

SOAP: Contract-First und WSDL

Beispiel: novaris-billing-soap/src/main/resources/wsdl/BillingService.wsdl.

Contract-First vs. Java-First

Es gibt zwei grundverschiedene Wege, einen SOAP-Service zu entwerfen:

Dieses Projekt verwendet Contract-First: BillingService.wsdl ist der eigentliche Vertrag zwischen dem Billing-Partnersystem und Novaris, unabhaengig davon, wie beide Seiten ihn in Java umsetzen.

Der Sonderfall in diesem Projekt: hand-gepflegte Contract-Klassen

Normalerweise generiert man aus der WSDL per wsimport automatisch das Service Endpoint Interface (SEI) und alle JAXB-Bindungsklassen. In diesem Projekt ist das bewusst NICHT der Fall - die verfuegbare wsimport-Maven-Plugin-Toolchain (org.jvnet.jax-ws-commons:jaxws-maven-plugin) ist seit ca. 2016 nicht mehr gepflegt und auf dem hier verwendeten aktuellen JDK nicht mehr zuverlaessig lauffaehig (ein konkreter, selbst erlebter interner Plugin-Fehler beim Versuch, es einzusetzen).

Das ist selbst ein authentisches Legacy-Lehrstueck: nicht nur Anwendungscode veraltet, auch Build-Tooling-Ketten tun das - und ein Team, das jahrelang denselben Toolchain-Stand gefahren hat, steht irgendwann vor genau diesem Problem, sobald ein JDK-Upgrade ansteht.

Der gewaehlte Ausweg: SEI, Fault-Exception und Fault-Detail-Bean (com.novaris.legacy.common.billing.contract.* in novaris-common-legacy) sind von Hand geschrieben, aber exakt passend zur WSDL. Diese Entscheidung ist transparent dokumentiert (siehe novaris-billing-soap/README.md) statt stillschweigend getroffen - der Preis dafuer ist Doppelpflege: aendert sich der Vertrag, muessen WSDL und Java-Klassen manuell synchron gehalten werden.

Document/Literal Wrapped Style

Die WSDL nutzt den Standardstil moderner SOAP-Services: style="document" mit use="literal". Jede Operation hat genau eine XML-Nachricht als Ein- und eine als Ausgabe (statt, wie im aelteren RPC-Stil, einzelne Parameter direkt auf der Wire-Ebene abzubilden). "Wrapped" bedeutet zusaetzlich: Parameter und Rueckgabewert werden automatisch in ein implizites Element gebuendelt (registerPolicyRequest/registerPolicyResponse) - das ist der Grund, warum BillingServicePort.registerPolicy(...) trotzdem wie eine ganz normale Java-Methode mit einzelnen Parametern aussieht: JAX-WS erledigt das Ein-/Auspacken automatisch, gesteuert durch @RequestWrapper/@ResponseWrapper (siehe deren Javadoc in BillingServicePort).

Warum ueberhaupt eine XSD-<types>-Sektion?

Die WSDL definiert die Nachrichtenstruktur (registerPolicyRequest, registerPolicyResponse, den Fault) als eingebettetes XML-Schema (XSD). Das ist der Teil des Vertrags, der bei einer echten Partnerintegration typischerweise zuerst zwischen den Teams abgestimmt wird - er legt exakt fest, welche Felder in welcher Reihenfolge, mit welchem Typ und welcher Verbindlichkeit (minOccurs) uebertragen werden, unabhaengig von jeder Programmiersprache.

⌂ Cockpit