Mit der JSR 299 hat CDI Einzug in den Java EE-Standard gehalten. Doch was ist dieses CDI eigentlich, was bezweckt es, welche Neuerungen bringt es und wie kann ich diese in meiner Java Enterprise-Applikation (EJB-Applikation) nutzen? All diese Fragen soll diese Blogserie klären.
Ziele JSR 299
Dependency Injection (DI) hat schon vor langer Zeit Einzug in Java-Applikationen gefunden. Dabei mussten sich Architekten und Entwickler immer Frameworks wie Spring oder Seam bedienen. Um diesen Umstand aus der Welt zu schaffen, war es Ziel des JSR 299, ein umfassendes DI Framework im Java EE-Standard zu etablieren. Außerdem sollte eine Standardisierung und Vereinfachung des Zusammenspiels zwischen EJB und JSF erreicht werden, d.h., die Geschäftslogik sollte einfacher in die Präsentationsschicht integriert werden können.
Ich nehme an dieser Stelle mal eines vorweg: Beide Ziele hat die JSR 299 Expert Group mit der Spezifikation „Contexts and Dependency Injection for the Java EE platform“ (CDI) erreicht.
Neuerungen
Dank CDI wird der Java EE-Standard um folgende Funktionalitäten erweitert:
- Dependecy Injection-Mechanismus
- Deklarative Verknüpfung von Beans
- Scope zwischen Request und Session
- Entkopplung von Interzeptoren
- Dekoratoren
- Beanverwaltung zur Laufzeit
Container, Kontext & Scope
Container, Kontext und Scope sollten für Entwickler keine vollkommen neuen Begriffe sein, da diese jedoch für das Verständnis von CDI von Bedeutung sind, hier eine kurze Erläuterung.
Bei CDI ist der Container für die Verwaltung des Lebenszyklus‘ der an einen Kontext gebundenen Objekte zuständig. Dieser Kontext beschreibt die Beziehungen der verwalteten Objekte zueinander. Der Scope definiert die Sichtbarkeit bzw. Lebenszeit der von CDI im Container verwalteten Objekte.
Beanverständnis
Von einer Bean wird bereits bei JSF, EJB und Spring gesprochen, ohne jedes Mal dasselbe zu bezeichnen. Auch CDI spricht von Beans, und auch in dieser Spezifikation herrscht ein eigenes Verständnis davon, was unter einer Bean verstanden wird.
CDI meint: „Eine Bean ist ein Objekt, dessen Lebenszyklus vom Container verwaltet wird.“
Folglich ist jedes dem CDI-Container „bekannt gemachte“ Objekt eine Bean im Sinne von CDI. Dabei werdem CDI zwei Typen von Beans unterschieden:
- Managed Beans
- Session Beans
Managed Beans
Damit der Lebenszyklus eines Objekts von CDI verwaltet werden kann, muss dieses Objekt einen parameterlosen Konstruktor besitzen oder einen, der mit der Annotation @Inject versehen ist. Erfüllt ein Objekt eines dieser Kriterien, wird sein Lebenszyklus und die mit dem Scope verbundene Abhängigkeit der Bean vom CDI Container verwaltet.
Session Beans
Session Beans sind streng genommen auch Managed Beans, so dass für sie auch die gleichen Kriterien gelten. Bei Session Beans kommt jedoch hinzu, dass ihr Lebenszyklus vom EJB Container verwaltet wird und sie ein eigenes Statusmanagement- und Nebenläufigkeitsmodell besitzen. Stateless und Singleton Session Beans sind scopeless, es braucht ihnen also kein CDI-spezifischer Scope zugewiesen werden. Stateful Session Beans hingegen muss ein Scope explizit zugewiesen werden.
CDI kann somit sofort mit den scopeless EJBs arbeiten, ohne dass diese angepasst werden müssen.
Nicht Beans
Nicht Beans im Sinne von CDI sind Message-Driven Beans, Interzeptoren, Servlets, JAX WS Services, JSP Tag Handler und Tag Library Event Listener. Diese müssen aber nicht ganz auf die Funktionalitäten von CDI verzichten und können zumindest Beans injiziert bekommen.
In der Praxis
Es gibt mitlerweile mehrere Implementierungen von CDI. In dieser Blogserie wird die Referenzimplementierung Weld von JBoss eingesetzt. Sie stellt Werkzeuge wie DI, Scopes, EL-Namen, Interzeptor-Binding, Dekoratoren und Produzenten zur Verfügung.
Um mit CDI starten zu können, muss in einer Applikation lediglich der CDI Deployment-Deskriptor angelegt werden, die beans.xml
. Möchte man seine Applikation als .war-Datei deployen, so muss diese im Verzeichnis WEB-INF liegen. Bei als .jar-Datei zu deployenden Applikationen gehört die beans.xml
in das Verzeichnis META-INF. Die unter einem der beiden Verzeichnisse abgelegte beans.xml
kann dabei leer sein.
Gut zu wissen ist an dieser Stelle auch, dass sich CDI nicht auf den Einsatz in Java EE-Applikationen beschränkt, sondern auch unter Java SE angewendet werden kann.
Da jetzt genug über die Theorie geredet und hoffentlich ein Grundverständnis von CDI aufgebaut wurde, möchte ich mit einem kleinen Praxisbeispiel den ersten Artikel der Blogserie abschließen.
Dependency Injection
Wie bereits unter dem Punkt Session Beans erwähnt, können scopeless EJBs sofort von CDI genutzt werden. Genau das wird im folgenden Code getan.
Wir haben folgende EJB gegeben:
@Stateless public class BlogServiceBean implements BlogService { ... }
Diese kann jetzt direkt mit der Annotation @Inject in eine Bean injiziert werden.
public class InvasionController { @Inject private BlogService blogService; ... }
Ausblick
In diesem Artikel wurden die Ziele sowie das Verständnis von CDI erläutert und auch mit der Dependency Injection schon das erste Tool der Werkzeugkiste, mit der CDI seine Ziele erreicht, vorgestellt.
In zwei noch folgenden Artikeln der Blogserie werden die restliche Werkzeugkiste von CDI in der Referenzimplementierung Weld vorgestellt und auch die Beispielapplikation „Friendly Invaders“ zum Download angeboten.
Eine geniale Titelzeile!