Meins oder deins? JSF 2.0 Scopes unter der Lupe

Java EE Scopes

Bereits in der letzten Ausgabe haben wir auf die Vorzüge der beiden JSRs 229 und 330 hingewiesen. Gleichzeitig haben wir am Beispiel der Annotationen @ManagedBean (JSF 2.0) und @Named (JSR 330) gezeigt, dass es einige Features gibt, die sowohl im JSF- als auch im JSR-299/330-Umfeld redundant vorhanden sind, und empfohlen, sich in der Welt von Java EE 6 auf die beiden JSRs 299 und 330 zu fokussieren. Ein ähnliches Bild ergibt sich auch für die Scopes. Auch hier gibt es starke Überschneidungen, da auch der JSR 299 die drei Scopes @RequestScoped, @SessionScoped, @ApplicationScoped zur Verfügung stellt. Interessant ist, dass es neben diesen drei genannten Scopes noch einen weiteren gibt, der bisher noch keinen Einzug in die JSF Spezifikation gefunden hat und daher bei Bedarf mithilfe von Zusatzbibliotheken bedient werden muss: @ConversationScope.

Anders als man das vielleicht vermuten würde, ist der Standard-Lifecycle einer Conversation gleichzusetzen mit dem Lifecycle eines Requests. Soll eine Conversation über mehrere Requests aufgespannt werden, muss sie als long-running gekennzeichnet und deren Start und Ende explizit programmiert werden. Zu diesem Zweck liefert CDI eine Build-in Bean vom Typ Conversation. Listing 1 zeigt ein entsprechendes Beispiel aus der CDI-Referenzimplementierung Weld [1].

Listing 1: Conversation in Aktion
@ConversationScoped 
@Stateful 
public class OrderBuilder { 

   private Order order; 
   private @Inject Conversation conv; 
   private @PersistenceContext(type = EXTENDED) EntityManager em; 
    
   ...
   public Order createOrder() { 
      order = new Order(); 
      conv.begin(); 
      return order; 
   } 
       
   public void saveOrder(Order order) { 
      em.persist(order); 
      conv.end(); 
   } 
    
   @Remove 
   public void destroy() {} 
}

Wie im Listing zu sehen, wird die Conversation in der Methode createOrder() mittels conv.begin() gestartet und in der Methode saveOrder() durch den Aufruf von conv.end() wieder beendet. Auch wenn der CDI Conversation Scope eine deutliche Verbesserung im Vergleich zu den JSF 2.0 Scopes darstellt, ist bei Weitem noch nicht die Funktionalität und der Komfort erreicht, wie man es von anderen 3rd Party Frameworks gewohnt ist. Es kommt zum Beispiel regelmäßig zu Problemen bei der parallelen Nutzung von Ajax Requests. Dass dies auch besser gelöst werden kann, zeigen alternative Lösungen wie Apache MyFaces Orchestra oder Apache MyFaces Trinidad [2], [3].

Missing Pieces

Verzichtet man zu Gunsten der allgemein gültigen CDI Scopes auf die spezifischen JSF Scopes, dann ergibt sich ein kleines aber nicht zu vernachlässigendes Problem. CDI bietet keinen View Scope an. CDI hat die Aufgabe, schichtenübergreifend technologieneutrale Features zur Verfügung zu stellen. Der JSF View Scope aber ist ausschließlich für die Präsentationsschicht konzipiert. Möchte man trotzdem CDI statt JSF Scopes nutzen und gleichzeitig nicht auf den View Scope verzichten, lässt sich dank des CDI Extensible Context Model ein eigener View Scope relativ einfach nachbauen. Ein Beispiel, wie das im Detail aussehen kann, findet sich im Blog von Steven Verborght [4]. Sowohl Apache OpenWebBeans [5] als auch Weld bieten eine @ViewScoped-Unterstützung an.

Ein ebenfalls interessanter Kandidat für die Zukunft stellt das noch junge Apache-MyFaces-Extensions-CDI-Projekt dar, das einen Teil der heute in Apache MyFaces Orchestra verfügbaren Features – und natürlich einige mehr – auf Basis von CDI anbieten wird.

Fazit

Die neuen JSF 2.0 Scopes sind ein erster wichtiger Schritt in die richtige Richtung. Schmerzlich vermisst wird nach wir vor ein @ConversationScoped zur Realisierung von typischer Wizard-Funktionalität. Dieser wiederum ist, genau wie die Klassiker @RequestScoped, @SessionScoped und @ApplicationScoped, Bestandteil der CDI-Spezifikation. Somit steht einer Verwendung von CDI nur das Fehlen des JSF-spezifischen @ViewScoped entgegen, der sich dank Extensible Context Model aber in CDI leicht nachimplementieren lässt.

Wie schon in der letzten Kolumne für die Managed Beans gilt also auch für die Scopes, dass einem Wechsel von der auf die Präsentationsschicht zugeschnittenen JSF-Variante hin zur allgemeinen CDI-Variante nichts im Weg steht. In der Praxis muss allerdings die Frage erlaubt sein, ob das gesamte Thema der Scopes nicht besser in einem generischen Layer behandelt werden sollte. Anstatt mehrere APIs mit demselben Ziel zu spezifizieren, scheint es durchaus sinnvoll zu sein, das Thema Scopes an einer zentralen Stelle zu platzieren, von der dann alle Webframeworks partizipieren können. Als möglicher Kandidat bietet sich die Servelt-Spezifikation an [6].

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 Oracle an einer Server-side-Push-Lösung für ADF Faces. Er ist PMC Chair von Apache MyFaces. Matthias blogt regelmäßig auf http://matthiaswessendorf.wordpress.com (Twitter: @mwessendorf).

Kommentare

Schreibe einen Kommentar

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