1. Ziel von Version 3: Portal kommuniziert mit anderen Systemen
Version 3 erweitert das SOAP-Lehrbuch um ein Enterprise-Portal, das nicht nur eine SOAP-Schnittstelle aufruft, sondern einen vollständigen Multi-System-Prozess steuert.
In realen Enterprise-Landschaften ist SOAP selten allein. Ein Portal nimmt Benutzerinteraktionen entgegen, validiert Eingaben, ruft Legacy-SOAP-Services auf, kombiniert REST-Services, schreibt Auditdaten, stößt JMS-Nachrichten an und zeigt dem Benutzer einen stabilen Status. Genau diese Schicht ist fachlich kritisch, weil sie die Welt des Benutzers mit der Welt der Kernsysteme verbindet.
Das Portal darf dabei nicht zur unkontrollierten Sammelstelle für Fachlogik werden. Es braucht eine klare Integration-Facade, fachliche Commands, Adapter pro Zielsystem, ein nachvollziehbares Fehlerkonzept und einen Prozess-Manager, der synchrone und asynchrone Schritte sauber trennt.
- Portal: Benutzeroberfläche, Session, Eingabevalidierung und Statusanzeige.
- Integration-Facade: ein fachlicher Einstiegspunkt für Portal Use Cases.
- Adapter: technische Übersetzung zu SOAP, REST, JMS und Datenbank.
- Process Manager: Reihenfolge, Status, Retry, Kompensation und Idempotenz.
- Observability: Correlation-ID, fachliche Tracking-ID, Audit und technische Logs.
3. Portal Request Flow: vom Formular bis zur Backend-Antwort
Der Ablauf beginnt nicht beim SOAP Envelope, sondern beim Benutzerwunsch. Erst danach wird daraus ein fachlicher Command und später eine konkrete SOAP-Nachricht.
Ein Benutzer klickt im Portal auf „Bestellung absenden“. Das Portal erhält Formularfelder, prüft Pflichtwerte und erstellt daraus ein SubmitPortalOrderCommand. Dieser Command ist kein SOAP-Objekt. Er ist ein fachliches Eingangsmodell des Portals.
Die Integration-Facade startet dann den Prozess. Der Prozess entscheidet, welche Backends aufgerufen werden. Erst im Adapter wird aus dem fachlichen Command ein SOAP Request, REST Request oder JMS Event.
- UI DTO: nah an der Oberfläche, enthält Formular- und Anzeigeaspekte.
- Command: fachliche Absicht, unabhängig von SOAP/XML.
- Process Context: technischer Status, Retry-Zähler, Correlation-ID, Ergebnisreferenzen.
- Backend DTO: zielsystemspezifisch, z. B. JAXB-Klassen aus WSDL.
Portal Controller erzeugt einen Command
package com.example.portal.web;
import com.example.portal.integration.PortalIntegrationFacade;
import com.example.portal.domain.SubmitPortalOrderCommand;
public final class PortalOrderController {
private final PortalIntegrationFacade integrationFacade;
public PortalOrderController(PortalIntegrationFacade integrationFacade) {
this.integrationFacade = integrationFacade;
}
public PortalOrderViewModel submit(PortalOrderForm form, UserSession session) {
SubmitPortalOrderCommand command = new SubmitPortalOrderCommand(
form.partnerOrderId(),
session.userId(),
session.tenant(),
form.customerNumber(),
form.lines(),
session.correlationId()
);
PortalOrderResult result = integrationFacade.submitOrder(command);
return PortalOrderViewModel.from(result);
}
}
4. Warum das Portal keine SOAP-Klassen in der UI verwenden sollte
SOAP/JAXB-Klassen entstehen aus dem externen Vertrag. Sie sind nicht automatisch ein gutes UI- oder Domänenmodell.
Ein häufiger Fehler in Legacy-Portalen ist das direkte Durchreichen generierter JAXB-Klassen bis in Controller, Session und View. Dadurch hängt die Oberfläche an WSDL-Details: Namespaces, optionalen XML-Elementen, technischen Listenstrukturen und Fault-Typen. Jede kleine Vertragsänderung wird dann ein Portal-Refactoring.
Besser ist eine Schichtentrennung: Das Portal besitzt eigene Formulare, ViewModels und Commands. Die SOAP Adapter besitzen JAXB-Klassen und Mappinglogik. Dazwischen liegt ein bewusstes fachliches Modell.
- UI-Modelle optimieren Bedienbarkeit.
- SOAP-Modelle optimieren Interoperabilität.
- Domänenmodelle optimieren fachliche Regeln.
- Mapping ist kein unnötiger Aufwand, sondern eine Schutzschicht.
5. PortalIntegrationFacade: ein fachlicher Einstiegspunkt
Die Facade bündelt den Portal Use Case und verhindert, dass Controller technische Backend-Reihenfolgen kennen müssen.
Die PortalIntegrationFacade ist keine gigantische God Class. Sie ist ein schmaler fachlicher Einstiegspunkt. Sie nimmt Commands entgegen, startet einen Prozess und gibt ein Ergebnis zurück, das für die Oberfläche geeignet ist. Der Controller muss nicht wissen, ob zuerst REST, dann SOAP, dann JMS oder erst SOAP, dann Datenbank aufgerufen wird.
In Version 3 ist die Facade der wichtigste Schutz gegen eine Portal-Schicht, die mit jedem neuen Backend unübersichtlicher wird.
PortalIntegrationFacade mit markiertem Facade Pattern
package com.example.portal.integration;
import com.example.portal.domain.SubmitPortalOrderCommand;
import com.example.portal.integration.process.PortalOrderProcessManager;
/**
* Design Pattern: Facade.
* Zweck: Das Portal bekommt einen einfachen fachlichen Einstiegspunkt
* und kennt keine SOAP-, REST-, JMS- oder DB-Details.
*/
public final class PortalIntegrationFacade {
private final PortalOrderProcessManager processManager;
public PortalIntegrationFacade(PortalOrderProcessManager processManager) {
this.processManager = processManager;
}
public PortalOrderResult submitOrder(SubmitPortalOrderCommand command) {
return processManager.start(command);
}
public PortalOrderStatusView status(String trackingId) {
return processManager.loadStatus(trackingId);
}
}
23. Statusseite im Portal: Benutzerfreundlichkeit für verteilte Prozesse
Wenn Backends langsam oder asynchron sind, braucht das Portal eine ehrliche Statusanzeige.
Ein verteiltes System kann nicht immer sofort „fertig“ melden. Das Portal sollte Statuszustände anzeigen, die fachlich verständlich sind: angenommen, in Prüfung, technisch verzögert, abgelehnt, abgeschlossen oder manuelle Klärung.
Die Statusseite ist kein technisches Detail. Sie ist ein fachlicher Vertrag mit dem Benutzer. Sie reduziert Supportaufwand, weil Tracking-ID und nachvollziehbare Zustände sichtbar sind.
- Accepted: Auftrag angenommen und vollständig verarbeitet.
- Pending: Auftrag wird verarbeitet oder Retry läuft.
- Rejected: fachlich abgelehnt, Grund anzeigen.
- ManualReview: Sachbearbeitung prüft.
- TechnicalDelay: technische Störung, keine doppelte Bestellung auslösen.
Portal Status ViewModel
public record PortalOrderStatusView(
String trackingId,
String visibleStatus,
String userMessage,
String nextActionHint
) {
public static PortalOrderStatusView from(ProcessState state) {
return switch (state.status()) {
case COMPLETED -> new PortalOrderStatusView(state.trackingId(), "Abgeschlossen", "Ihre Bestellung wurde verarbeitet.", "Keine Aktion nötig.");
case RETRY_TECHNICAL -> new PortalOrderStatusView(state.trackingId(), "In Bearbeitung", "Ein Backend-System antwortet verzögert.", "Bitte nicht erneut absenden.");
case BUSINESS_REJECTED -> new PortalOrderStatusView(state.trackingId(), "Abgelehnt", state.businessMessage(), "Bitte Eingaben prüfen.");
default -> new PortalOrderStatusView(state.trackingId(), "In Prüfung", "Der Auftrag wird geprüft.", "Status später aktualisieren.");
};
}
}