Suche
Was ist neu?

CDI 2.0 ist da: Dependency Injection jetzt auch für Java SE

Hartmut Schlosser

Die Arbeiten an Java EE 8 schreiten voran. Mit der Version 2.0 der Context and Dependency Injection (CDI) Spezifikation ist nun eine der Kernkomponenten für das Release fertiggestellt. Was ist neu?

CDI 2.0: Neue Struktur

Was zunächst auffällt, ist die neue Struktur der Spezifikation. In der Version 2.0 wurde CDI in drei Teile aufgesplittet: In „Core CDI“ werden die übergreifenden Konzepte beschrieben. Auf dieser Grundlage fügt der neue Part „CDI in Java SE“ spezifische Features für die CDI-Nutzung in der Java Standard Edition hinzu. Die Spezifikationen in Teil 3 basieren ebenfalls auf Core CDI, sind aber auf den Einsatz in einem Java EE Container zugeschnitten.

Diese Aufteilung spiegelt eine der wichtigsten Neuerungen in CDI 2.0 wider: Die bislang nur in der Praxis realisierte, jedoch nicht spezifizierte Nutzung von CDI in Java-SE-Projekten wurde durch ein neues API offiziell in den Standard aufgenommen.

CDI 2.0 in Java SE – so geht`s

Im Java SE-Kontext muss der CDI Container explizit gestartet werden. Dies wird in CDI 2.0 durch die abstrakte Klasse SeContainerInitializer und die statische Methode newInstance() durchgeführt.

Dabei ist SeContainerInitializer ein ServiceProvider der Services javax.enterprise.inject.se.SeContainerInitializer, der in META-INF/services deklariert wird. Diese Klasse erlaubt die Konfigurierung des CDI Containers vor dem eigentlichen Bootstrapping. Die Methode SeContainerInitializer.initialize() löst dann das Bootstrapping aus und gibt eine Instanz von SeContainer zurück.

Lesen Sie auch: CDI – Java SE, die Welt der Threads

Aus synchron wird asynchron

Eine weitere Neuerung in CDI 2.0 ist die Unterstützung für asynchrone Events. Dafür steht die Methode fireAsync() zur Verfügung. Das Beispiel aus der offiziellen Spezifikation sieht so aus:

@Inject Event<LoggedInEvent> loggedInEvent;

public void login() {
    ...
    loggedInEvent.fireAsync( new LoggedInEvent(user) );
}

 

Alle aufgelösten asynchronen Observer werden in einem oder mehreren separaten Threads aufgerufen. Darüber hinaus stellt das Interface Event eine Methode bereit, um Events mit einer spezifischen Kombination aus Typen und Qualifiern zu feuern:

public interface Event<T> {

    public void fire(T event);
    public <U extends T> CompletionStage<U> fireAsync(U event);
    public <U extends T> CompletionStage<U> fireAsync(U event, NotificationOptions options);

    public Event<T> select(Annotation... qualifiers);
    public <U extends T> Event<U> select(Class<U> subtype, Annotation... qualifiers);
    public <U extends T> Event<U> select(TypeLiteral<U> subtype, Annotation... qualifiers);

}

Mehr zum Thema: EnterpriseTales: Asynchrone Events in CDI 2.0

Observer-Prioritäten

Interessant ist die neue Option, eine Reihenfolge für den Aufruf verschiedener Observer-Methoden für spezifische Events festzulegen. Dafür wurde die Annotation @Priority eingeführt, mit der ein Event-Parameter ausgezeichnet werden kann:

void afterLogin(@Observes @Priority(javax.interceptor.Interceptor.Priority.APPLICATION) LoggedInEvent event) { ... }

Allerdings ist die Bearbeitung mehrerer Observer derselben Priorität undefiniert, sodass die Observer-Methoden in einer nicht vorhersehbaren Reihenfolge notifiziert werden.

Eingebaute Annotation-Literale

Neu sind zudem einige vordefinierte Annotationen, über die sich statische Literal-Klassen definieren lassen. Die folgenden Annotationen stehen zur Verfügung:

  • javax.enterprise.inject.Any
  • javax.enterprise.inject.Default
  • javax.enterprise.inject.New
  • javax.enterprise.inject.Specializes
  • javax.enterprise.inject.Vetoed
  • javax.enterprise.util.Nonbinding
  • javax.enterprise.context.Initialized
  • javax.enterprise.context.Destroyed
  • javax.enterprise.context.RequestScoped
  • javax.enterprise.context.SessionScoped
  • javax.enterprise.context.ApplicationScoped
  • javax.enterprise.context.Dependent
  • javax.enterprise.context.ConversationScoped
  • javax.enterprise.inject.Alternative
  • javax.enterprise.inject.Typed

Somit kann die  Literal-Klasse genutzt werden, um das korrespondierende AnnotationLiteral zu instantiieren:

Default defaultLiteral = new Default.Literal();

Zusätzlich stellt CDI Annotations-Literale für die folgenden JSR 330 Annotationen (Dependency Injection for Java) bereit:

  • javax.inject.Inject mit der Klasse javax.enterprise.inject.literal.InjectLiteral
  • javax.inject.Named mit der Klasse javax.enterprise.inject.literal.NamedLiteral
  • javax.inject.Qualifier mit der Klasse javax.enterprise.inject.literal.QualifierLiteral
  • javax.inject.Singleton mit der Klasse javax.enterprise.inject.literal.SingletonLiteral

Lambdas, Streams & More

Was hat CDI 2.0 sonst noch im Gepäck?

Zu erwähnen sind die Konfiguration für SPI-Elemente sowie die Unterstützung von Java 8 Features wie Streams und Lambda Expressions. Außerdem ist es möglich, im Event ProcessObserverMethod Observer-Methoden zu konfigurieren. Im Interface InterceptionFactory kann ein Interceptor auf einen Producer angewandt werden:

@Produces
@RequestScoped
public Product createInterceptedProduct(InterceptionFactory<Product> interceptionFactory) {
  interceptionFactory.configure().add(ActionBinding.Literal.INSTANCE);
  return interceptionFactory.createInterceptedInstance(new Product());
}

CDI 2.0 ausprobieren

Wer CDI 2.0 mit dieser Feature-Vielfalt nutzen möchte, muss nicht auf das Release von Java EE 8 warten. Schon jetzt stehen die Neuerungen in der Referenzimplementieruing Weld 3.0 zur Verfügung.

CDI Spec Lead Antoine Sabot-Durand von Red Hat beschreibt auf www.cdi-spec.org die Vorgehensweise. Durch folgenden Code wird der pom.xml-Datei die cdi-api 2.0-Komponente hinzugefügt:

<dependency>
    <groupId>javax.enterprise</groupId>
    <artifactId>cdi-api</artifactId>
    <version>2.0-PFD</version>
</dependency>

Weitere Einrichtungsschritte, beispielsweise für Red Hats WildFly-Server, beschreibt Sabot-Durand in seinem Blogpost.

Die gesamte Spezifikation für CDI 2.0 finden Interessierte unter http://docs.jboss.org/cdi/spec/2.0/cdi-spec.html.

Verwandte Themen:

Geschrieben von
Hartmut Schlosser
Hartmut Schlosser
Hartmut Schlosser ist Redakteur und Online-Koordinator bei Software & Support Media. Seine Spezialgebiete liegen bei Java-Enterprise-Technologien, JavaFX, Eclipse und DevOps. Vor seiner Tätigkeit bei S & S Media studierte er Musik, Informatik, französische Philologie und Ethnologie.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.