GEDOPLAN
Jakarta EE (Java EE)

CDI: Injektionen filtern nach Modulzugehörigkeit

Jakarta EE (Java EE)

In der vergangenen Woche habe ich in unseren Seminarräumen in Berlin ein Training Java EE Masterclass durchgeführt, worin neben JPA, EJB und JSF auch das Thema CDI behandelt wird. Mit den engagierten Teilnehmern entwickelte sich insbesondere am Kursende eine interessante Diskussion zu diversen weiterführenden Themen, u. a. darüber, ob es möglich sei, eine Bibliothek so aus CDI-Komponenten aufzubauen, dass diese innerhalb der Bibliothek beliebig zur Injektion bereit gestellt werden, eine die Bibliothek nutzende Anwendung jedoch nur bestimmte Beans daraus angeboten bekommt, also bspw. so:

  • Library cdi-injectfilter-lib
    • definiert einen Service GreetingService, der mit Hilfe eines weiteres Services PartOfDayService realisiert wird.
    • GreetingService und PartOfDayService sind CDI Beans, die mittels Injektion miteinander verknüpft werden.
  • Anwendung cdi-injectfilter-web
    • nutzt GreetingService aus cdi-injectfilter-lib mittels Injektion,
    • soll PartOfDayService nicht (mittels Injektion) nutzen.

Die spontane Idee, PartOfDayService durch Annotation mit @Vetoed (bzw. @Typed) aus dem (CDI-) Rennen zu nehmen, greift zu kurz, weil dann nicht nur die Injektion eines PartOfDayService in cdi-injectfilter-web verhindert wird, sondern die Nutzung von PartOfDayService als CDI Bean generell, also auch in cdi-injectfilter-lib, unterdrückt wird.

Gesucht ist also eine Möglichkeit, die Injektion einer CDI Bean in Abhängikeit vom Injektionsziel zu erlauben oder verwehren. Dies gelingt relativ einfach damit, dass die betreffende Bibliothek – im Beispiel cdi-injectfilter-lib – zu einer CDI Extension gemacht wird. Dann können mit Hilfe eines Observers für den Lifecycle Event, den der Container während des Anwendungsdeployments für eine Injektionsstelle feuert, unerwünschte Injektionen abgelehtn werden.

Die folgenden Schritte sind dafür nötig:

  • Bibliothek zu einer CDI Extension machen:
    • Klasse als Implementierung von javax.enterprise.inject.spi.Extension entwerfen und im Service Descriptor META-INF/services/javax.enterprise.inject.spi.Extension registrieren
      (⇒de.gedoplan.beantrial.cdi.injectfilter.lib.extension.InjectFilterExtension),
    • darin eine Observer-Methode für den Event ProcessInjectionPoint<T, X> vorsehen. Diese Methode wird vom Container während des initialen Scans für jeden erkannten Injektionspunkt aufgerufen. Am übergebenen Event-Objekt kann man erkennen, was wohin injiziert werden soll. Unerwünschte Kombinationen können durch Aufruf der Event-Methode addDefinitionError mit Schimpf und Schande belegt werden.
  • Zur Unterscheidung der nur innerhalb des Bibliotheksmoduls frei nutzbaren Beans von denen, die auch ausserhalb injizierbar sein sollen, empfiehlt sich die Einführung eines entsprechenden CDI Qualifiers
    (⇒de.gedoplan.beantrial.cdi.injectfilter.lib.LibraryService).
    Die Injektion innerhalb der Library geschieht dann (natürlich) ausschliesslich unter Nutzung dieses Qualifiers.
    In der o. a. Observer-Methode können die betroffenen Injektionsstellen anhand des Qualifiers erkannt werden und Injektionen in Ziele ausserhalb der Library abgelehnt werden.
  • Eine unerwünschte Injektion sollte nun mit einen Deployment-Fehler belegt sein
    (⇒de.gedoplan.beantrial.cdi.injectfilter.web.presentation.ServicePresenter).

Der gesamte Beispielcode mit den genannten Klassen (⇒ …) findet sich auf GitHub.

Es sei darauf hingewiesen, dass die geschilderte Lösung ein paar kleine Contras hat:

  1. Der Beispielcode macht die “Injektionserlaubnis” am Paket der Zielklasse fest. Das setzt eine “gutmütige” Paketstruktur voraus. Würde ein(e) “kreative(r)” Entwickler(in) der nutzenden Anwendung die Beans in Paketen platzieren, deren Name mit denen der genutzten Bibliothek übereinstimmen, würde er/sie die Injektionseinschränkung damit umgehen.
  2. Ebenfalls umgehen ließe sich die Injektionseinschränkung durch die Bereitstellung eines passenden Producers in der aufrufenden Anwendung.
  3. Die Einschränkung wird erst zum Deployent-Zeitpunkt erkennbar. Eine IDE wie Eclipse oder NetBeans wird vorher nicht warnen, wenn eine unerwünschte Injektion programmiert wird.

Die ersten beiden Nachteile treten bei “gutmütiger” Softwareentwicklung nicht auf. Oder anders gesagt: Denen mit zuviel kreativer Energie kann so nicht geholfen werden. Der dritte Nachteil wird durch die empfohlene Nutzung eines Qualifiers zumindest weitgehend entschärft – soweit der Quallifier nicht kreativ misbraucht wird – aber das hatten wir ja schon.

Viel Spass/Erfolg mit komponentenbasierter Softwareentwicklung auf Basis von Java EE!

Zur Vertiefung sei auf unser umfangreiches Seminarangebot hingewiesen: GEDOPLAN IT Training. Alle Kurse gibt es auch kundenspezifisch angepasst!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Bitte füllen Sie dieses Feld aus.
Bitte füllen Sie dieses Feld aus.
Bitte gib eine gültige E-Mail-Adresse ein.
Sie müssen den Bedingungen zustimmen, um fortzufahren.

Autor

Diesen Artikel teilen

LinkedIn
Xing

Gibt es noch Fragen?

Fragen beantworten wir sehr gerne! Schreibe uns einfach per Kontaktformular.

Kurse

weitere Blogbeiträge

IT-Training - GEDOPLAN
Jakarta EE (Java EE)

JPA mit dynamischer DB-Verbindung

In Java-EE-Anwendungen, die JPA zum DB-Zugriff nutzen, wird im Normalfall eine Datasource zur Spezifikation der Datenbankverbindung genutzt: &lt;persistence ...&gt; &lt;persistence-unit…

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!