Version 4 · Migration
Runtime-Modernisierung
EJB-, JNDI- und WebSphere-spezifische Kopplung wird über Use Cases, Ports, Adapter und klare Transaktionsgrenzen geschnitten.
EJB-, JNDI- und WebSphere-spezifische Kopplung wird über Use Cases, Ports, Adapter und klare Transaktionsgrenzen geschnitten.
Großer Schnitt: Fachlogik vor Laufzeitlogik
Bei der Runtime-Modernisierung wird nicht zuerst das Framework gewechselt. Zuerst wird die fachliche Fähigkeit freigelegt: Befehl, Validierung, Regeln, Persistenz, Ereignis, Nachweis. Danach kann entschieden werden, ob ein Teil in Liberty, JBoss EAP, Spring Boot, Quarkus oder Jakarta EE weiterlebt.
Vorher: WebSphere-EJB mischt alles
Vorher: EJB mit JNDI, JDBC, JMS und Fachlogik
@Stateless
public class InvoiceBean {
@Resource SessionContext ctx;
@EJB CustomerBean customerBean;
@Resource(mappedName = "jdbc/LegacyDS") DataSource ds;
@Resource(mappedName = "jms/InvoiceQueue") Queue queue;
public InvoiceResult createInvoice(InvoiceRequest request) {
// Problem: UI-Validierung, DB-Zugriff, SOAP-Aufruf und MQ-Senden sind gemischt.
// Refactoring-Ziel: fachlichen Use Case herauslösen und WebSphere-spezifische Adapter kapseln.
try (Connection c = ds.getConnection()) {
Customer customer = customerBean.loadCustomer(request.customerNo());
BigDecimal amount = calculateLegacyAmount(request, customer);
insertInvoice(c, request, amount);
sendJmsMessage(queue, request.invoiceNo());
return InvoiceResult.ok(request.invoiceNo(), amount);
} catch (Exception ex) {
ctx.setRollbackOnly();
return InvoiceResult.failed(ex.getMessage());
}
}
}
Nachher: Use Case mit Ports und Adaptern
Nachher: fachlicher Use Case mit markierten Patterns
public final class CreateInvoiceUseCase {
private final CustomerPort customerPort; // Pattern: Ports and Adapters
private final InvoiceRepository repository; // Pattern: Repository
private final InvoicePolicy policy; // Pattern: Policy / Specification
private final DomainEventPublisher events; // Pattern: Outbox Publisher
public CreateInvoiceUseCase(CustomerPort customerPort,
InvoiceRepository repository,
InvoicePolicy policy,
DomainEventPublisher events) {
this.customerPort = customerPort;
this.repository = repository;
this.policy = policy;
this.events = events;
}
public InvoiceResult handle(CreateInvoiceCommand command) {
CustomerSnapshot customer = customerPort.load(command.customerNo());
Invoice invoice = policy.createDraft(command, customer);
repository.save(invoice);
events.publish(invoice.createdEvent());
return InvoiceResult.ok(invoice.number(), invoice.total());
}
}
Entscheidungsmatrix Runtime
| Option | Wann sinnvoll |
|---|---|
| WebSphere Liberty / Open Liberty | Wenn viel Jakarta/Jakarta-ähnliche Struktur bleibt und Serververhalten kontrolliert migriert werden soll. |
| JBoss EAP auf OpenShift | Wenn Java-Enterprise-Serverbetrieb mit Hersteller-Support und Application-Server-Konzept gewünscht ist. |
| Spring Boot | Wenn fachliche Slices als selbstständige Services mit starkem Ökosystem entstehen sollen. |
| Quarkus / MicroProfile | Wenn Cloud-Native Java, schnelle Starts und MicroProfile-Konventionen wichtig sind. |