Blog

Freundliche Eindringlinge – Moderne Web-Applikationen mit CDI

Am 07.12.2011 war die JUGHH bei uns zu Gast, und ich habe im Vortrag „Freundliche Eindringlinge – Moderne Web-Appliaktionen mit CDI“ die Neuerungen von CDI anhand der Beispielapplikation „Friendly Invaders“ vorgestellt. Für alle, die den Vortrag noch mal Revue passieren lassen wollen, den Termin verpasst haben oder denen einfach alles zu schnell ging, sind im folgenden die Vortragsfolien, die Beispielapplikation sowie die „Tonspur“ in Schriftform zu finden.

Vortragsfolien

Tonspur

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?

Motivation – 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 – Was bietet CDI?

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

Bean-Verständnis – Beans

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 werden 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.

Konzepte

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.

DI

Dependency Injection ist an sich nichts Neues, aber sie wird mit CDI in den Standard von Java-EE-Applikationen und auch Java-SE-Appliakationen gehoben. Die Annotation @Inject ist für die DI zuständig.

Typsichere Auflösung

In CDI findet ein Typesave-Resolution-Algorithmus Anwendung. Wird also eine Bean injiziert, dann wird immer der passende Typ an diese gebunden. Erfolgt keine genauere Spezifizierung durch Qualifier oder Alternativen, wird immer die Default-Implementierung genommen – folglich eine Bean vom passenden Typ.

Lose Kopplung

Eine lose Kopplung wird erreicht, wie üblich bei Web-Applikationen, durch eine Trennung von Client und Server, die neuen unterschiedlichen Scopes (Lebenszyklen) und die Realisierung von Produzenten und Konsumenten, auf die im Praxisteil noch detaillierter eingegangen wird.

Interceptor-Binding und Dekoratoren

CDI bietet ein neues Konzept, um Interzeptoren an Beans zu binden und erreicht auch damit eine Entkopplung. Dekoratoren sind eine Umsetzung des Decorator-Patterns und ermöglichen es, Methoden um Geschäftslogik zu erweitern.

SPI

SPI stellt für Entwickler eine Schnittstelle zur Verfügung, um leichter eigene Dienste in CDI-Applikationen zu integrieren.

In der Praxis

Es gibt mittlerweile mehrere Implementierungen von CDI. In dieser Blogserie wird die Referenzimplementierung Weld von JBoss eingesetzt. Sie stellt Werkzeuge wie DI, Scopes, EL-Namen, Interceptor-Bindings, 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.

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;
 ...
}

Qualifier

Qualifier sind dazu da, bei mehreren Implementierungen eines Typs genau zu definieren, welche konkrete Implementierung von CDI injiziert werden soll. Dazu muss zunächst ein entsprechender Qualifier definiert werden bzw. eine mit @Qualifier annotierte Annotation.

@Qualifier
@Target({TYPE, METHOD, PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface Holisticon {}

Die für Annotationen typischen Meta-Annotationen @Target und @Retention legen fest, was mit der definierten Annotation annotiert werden darf und wann die Auflösung der Annotation erfolgt.

Eine Stateless Session Bean wird mit diesem Qualifier annotiert.

@Holisticon
@Stateless
public class HolisticonBlogServiceBean
    implements BlogService {
  ...
}

Und um auch die gewünschte Bean zu injizieren, wird der genutzte BlogService ebenfalls mit dem Qualifier annotiert.

public class InvasionController {
  @Inject @Holisticon
  private BlogService blogService;
  ...
}

Würde bei mehreren Implementierungen des BlogServices auf einen Qualifier verzichtet werden, so würde Weld den Start des Containers verweigern und folgende Exception werfen:

WELD-001409 Ambiguous dependencies for type [BlogService]
with qualifiers [@Default] at injection point ...

Der in der Exception erwähnte Qualifier @Default wird implizit gesetzt, wenn die Bean nicht explizit einen Qualifier bekommen hat.

Alternativen

Mittels Alternativen kann zur Deployment-Zeit festgelegt werden, dass anstatt der eigentlichen Implementierung eines Typs eine alternative Implementierung genutzt wird. Diese Alternative hat den Qualifier @Alternative und muss im CDI Deployment-Deskriptor, der beans.xml, aktiviert werden.

Die alternative Implementierung von BlogService soll ein Mock sein.

@Alternative
public class BlogServiceMock implements BlogService{
  ...
}

In der beans.xml wird die Alternative wie folgt aktiviert.


    de.holisticon.blog.friendlyInvaders.service.mock.BlogServiceMock

Wie das Codebeispiel suggerieren soll, sind diese Alternativen besonders nützlich, wenn es um das Testen einer Applikation geht.

EL-Namen

Die einfachste Variante, eine Bean dem CDI-Kontext hinzuzufügen, ist, sie mit @Named zu annotieren. Diese Annotation ermöglicht, dass eine Bean direkt in der Präsentationsschicht, wie z.B. einer JSF-Seite, angesprochen werden kann.

Zunächst wird ein Controller mit @Named annotiert.

@Named
public class InvasionController{
  @Inject @Holisticon
  private BlogService blogService;
  ...
}

Ist eine Bean mit @Named annotiert, so ist sie mit ihrem Namen in der EL ansprechbar. Zu beachten ist, dass der Name hierbei immer mit einem kleinen Buchstaben beginnt. Der EL-Name der annotierten Bean ist hier invasionController, wie im folgenden Auszug einer JSF-Seite.


  #{blogArticle.title}

Gefällt der automatische EL-Name der Beans nicht, so hat man die Möglichkeit, ihnen auch Namen via Annotation zuzuweisen (z.B. @Named („MeinName“)).

Scopes

Auch bei CDI gibt es Scopes, die die Lebenszeit von Objekten und das Verhalten von Objekten zueinander beschreiben. Beans können in CDI mit einem der folgenden Scopes annotiert werden:

  • @RequestScoped
  • @ConversationScoped
  • @SessionScoped
  • @ApplicationScoped

Wird eine Bean mit einem Scope annotiert, so wird sie dem entsprechenden Kontext im CDI-Container zugewiesen.

@Named
@SessionScoped
public class InvasionController implements Serializable {
  private static final long serialVersionUID = 1L;
  @Inject @Holisticon
  private BlogService blogService;
  ...
}

Dieser Controller wird an den SessionContext gebunden und bleibt für die Lebenszeit der Session erhalten.

An dieser Stelle ist gut zu wissen, dass Beans mit dem Session oder Conversation Scope serialisierbar sein müssen. Implementieren diese Beans nicht die Klasse Serializable, so verweigert CDI den Start und wirft die folgende Exception:

WELD-000072 Managed bean declaring a passivating scope must be
passivation capable.
Conversation Scope

Der einzig wirklich neue Scope, den CDI bietet, ist der Conversation Scope. Er schließt die Lücke zwischen dem Scope eines Requests und dem Scope einer Session, den Entwickler schon lange vermissten und teilweise durch eigene Implementierungen realisieren mussten. Die Vorteile der Conversation liegen auf der Hand, nutzerspezifische Daten können über mehrere Requests hinweg „gemerkt“ werden und es bleiben keine alten beziehungsweise nicht mehr benötigten Daten z.B. in der Session, da der Beginn und das Ende einer Conversation explizit gesetzt werden können. Ein weiteres schönes Feature ist, dass in jedem Browser Tab eine eigene Conversation gehalten wird.

In der Praxis ist der Conversation Scope unter anderem für einen Checkout-Prozess sehr nützlich, so auch im Codebeispiel. Dazu wird eine Stateful CheckoutServiceBean mit der Annotation @ConversationScoped annotiert.

@Stateful
@ConversationScoped
public class CheckOutServiceBean {
  @Inject
  private Conversation conversation;
  private KudosCart kudosCart;

  public KudosCart createKudosCart() {
    kudosCart = new KudosCart();
    // if no conversation is "open“
    if (conversation.isTransient())
      conversation.begin();
    return kudosCart;
  }
  public void checkout() {
    kudosCart.getCart().clear();
    conversation.end();
  }
}

Um die Conversation über mehrere Requests hinweg leben zu lassen – in der Spec wird von einer lange laufenden Conversation gesprochen – injizieren wir uns die Conversation in unsere Bean. Mit diesem Conversation-Objekt kann explizit festgelegt werden, wann eine Conversation beginnt (conversation.begin()) und wann sie endet (conversation.end()). Ob für einen Nutzer bereits eine Conversation „geöffnet“ wurde, kann mit conversation.isTransient() geprüft werden.

Zu beachten ist, dass die Conversation automatisch nur bei JSF Requests zur Verfügung steht. Agiert man nicht mit JSF Requests (Links, JavaScript etc.), muss eine Conversation ID (cid) als Parameter mitgegeben werden.

<a href="/add.jsp?cid=#{ javax.enterprise.context.conversation.id }">
 hinzufügen
</a>

Stereotypen

Sterotypen können als Annotationen verstanden werden, die mehrere Annotationen bündeln können.

Es kann z.B. ein Stereotyp angelegt werden, der die Annotationen @SessionScoped und @Named bündelt (die Annotationen werden im Folgenden noch erklärt). Ein Stereotyp wird mit der Annotation @Stereotype annotiert.

@Stereotype
@Named
@SessionScoped
@Target(TYPE)
public @interface NSS {}

Die mit @NSS annotierte Klasse bekommt also implizit @Named und @SessionScoped annotiert.

@NSS
public class InvasionController implements Serializable {...}

Events

Wie auch die Dependency Injection sind Events kein vollkommen neues Konzept für den Java EE Stack. CDI liefert jedoch ein neues Werkzeug, getreu dem Observer Pattern, um Events zu realisieren.

Im Kontext von Events spricht CDI von Producern und Observern. Producer erzeugen Events und Observer „lauschen“, ob Events eingetreten sind. Um Producer und Observer zusammenzubringen bzw. für die Observer festzulegen, welche Events für sie von Interesse sind, werden Qualifier genutzt.

Ergo muss im ersten Schritt ein Qualifier angelegt werden.

@Qualifier
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface Invaded {}

Im zweiten Schritt wird der Producer in der Bean angelegt, aus welcher heraus wir Events werfen wollen.

@NSS
public class InvasionController implements Serializable{
  ...
  @Inject @Invaded
  private Event blogArticleEvent;
  ...
  public String giveKudos(BlogArticle blogArticle, int amount){
    blogArticleEvent.fire(blogArticle);
    ...
  }
}

Im Codebeispiel tritt ein Event ein, wenn durch die Methode giveKudos(blogArticle, amount) dem Autor eines Blogartikels Anerkennung gezeigt wird. Das Event-Objekt wird mit @Invaded annotiert und kann somit mit entspechenden Observern in Beziehung gesetzt werden.

Fehlen also nur noch Observer, die reagieren, wenn ein Event eingetreten ist.
Zum Beispiel könnte beim Eintreten des Events getwittert werden, wer gerade für welchen Blogartikel Anerkennung bekommen hat.

@RequestScoped
public class InvasionTweeter{
  public void afterBlogIntrude( @Observes @Invaded BlogArticle blogArticle) {
    ...
  }
}

Da nicht jeder Mensch bei Twitter ist und die Autoren sicher gern Bescheid wüssten, sobald sie Anerkennung bekommen, könnte zusätzlich ein Observer Mails an die Autoren versenden.

@RequestScoped
public class InvasionMailer{
  public void afterBlogIntrude( @Observes @Invaded BlogArticle blogArticle) {
    ...
  }
}
Observer Pattern

Die Frage, ob CDI nun getreu dem Observer Pattern agiert, muss mit „Jein“ beantwortet werden. Nicht nur Producer sind von Observern entkoppelt, sondern auch Observer von Producern. Hinzu kommt, dass Observer Events mit Qualifiern filtern und verzögert aufgerufen werden können, z.B. erst, nachdem eine Transaktion abgeschlossen wurde.

Interceptor-Bindings

Ja, auch Interzeptoren sind nichts Neues, aber mit den Interceptor-Bindings wird ein mächtiges Werkzeug für des Binden von Interzeptoren an Methoden zur Verfügung gestellt. Auch hier dienen Annotationen als Bindeglied.

Im ersten Schritt wird eine mit @InterceptorBinding annotierte Annotation angelegt, das Interceptor-Binding LoggerBinding.

@InterceptorBinding
@Retention (RUNTIME)
@Target ({METHOD, TYPE})
public @interface LoggerBinding {}

Im zweiten Schritt wird ein mit dem Interceptor-Binding annotierter Interzeptor erstellt.

@LoggerBinding
@Interceptor
public class LoggingInterceptor implements Serializable {
  private static final long serialVersionUID = 1L;
  @Inject
  private Logger log;

  @AroundInvoke
  public Object onMethodCall(InvocationContext context)
      throwsException {
    ...
  }
}

Die anderen zwei Annotationen @Interceptor und @AroundInvoke sollten, wenn schon mal Interzeptoren eingesetzt wurden, bekannt sein. @Interceptor markiert die Klasse als Interzeptor, und mit @AroundInvoke wird die Methode gekennzeichnet, die beim Aufruf einer mit dem Interzeptor verbundenen Methode ausgeführt wird.

Im dritten Schritt müssen wir unseren Interzeptor jetzt an eine Bean heften. Dazu wird das Interceptor-Binding @LoggerBinding an die Methode checkout() der CheckoutServiceBean annotiert.

@Stateful @ConversationScoped public class CheckOutServiceBean {
  ...
  @LoggerBinding public void checkout() {
    conversation.end();
  }
}

Interzeptoren müssen konfiguriert werden, damit sie in der Applikation dann auch Anwendung finden. Standardmäßig sind sie deaktiviert. Also muss im letzten Schritt der Interzeptor im CDI Deployment-Deskriptor definiert werden.

Dazu wird die beans.xml um folgende Zeilen erweitert.


    de.holisticon.blog.friendlyInvaders.interceptor.LoggingInterceptor

Jetzt ist der Interzeptor aktiviert und jeder Checkout wird geloggt.

Die mit CDI eingeführten Annotationen ermöglichen es, Interzeptoren an Beans zu binden, ohne dass eine Abhängigkeit zwischen der konkreten Bean und einem konkreten Interzeptor entsteht.

Dekoratoren

Mit Dekoratoren bietet CDI eine saubere Umsetzung des Decorator Patterns.

Der Dekorator und die zu dekorierende Klasse müssen dabei das gleiche Interface implementieren. Der Dekorator wird mit @Decorator annotiert.

@Decorator
public abstract class CheckoutServiceDecorator
    implements CheckoutService, Serializable {
   ...
  @Inject @Delegate
  private CheckoutService checkoutService;

    public void giveKudos( BlogArticle blogArticle, float amount) {
      if (blogArticle.getAuthor().getName().endsWith(" Erck")){
        logger.info("No Kudos in the form of money.");
    }else{
        checkoutService.giveKudos(blogArticle, amount);
    }
  }
}

Jeder Dekorator muss ein mit @Delegate annotiertes Objekt besitzen: das Objekt, das dekoriert werden soll. Alle Methoden, die dekoriert, bzw. um Geschäftslogik erweitert werden sollen, werden vom Dekorator implementiert. Im Codebeispiel soll folglich die Methode giveKudos(blogArticle, amount) des CheckoutServiceController dekoriert werden.

Auch Dekoratoren sind Deployment-spezifisch und müssen in der beans.xml aktiviert werden.


    de.holisticon.blog.friendlyInvaders.decorator.CheckoutServiceDecorator

Dank des Dekorators bekommt jetzt keiner, der meinen Nachnamen trägt, mehr Anerkennung in Form von Centbeträgen.

Interzeptoren vs. Dekoratoren

Da im Artikel ja schon vorgestellt wurde, wie einfach sich Interzeptoren mit den Interceptor-Bindings an Klassen binden lassen, bleibt die Frage offen, wann Interzeptoren und wann Dekoratoren die richtige Wahl sind.

Ein konkreter Interzeptor lässt sich an beliebige Klassen jedes Java-Typs binden und sollte eingesetzt werden, um technische Aspekte wie z.B. Logging zu realisieren.

Ein konkreter Dekorator lässt sich nur an eine Klasse eines konkreten Java-Typs binden, kennt somit die Semantik und sollte eingesetzt werden, um eine Klasse mit Aspekten der Geschäftslogik zu dekorieren.

Produzenten

Als letztes Werkzeug sollen die Produzenten vorgestellt werden. Sie sind mit @Produces annotierte Methoden, die immer genau dann aufgerufen werden, wenn eine Instanz eines zu produzierenden Objektes verlangt wird und noch keine entsprechende Instanz erzeugt wurde.

Im Beispielcode wird ein Produzent für den Logger erzeugt. Um diesen Logger von ggf. anderen Loggern zu unterscheiden, wurde zuvor der Qualifier @HcoLogger definiert.

public class HcoLoggerFactory {

  @Produces @HcoLogger
  public Logger produceLogger(InjectionPoint injectionPoint){
    return LoggerFactory.getLogger(injectionPoint.getMember()
      .getDeclaringClass().getName());
  }
}

Soll im Kontext einer Klasse ein Logger via Dependency Injection injiziert werden und wurde für diesen Kontext noch kein Logger erzeugt, so wird er über die Methode produceLogger(injectionPoint) erzeugt.

Im Codebeispiel ist zu sehen, dass der Logger in Abhängigkeit des Typs der aufrufenden Klasse erzeugt wird. Wird eine Instanz über den Produzenten erzeugt, so hat sie den Scope @Dependent, d.h., die Instanz nimmt den Scope und somit auch den Kontext der Klasse an, in die sie injiziert wurde.

Dass im Hintergrund ein Producer greift, ist im CheckoutServiceDecorator nicht zu sehen.

@Decoratorpublic abstract class CheckoutServiceDecorator
    implements CheckoutService, Serializable {
   ...
  @Inject @HcoLogger
  private Logger logger;
  ...
}

Einsatzgebiete

Produzenten sind genau dann sinnvoll, wenn der Typ der zu produzierenden Klasse zur Laufzeit variiert bzw., wenn die Initialisierung individuell erfolgt.

Beispielapplikation

Friendly Invaders (deutsch: Freundliche Eindringlinge)

Um natürlich nicht einfach nur staubigen Quellcode zu lesen, sondern das Ganze auch in der Praxis zum Fliegen zu bringen, dient die Beispielapplikation „Friendly Invaders„.

Sinn und Unsinn

Die Beispielapplikation ermöglicht es Lesern, den Autoren von Blogbeiträgen in einem via RSS angebundenen Blog Anerkennung (Kudos) zu zeigen. Dazu befindet sich unter jedem Blogartikel ein „Give Kudos“ Button.

"Give Kudos" Button

Wurde dieser Button geklickt, wird das Kudos in einen Warenkorb gepackt. Wird auf den Warenkorb, der durch eine Bean im Conversation Scope implementiert wurde, geklickt, so wird ein einstufiger Checkout vollzogen und schließt den Prozess der Anerkennung ab.

cid des Conversation Scope als Parameter

cid des Conversation Scope als Parameter

Observer, Dekorator, Logger und Interzeptor erzeugen Text auf der Console, der ihre Aktivität zweifelsfrei belegen soll.

[STDOUT] Observer: Tweet: Rolf Dräther: Aus dem Leben einer User Story
[STDOUT] Observer: Mail: Rolf Dräther: Aus dem Leben einer User Story
[de.holisticon.blog.friendlyInvaders.decorator.CheckoutServiceDecorator]
Kudos and Money
[de.holisticon.blog.friendlyInvaders.interceptor.LoggingInterceptor]
checkout: Fri Dec 16 17:27:21 CET 2011
Lebensraum

Um die Applikation auszuführen, empfehle ich den JBoss 6 Application Server. Soll die Anwendung in Eclipse, mit Serveradapter für den JBoss 6 Application Server und API zum Editieren der beans.xml, zum Laufen gebracht werden, so müssen in Eclipse die JBoss Tools 3.2 installiert werden.

Zusammenfassung

Innerhalb des Vortrages wurde die Werkzeugkiste von CDI vorgestellt. Alle Werkzeuge erleichtern den Entwicklern von Applikationen die Arbeit erheblich und helfen, die Basics wie Entkopplung und Separation of Concerns umzusetzen.

Das Ziel, ein umfassendes DI Framework im Java EE Standard zu etablieren und eine bessere Verbindung zwischen JSF und EJB bzw. der Präsentationsschicht und Geschäftslogik herzustellen, wurde definitiv erreicht.

Ob CDI mit der Referenzimplementierung Weld in der Praxis in der Lage ist, Frameworks wie Spring oder Seam aus der Welt zu schaffen, wird sich zeigen.

Was ist eure Meinung dazu? Hat CDI das Zeug, Spring oder Seam als DI Frameworks zu verdrängen? Über Kommentare würde ich mich freuen.

Holisticon AG — Teile diesen Artikel

Über den Autor

Die Holisticon AG ist eine Management- und IT-Beratung aus Hamburg. Wir entwickeln beste Individualsoftware, Webplattformen und Apps. Geschäftsprozesse durchdringen wir und automatisieren sie. Große Datenmengen machen wir mit Smart-Data-Ansätzen beherrschbar. ...und das alles agil.

Antwort hinterlassen