Jakarta EE: CDI, JTA, JAX-RS, JMS und Batch
Standardbasierte Enterprise-Entwicklung mit Container-Diensten verstehen.
Jakarta EE als Standardplattform
Jakarta EE ist eine standardisierte Plattform für Enterprise-Anwendungen. Sie liefert Spezifikationen für Dependency Injection, REST, Persistence, Transactions, Messaging, Security, Validation, Batch und weitere Bereiche. Wichtig ist die Trennung zwischen Spezifikation und Implementierung: Jakarta EE definiert APIs und Verhalten, konkrete Server oder Frameworks liefern die Runtime.
| Spezifikation | Wofür sie gut ist | Typisches Missverständnis |
|---|---|---|
| CDI | Dependency Injection, Scopes, Events | CDI ist nicht nur @Inject, sondern Lebenszyklus und Kontexte |
| JTA | Transaktionsgrenzen über Ressourcen | Transaktion gehört an Use-Case-Grenze |
| JAX-RS | REST Endpunkte und Clients | HTTP-Status und Fehlervertrag sind Architektur, nicht Deko |
| JPA | Objekt/Relation-Mapping | Entity ist nicht automatisch Domain-Modell |
| JMS | Asynchrone Nachrichten | Message-Verarbeitung braucht Idempotenz und DLQ |
CDI und Application Service
CDI hilft, Objektgraphen kontrolliert zusammenzubauen. In Enterprise-Code sollte CDI nicht die Fachlogik ersetzen. Die Fachlogik bleibt in Domain- und Application-Services; CDI verdrahtet die Implementierungen.
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
@ApplicationScoped
public class InvoiceApplicationService {
@Inject InvoiceRepository invoices;
@Inject OrderClient orders;
@Inject DomainEventPublisher events;
// Pattern: Transaction Script an der Use-Case-Grenze - bewusst hier, nicht im Controller.
@Transactional
public InvoiceId createInvoiceFor(OrderId orderId) {
OrderSnapshot order = orders.load(orderId);
Invoice invoice = Invoice.from(order);
invoices.persist(invoice);
events.publish(new InvoiceCreated(invoice.id(), orderId));
return invoice.id();
}
}
JAX-RS Resource sauber schneiden
@Path("/invoices")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class InvoiceResource {
@Inject InvoiceApplicationService service;
@POST
public Response create(CreateInvoiceRequest request) {
InvoiceId id = service.createInvoiceFor(request.orderId());
return Response.created(URI.create("/invoices/" + id.value()))
.entity(new CreateInvoiceResponse(id.value()))
.build();
}
}
Jakarta EE 11 Modernisierung
Jakarta EE 11 ist relevant, weil es moderne Java-Sprachmerkmale besser berücksichtigt und Java 17+ als Basis setzt. Für Legacy-Projekte ist der wichtigste Schritt oft nicht sofort Jakarta EE 11, sondern die kontrollierte Migration von javax.* zu jakarta.*, die Aktualisierung des Application Servers und die Entkopplung alter EJB-/SOAP-/JSP-Schichten.