← Zur Uebersicht

Exceptions in EJB: Application vs. System Exceptions

Das ist einer der am haeufigsten missverstandenen Teile des EJB-Modells - und einer der Gruende, warum "EJB verstehen" oft schwerer faellt, als es sein muesste. Dieses Projekt zeigt drei konkrete Exception-Klassen, die zusammen das gesamte Bild ergeben.

Die Grundunterscheidung

Der EJB-Container behandelt jede aus einer Business-Methode geworfene Exception nach einem von zwei grundverschiedenen Mustern:

Application Exception System Exception
Bedeutung ein erwarteter, fachlicher Fall ein unerwarteter, technischer Fehler
Transaktion je nach @ApplicationException(rollback=...) immer automatischer Rollback
Fuer Remote-Clients bleibt die urspruengliche Exception-Klasse wird in EJBException/RemoteException verpackt
Aufrufer-Erwartung soll gezielt behandelt werden i.d.R. nicht sinnvoll behandelbar
In diesem Projekt PolicyNotFoundException, UnderwritingRejectedException LegacySystemUnavailableException

Application Exceptions: zwei Beispiele mit unterschiedlichem Rollback-Verhalten

Beide erweitern bewusst die checked Exception (nicht RuntimeException) - jede Methode auf PolicyManagementLocal/PolicyManagementRemote, die sie werfen kann, deklariert das explizit in ihrer Signatur (throws PolicyNotFoundException). Der Compiler zwingt Aufrufer damit, sich mit dem Fall auseinanderzusetzen.

Wichtig: Der Spezifikations-Default fuer @ApplicationException ist rollback = false. Beide Klassen in diesem Projekt setzen den Wert trotzdem explizit, damit die Absicht im Code steht und nicht implizit aus der Spezifikation erinnert werden muss.

System Exceptions: LegacySystemUnavailableException

Erweitert bewusst RuntimeException (unchecked) und traegt keine @ApplicationException-Annotation. Damit verhaelt sie sich exakt wie eine System Exception:

Verwendet wird sie durchgaengig in den Datenzugriffsschichten (LegacyContractDao, JndiLookupHelper, AuditLogDao - wobei letztere sie bewusst NICHT wirft, siehe docs/10-ejb-konzepte/05-interceptors.md), um checked SQLException/ NamingException in ein einheitliches, unchecked Format zu uebersetzen.

Warum diese Unterscheidung ueberhaupt so wichtig ist

Ohne sie muesste jeder Aufrufer jeder EJB-Methode potenziell mit jeder denkbaren Exception rechnen - fachlichen wie technischen. Die Trennung macht die Business-Interfaces selbst zur Dokumentation: throws PolicyNotFoundException sagt dem Aufrufer exakt, mit welchen fachlichen Ausnahmefaellen zu rechnen ist, waehrend technische Ausfaelle (DB weg, MQ weg, JNDI kaputt) einheitlich und automatisch behandelt werden, ohne die Methodensignaturen mit jeder denkbaren technischen Fehlerquelle zu ueberladen.

⌂ Cockpit