Apache MyFaces CDI Extensions - JAXenter
FacesTales

Apache MyFaces CDI Extensions

Treue Fans der JSF-Kolumne haben bereits in der Ausgabe 8.2010 mit einigen Features von CDI Bekanntschaft gemacht. Damals ging es um die neuen Scopes von JSF 2 und denen des JSR 299. Ein weiterer großer Vorteil von CDI liegt in der Möglichkeit zur Entwicklung von Erweiterungen. Diesen Weg geht das Apache-MyFaces-CODI-Projekt und bietet CDI-basierte Erweiterungen sowie neue Scopes für die Programmierung von Java-EE-Anwendungen.

Wozu CODI? Was ist Orchestra?

Anders als viele vielleicht vermuten, legt MyFaces schon seit Langem den Fokus auf den ganzheitlichen Java Web Application Stack und zielt somit nicht nur auf den View/JSF-Bereich einer Webanwendung ab. Dank CDI stehen in diesem Umfeld neue Möglichkeiten, z. B. der Conversation Scope, zur Verfügung. Der CDI Conversation Scope stellt eine deutliche Verbesserung im Vergleich zu den JSF 2.0 Scopes dar, bietet aber leider immer noch nicht die Funktionalität und den Komfort, den man von anderen 3rd-Party-Frameworks gewohnt ist. Orchestra [1], [2] beispielsweise bietet die Möglichkeit, den Lifecycle einer Conversation unterschiedlich zu bestimmen:

  • access: Die Conversation startet automatisch mit der Referenzierung einer Bean. Sie lebt so lange, wie sie auf XHTML-Seiten des Navigation Flow referenziert wird. Wird eine Bean mit dem access view scope nicht mehr verwendet, so wird sie automatisch entfernt.
  • manual: Die Conversation startet ebenfalls automatisch, allerdings muss sie explizit, z. B. über einen entsprechenden API-Aufruf, beendet werden.

Bei dem CDI-Standard-Conversation-Scope ist dies ein wenig anders. Soll eine Conversation über mehrere Requests aufgespannt werden, muss sie als long-running gekennzeichnet und ihr Start und Ende müssen explizit programmiert werden (via javax.enterprise.context.Conversation: end()/begin()). Genau diese Lücke möchte CODI schließen und tritt an, um Orchestra-Features auf Basis des CDI-Standards zu realisieren. Dazu führt es drei neue Annotationen ein: @ConversationScoped, @WindowScoped und @ViewAccessScoped ein.

Die „@ConversationScoped“-Annotation

Der conversation Scope ähnelt dem von CDI, wird aber automatisch gestartet und kann somit einfach über mehrere Requests hinweg verwendet werden. Probleme wie die BusyConversationException bei parallelen AJAC-Requests treten mit dem CODI Scope nicht auf. Auch in MyFaces CODI gibt es eine (Default) Bean, um die Conversation manuell zu beenden (Listing 1).

Listing 1: CODI’s Conversation Scope
@Named
@ConversationScoped
public class CodiConversationBean implements Serializable {

  // Entity Manager injection
  @PersistenceContext private EntityManager em;

  // CODI Conversation injection
      @Inject private Conversation conversation;
  ...
      public String checkout() {         em.persist(......);         conversation.end();         ...       }
   }

Beim Aufruf der checkout()-Action-Methode wird die Bean verworfen. Sollte die angezeigte Seite nach diesem Aufruf ebenfalls die codiConversationBean Bean benutzen, so wird automatisch ein neues Objekt erzeugt. Beim Lesen des Codes ist zu beachten, dass die Conversation Bean und Annotation denselben Namen wie im CDI-Standard besitzen, jedoch kommen die CODI-Klassen aus einem anderen Package (org.apache.myfaces.extensions.cdi.core.api.scope.conversation). Der Timeout-Wert des Conversation Scope liegt bei 30 Minuten.

Der „@WindowScope“

Der window Scope funktioniert ähnlich wie der ConversationScope. Auch er wird automatisch gestartet und muss, wenn gewünscht, über dasselbe API beendet werden. Der große Unterschied zum ConversationScope ist der, dass eine Bean dieses Gültigkeitsbereichs keinen Timeout besitzt. Ein @WindowScoped Bean kann konsequent über sämtliche POSTBACKs verwendet werden. Die gleiche Instanz der Bean wird ebenfalls in einem neuen Tab/Window benutzt, wenn der windowId-Parameter korrekt übermittelt wird. Dieses Verhalten lässt sich gut als „Session per Window“ beschreiben (Listing 2).

Listing 2: Der Window Scope
@Named
@WindowScoped     public class WindowBean implements Serializable { 
  // Entity Manager injection
  @PersistenceContext private EntityManager em;

  // CODI Conversation injection
      @Inject private Conversation conversation;
  ...
  public String checkout() {
    em.persist(......);
    conversation.end();
    ...
  }
}

Innerhalb der checkout()-Methode wird die Bean durch den conversation.end()-Aufruf verworfen. Sämtliche anderen (laufenden) Conversation bleiben jedoch bestehen. Der obere Aufruf beendet immer nur die Conversation der aktuellen Bean. Allerdings ist es möglich, sämtliche Beans, egal ob @WindowScoped oder @ConversationScoped, auf einen Schlag zu beenden (Listing 3).

Listing 3: Reset sämtlicher Conversations
...
 // CODI windows context injection
      @Inject private WindowContext windowContext;       ...
  public String checkout() {
    em.persist(......);
    windowContext.end()
    ...       }
...
Die Nutzung von „@ViewAccessScoped“

Der ViewAccess Scope von CODI stellt den einfachsten der drei neuen Scopes dar. Enthält eine XHTML-Seite eine Bean mit diesem Scope, so wird die Conversation gestartet. Wie bei dem Window Scope gibt es ebenfalls keinen Timeout-Wert für Beans dieses Scopes. Allerdings werden die Beans wieder verworfen, sobald sie nicht mehr innerhalb einer View genutzt werden. CODI entfernt die Beans dann automatisch aus dem Speicher (Listing 4).

Listing 4: ViewAccess Scope von MyFaces CODI
@Named
@ViewAccessScoped
public class ViewAccessBean implements Serializable { 
  // Entity Manager injection
  @PersistenceContext private EntityManager em;
  ...
  public String checkout() {
    em.persist(......);         ...
  } 
}
Weitere CODI-Module

Neben den vorgestellten CDI Scopes, die durch Orchestra inspiriert wurden, stellt CODI noch weitere Module bereit. Für den JSR-303 (BeanValidation) wird beispielsweise ein CDI Producer für BeanValidation-Artefakte (z. B. ValidatorFactory oder Validator) angeboten. Besonders interessant ist das JSF-1.2-Modul von CODI: Sämtliche CDI-Features sind dank dieses Moduls nicht nur mit dem neuen JSF-2-Standard, sondern auch mit der alten Version 1.2 nutzbar. Aber nicht nur die Java-EE-Welt wird durch CODI angesprochen. Für Java SE gibt es in CODI ein CDI-basiertes Message API. Der Fokus liegt hier auf einer besseren i18n-Unterstützung mit einem Fluent API.

Fazit

Apache MyFaces CODI ist ein recht junges Projekt, das versucht, die Lücken und Probleme der CDI-Spezifikation geschickt zu schließen. Zusätzlich werden deutlich Mehrwerte durch einige bereits bestehende Module geboten. Die CODI-Features wurden nicht im häufig zitierten Elfenbeinturm erfunden, sondern durch explizite Anforderungen aus der Web-Developer-Community heraus entwickelt. Die Kolumne zeigte, wie in CODI geschätzte Orchestra-Features auf das einheitliche CDI-Programmiermodell portiert wurden. Für die Zukunft hat das CODI-Team weitere Features in Planung. Auf Github [3] gibt es ein kleines Beispiel der verschieden Scopes auf Basis von MyFaces 2.0.2, MyFaces CODI sowie Apache OpenWebBeans.

Lars Röwekamp ist Geschäftsführer der OpenKnowledge GmbH und berät seit mehr als zehn Jahren Kunden in internationalen Projekten rund um das Thema Enterprise Computing (Twitter: @mobileLarson).

Matthias Weßendorf arbeitet für die Firma Kaazing. Dort beschäftigt er sich mit WebSocket, HTML5 und weiteren Themen rund um das „Next Generation Web“. Matthias bloggt regelmäßig auf http://matthiaswessendorf.wordpress.com (Twitter: @mwessendorf).

Kommentare

Schreibe einen Kommentar

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