18. Juni 2013 | 2 min lesezeit

Immer wenn man einen Scope braucht, ist keiner da…

Im Bereich von Enterprise Webanwendungen hat sich der Gebrauch von CDI (bspw. in Verbindung mit JSF) als äußerst praktisch erwiesen. Durch die automatische Bindung von @RequestScoped und @SessionScoped Variablen an den jeweils aktiven Request bzw. die Session des Servers, hat man eine komfortable Lösung an der Hand seine Objekte im jeweiligen Kontext zur Anwendung zu bringen. Das kann allerdings auch Probleme nach sich ziehen, sobald man einmal gezwungen sein sollte sich außerhalb eines solchen Kontextes zu bewegen.

Ist das nicht eher ein theoretisches Problem?

Mancher mag sich an dieser Stelle vielleicht fragen, wann ein solcher Fall überhaupt auftritt. Wenn ich eine Webanwendung habe und ein User mit dieser interagiert, müsste ich dann nicht immer einen Request- oder Session-Scope zur Verfügung haben? Ja, dass stimmt … wenn ein User mit dieser interagiert. Zum Beispiel ist das nicht der Fall wenn die Webapplikation gerade im Begriff ist hoch- oder herunterzufahren. Auf dieses Problem gestoßen bin ich jedoch in einem Szenario bei dem, nach dem Timeout einer Session, noch "Aufräumarbeiten" zu erledigen waren und ich zu diesem Zweck einen Service verwendet habe in dem ein @RequestScoped EntityManager zum Einsatz kam. Jedes mal, wenn mein Code auf den EntityManager zugreifen wollte, wurde mir dies von meiner CDI-Implementierung (in diesem Fall Weld) mit folgender Meldung quittiert: org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.RequestScopedNach einigem Überlegen kam dann der Gedanke auf, dass bei einem Session-Timeout mit Sicherheit kein Request mehr aktiv sein dürfte, da es ja ansonsten gar nicht erst zu diesem Timeout gekommen wäre. Was konnte also getan werden?

Der Standard hilft nicht weiter

Die erste (ernüchternde) Erkenntnis ist, dass es kein standard-gemäßes Vorgehen gibt, um dieses Problem zu lösen. Sofern man nicht auf Drittlibraries wie beispielsweise Apache Deltaspike zurückgreifen kann oder möchte, ist man auf die jeweilige Implementierung der CDI-Spezifikation angewiesen. Ich möchte den Lösungsweg hier – wieder anhand von JBoss Weld – skizzieren.Weld bietet (im Falle eines Request Scopes) den sogenannten BoundRequestContext, um einen entsprechenden Kontext zu erzeugen. Beispiele für andere Scopes finden sich in der Dokumentation von Weld. Habe ich nun einen Methodenaufruf in dem ich einen solchen Request Scope benötige, erstelle ich mir vorher den Kontext und baue ihn danach wieder ab:

Und das packe ich jetzt um jeden Methodenaufruf?

Vom rein technischen Standpunkt her: Funktionieren würde es. Aber der gute Softwareentwickler in einem, schreit an dieser Stelle natürlich auf. Hier muss es einfach einen besseren Lösungsweg geben. Und da wir uns gerade näher mit den Interna von CDI befassen liegt es nahe auch bei CDI eine Lösung für dieses Problem zu suchen. Und diese Lösung finden wir auch. Das Stichwort lautet „Interceptor“. Wenn wir uns einen Interceptor schreiben, können wir unsere useRequestScopeInHere()-Methode einfach mit diesem Interceptor annotieren und schon wird bei jedem Aufruf ein RequestScope bereitgestellt.


Keine Kommentare

Kontakt

OPEN KNOWLEDGE GmbH

Standort Oldenburg:
Poststraße 1, 26122 Oldenburg

Standort Essen:
II. Hagen 7, 45127 Essen