Convention over Code in Java EE
Seite 2: EJB 3.1
EJB 3.1 – Maniküre im Komponentenland
Zu den wesentlichen Bausteinen der Enterprise-Plattform gehört die Komponententechnik Enterprise JavaBeans (EJB). Anhand der Versionsnummer 3.1 lässt sich schon erahnen, dass im Vergleich zum Vorgänger nur kosmetische Änderungen zu erwarten sind.
Eine augenscheinliche Veränderung von EJB 3.1 ist die Einführung von Enterprise JavaBeans, von denen es nur genau eine Instanz geben darf und auf die sich gleichzeitig von mehreren Clients (Threads) zugreifen lässt. Bisher waren die sogenannten Singletons nur mit proprietären Funktionen der Application-Server-Hersteller oder durch klassische Java SE Singletons umzusetzen. Gerade Letzteres entwickelt sich innerhalb eines Application Server oft zum Lotteriespiel, da sich Java SE Singletons durch ihre Abhängigkeit zu einem Classloader im Kontext einer "Java EE"-Anwendung gern etwas anders verhalten als erwartet.
Der Schritt zu einem Java EE Singleton ist vergleichsweise einfach: Mit der Annotation @Singleton lässt sich ein EJB-Container anweisen, eine Session Bean zu erzeugen, die es in einer Anwendung nur genau einmal geben darf. Es ist dem Container überlassen, wann er Singleton Session Beans instanziert. Abhilfe schafft hierfür die Annotation @Startup, die einen EJB-Container veranlasst, ein Java EE Singleton vor dem ersten Zugriff auf die Anwendung zu instanzieren. In Verbindung mit den bekannten EJB-Lebenszyklus-Annotationen (@PreConstruct, @PostConstruct et cetera) sowie der neu eingeführten Annotation @DependsOn sind Anwendungen nun kontrolliert und in vordefinierter Abfolge zu initialisieren.
Zu beachten gilt jedoch die Einschränkung "in einer Anwendung": Sollte ein Java EE Singleton in mehreren Enterprise-Java-Anwendungen existieren oder aber eine "Java EE"-Anwendung in mehr als einer Application-Server-Instanz deployt sein (Stichwort Clustering), erzeugt der EJB-Container für jedes Deployment eine Singleton-Instanz. Insofern ist das Java EE Singleton nach EJB 3.1 nicht ein globales, clusterfähiges "Enterprise Singleton", sondern eines, das einem Java SE Singleton unter Vermeidung der bisher bekannten Classloader-Probleme ähnelt.
Mach mal – ich warte ... vielleicht
Angelehnt an die Möglichkeiten der Concurrency API java.util.concurrent der Java SE 5 führt EJB 3.1 mit Asynchronous Invocations eine leichtgewichtige, asynchrone Ausführung der Business-Logik ein. Was in der Vergangenheit mit "Java EE"-Bordmitteln nur unter Nutzung relativ schwergewichtiger "Java Messaging Service"-Aufrufer (JMS) umzusetzen war, geht nun mit einfacher Annotation unter Berücksichtigung einer speziellen Methodensignatur, sofern das Ergebnis des asynchronen Aufrufs für einen Client von Interesse ist.
Das folgende Code-Fragment zeigt eine asynchrone Methode ohne Rückgabewert, deren Ausführung einen aufrufenden Client nicht blockiert.
@Asynchronous
public void performAsynchronous() {
...
}
Durch die Annotation einer Bean-Methode legt man die asynchrone Ausführung gleichzeitig für die lokale und entfernte Sicht einer Enterprise Bean fest. Erfolgt die Annotation nur im Local- oder nur im Remote Interface, gilt die Asynchronität nur für den jeweiligen Zugriffsmechanismus der Enterprise Bean.
Benötigt ein Client das Ergebnis eines asynchronen Methodenaufrufs, muss die entsprechende Methode einen Rückgabewert vom Typ java.util.concurrent.Future definieren. Clients können dann – wie in der Java SE für ein Future spezifiziert – mit get() auf das Ergebnis zugreifen oder auf die Verarbeitung mit weiteren Future-Methoden Einfluss nehmen. EJB 3.1 unterstützt im Wesentlichen die Semantik aller Methoden von Future, insbesondere get(long timeout, TimeUnit unit). Das folgende Beispiel zeigt eine asynchrone Methode mit einem parametrisierten Rückgabewert:
@Asynchronous
public Future<Money> performCalculation() {
...
}