Beispiel: novaris-billing-soap/src/main/resources/wsdl/BillingService.wsdl.
Es gibt zwei grundverschiedene Wege, einen SOAP-Service zu entwerfen:
@WebService
annotierte Java-Klasse/Interface; der Anwendungsserver generiert daraus zur Laufzeit oder
beim Deployment automatisch die WSDL. Schnell, aber der Vertrag ist eine Ableitung des
Codes - aendert sich die Java-Signatur, aendert sich unbemerkt auch der Vertrag.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.
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.
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).
<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.