Alles Ansichtssache: Spaß mit @Scopes

Wo bleibt der Spaß?

Bisher waren die Beispiele noch recht transparent und nachvollziehbar. Entscheidend für das Verhalten der Anwendung ist vor allem die Frage: Normal Scope oder Pseudo Scope? Richtig spannend wird es allerdings erst, wenn man einmal einen tieferen Blick riskiert. Was passiert z. B. mit unserer Anwendung, wenn es zum Zeitpunkt des Injizierens gar keinen angemeldeten User gibt? Hier würde man zunächst einmal erwarten, dass die Anwendung ein null zurück liefert. Dies ist allerdings nur bei Dependent Scope, nicht aber bei den Normal Scopes der Fall. Die Erklärung liegt auf der Hand: Normal Scopes arbeiten mit einem Proxy. Eine Abfrage auf null würde also lediglich testen, ob der Proxy null ist, was per Definition niemals der Fall sein kann. Eine mögliche Lösung könnte so aussehen, dass die Producer-Methode immer einen gültigen Wert liefert, der durch einen Default-Wert – in unserem Fall beispielsweise einem AnonymousUser – vorbelegt wird. Damit der Nutzer eines injizierten Objekts nicht wissen muss, ob es sich um ein Dependent-Scope- oder Normal-Scope-Objekt handelt, wäre es sinnvoll, das gleiche „never null“-Pattern auch bei Producern zu verwenden, die Objekte im Dependent Scope erzeugen. Eine Alternative wäre es an dieser Stelle, mit einem CDI Provider zu arbeiten. Dazu aber später mehr.

Im obigen Beispiel haben wir betrachtet, was passiert, wenn das zu injizierende Objekt nicht existiert. Wie aber sieht es aus, wenn der zugehörige Scope noch gar nicht aufgebaut wurde? Nehmen wir für unser Beispiel einmal an, dass ein Logger grundsätzlich auch den angemeldeten User mit ins Log schreibt und die zugehörige Producer-Methode diesen, wie in Listing 2 gezeigt, im Session Scope erzeugt. Kommt der Logger nun beim Hochfahren der Anwendung zum Einsatz, bekommen wir ein Problem in Form einer ContextNotActiveException. An dieser Stelle muss also sichergestellt sein, dass entweder der Scope bereits existiert oder es alternativ nicht zum Injizieren kommt.

Als Letztes wollen wir uns noch das Zusammenspiel von JPA-Entitäten und CDI Beans anschauen. Prinzipiell spricht erst einmal nichts dagegen, eine JPA-Entität zu injizieren. In unserem Beispiel wäre also vorstellbar, dass es sich bei dem aktuellen, im Session Scope erzeugten User um eine JPA-Entität handelt. Was passiert nun aber, wenn diese Entität aus dem Injection Target heraus verändert und gespeichert werden soll? Da das Injection Target nur Zugriff auf den Proxy (aka Contextual Reference), nicht aber auf die Entität selbst (aka Contextual Instance) hat, kommt es hier zu einem gewaltigen Problem. Was also tun? Als erste Alternative bietet es sich an, sich eine Bean im Dependent Scope injizieren zu lassen. Damit verbunden sind natürlich alle bereits geschilderten Nachteile. Eine zweite Alternative wäre es, vor dem Verändern bzw. Speichern der Entität diese noch einmal direkt aus der Datenbank oder dem Cache zu laden, um so die echte Entität und nicht nur den Proxy im Zugriff zu haben. Als dritte Alternative wäre es denkbar, sich anstelle des User Proxy einen User Provider injizieren zu lassen:

@Inject @Authenticated Provder userProvider;

Im Gegensatz zum Proxy erlaubt der Provider via get()-Methode einen direkten Zugriff auf die Contextual Instance und somit auf die JPA-Entität.

Fazit

Bereits diese kleinen Beispiele zeigen, dass CDI Scopes ein enormes Potenzial mit sich bringen – hat man einmal den wesentlichen Unterschied zwischen Pseudo Scope und Normal Scope verstanden. Dem Potenzial gegenüber steht die Gefahr, durch falsche Nutzung unerwünschte Nebeneffekte zu produzieren. Um zu verhindern, dass im Injection Point Kenntnisse über die Art der Erzeugung des zu injizierenden Objekts vorhanden sein müssen, bieten sich verschiedenen Patterns an, die konsequent innerhalb der Anwendung eingesetzt werden sollten.

Lars Röwekamp ist Geschäftsführer der open knowledge 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. Er bloggt regelmäßig auf http://matthiaswessendorf.wordpress.com (Twitter: @mwessendorf).

Kommentare

Schreibe einen Kommentar

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