Erweiterter Event-Mechanismus mit CDI

Interessiert mich – nicht!

Neben der eben gezeigten, dynamischen Erzeugung von Events, inklusive zugehörigem Qualifier, existiert noch eine zweite Variante der Laufzeitdynamisierung: Conditional Observer. Bei dieser Art von Qualifiern signalisiert man dem CDI-Container, dass ein Observer nur dann ein Event erhalten soll, wenn eine vordefinierte Bedingung erfüllt ist.

public void newArticleOberserverMethod(@Observes(receive= ...) 
    @Created article) {...}

Die Bedingung ist dabei nicht wirklich frei wählbar, denn es existiert eigentlich nur eine – genau genommen zwei – Option(en). Wählt man für receive=IF_EXISTS wird die Observer-Methode nur dann ausgeführt, wenn die zugehörige Bean existiert, also vom CDI-Container bereits erzeugt worden ist. Wählt man dagegen receive=ALLWAYS, den Default-Wert, springt die Observer-Methode immer an, was dann aber wiederum die initiale Erzeugung der Bean-Instanz zur Folge haben kann. Möglich wird dieser Mechanismus durch die Proxies der verschiedenen CDI Scopes. Es ist daher auch nicht erlaubt, eine Conditional-Oberserver-Methode mit Wert receive=IF_EXISTS in einer @Dependent Scope Bean zu deklarieren. Diese besitzt keinen Proxy und ist somit per Definition immer existent, sobald sie durch eine andere CDI Bean referenziert worden ist.

Es stellt sich nun zu Recht die Frage, in welch einem Szenario eine Conditional-Oberserver-Methode sinnvoll wäre. Denkbar wäre ein CDI-basiertes Cache-System, dessen Observer-Methoden entscheiden, ob und wann ein Neuladen des Caches sinnvoll ist. In einem derartigen Beispiel wäre es absolut sinnvoll, einen Cache nicht extra aufbauen zu müssen, nur um dann festzustellen, dass er nicht aktualisiert werden muss.

Interessiert mich – nicht immer!

Ebenfalls als eine Art Conditional Observer können auch die Transactional Observer Methods bezeichnet werden, in denen – mittels des during-Attributs – über eine zusätzliche Klassifizierung angegeben werden kann, in welcher Transaktionsphase bzw. bei welchem Transaktionsstatus die Observer-Methode ausgeführt werden soll.

public void newArticleOberserverMethod(@Observes(during= ...) 
    @Created article) {...}

Neben dem Default-Wert IN_PROGRESS, der eine sofortige Ausführung der Observer-Methode nach sich zieht, sind zusätzlich die folgenden Werte möglich:

  • BEFORE_COMPLETION: Ausführung während der before_completion-Phase einer Transaktion.
  • AFTER_COMPLETION: Ausführung während der afte_completion-Phase einer Transaktion.
  • AFTER_SUCCESS: Ausführung während der after_completion-Phase einer Transaktion, bei erfolgreicher Durchführung der Transaktion.
  • AFTER_FAILURE: Wie AFTER_COMPLETION, aber bei nicht erfolgreicher Durchführung der Transaktion.

Für die korrekte Ausführung ist an dieser Stelle wieder einmal der CDI-Container zuständig. Ist eine JTA-Transaktion aktiv, wird im Falle eines Werts BEFORE_COMPLETION oder AFTER_COMPLETION/_SUCCES/_FAILURE die Observer-Methode für eine spätere Abarbeitung während der entsprechenden Transaktionsphase vorgemerkt und somit der eigentlich synchrone Ablauf der Observer-Methode „delayed“. Andernfalls erfolgt die Ausführung umgehend.

Fazit

Bereits [1] hat gezeigt, mit wie wenig Code dank CDI der Aufbau einer Event-driven Architecture (EDA) realisiert werden kann. Der Verzicht auf Wrapper-Event-Objekte zu Gunsten von zusätzlichen Qualifiern erhöht dabei noch einmal die Transparenz und Lesbarkeit des Codes. Richtig interessant wird es aber, wenn erst zur Laufzeit entschieden wird, welcher Qualifier genutzt werden soll und die Observer-Methoden zusätzlich nur unter bestimmten Bedingungen und bestimmtemTransaktionsstatus ausgeführt werden. Eines sollte man aber bei aller Euphorie nicht vergessen. CDI Observer arbeiten aktuell noch synchron. Langlaufende Berechnungen haben dort also nichts zu suchen. Oder gibt es dafür etwa auch eine Lösung? Stay tuned!

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.