FacesTales

Java EE 6: Mehr Annotations für die Entwickler

Lars Röwekamp und Matthias Weßendorf

Bisher lagen Java EE und Spring aufgrund stark abweichender Konzepte meilenweit auseinander. Dank der Vereinfachung des Programmiermodells in Java EE 5/6 und der Verwendung von Annotations in beiden Welten, scheint die Kluft langsam, aber sicher kleiner zu werden. Und dies hat direkte Auswirkungen auf die JSF2-Welt…

ManagedBeans mit JSF 2.0

Mit JSF2 gibt es ein neues (optionales) javax.faces.bean-Paket, dass unter anderem neben verschiedenen Scopes auch die @ManagedBean/ManagedProperty Annotations enthält. Statt wie bisher die Beans innerhalb der faces-config.xml zu beschreiben, kann die Deklaration nun direkt innerhalb der Java-Klasse erfolgen:

@javax.faces.bean.ManagedBean
@javax.faces.bean.RequestScoped
public class MyBean
{
  ...
      @ManagedProperty(...) private Service myService;
}

Eine so annotierte Bean kann im Anschluss über den #{myBean}-Ausdruck innerhalb der Expression Language angesprochen werden. Soweit so gut. Doch nicht nur die JSF-Spezifikation bedient das weite Feld der „managed beans“ innerhalb des Java-EE-6-Universums.

Wer die Wahl hat…

Durch die Enterprise Editon Version 6 steht mit „Contexts and Dependency Injection for the Java EE platform“ ein ganz neuer Standard bereit. Ursprünglich sollte der zugehörige JSR 299 dazu dienen, das JBoss Seam-Framework zu standardisieren, oder besser gesagt, die darin enthaltenen Ideen. Aber wie so oft, kam es in der Praxis anders, als in der Theorie geplant: Das Grundkonzept des „Dependency Injection“ wurde abstrahiert und in einen eigenen, deutlich kleineren JSR 330 (Dependency Injection for Java) ausgelagert. Der gesamte Standard besteht aus lediglich fünf Annotationen sowie einem Interface. Die beiden wichtigsten Annotationen sind:

  • @Inject: Der Injection Point innerhalb einer „managed bean“
  • @Named: Stellt „managed beans“ unter einem bestimmten Namen bereit

Da die JSRs 299/330 fester Bestandteil von Java EE 6 sind, das javax.faces.bean-Packet aber nicht, empfiehlt es sich, die JSF-basierten Annotationen erst gar nicht zu benutzen. Die oben bereits gezeigte Bean würde unter Verwendung der eben beschriebenen JSRs wie folgt aussehen:

@javax.inject.Named
@javax.enterprise.context.RequestScoped
public class MyBean
{
  ...
      @Inject private Service myService;
}

´

Der Unterschied ist nicht dramatisch. Und auch außerhalb eines Java EE Containers kann der CDI-Standard + JSR 330 genutzt werden. Sowohl JBoss Weld als auch Apache OpenWebBeans haben Beispiele für die Integration in Servler-Container wie Apache Tomcat. Diese Tatsache untermauert die neue Leichtgewichtigkeit von vielen Java-EE-(Teil-)Technologien!

Allerdings steht im Rahmen von Java EE 6 – leider – noch eine weitere Annotation bereit, um „managed beans“ (oder lightweight components) zu kennzeichnen: @javax.annotation.ManagedBean. Der Lebenszyklus dieser Beans wird vom Container verwaltet, und neben der @Resource Injection unterstützt dieser zusätzlich die bekannten Callbacks der @PostConstruct- and @PreDestroy-Annotationen.

… hat die Qual

Damit wäre nun die Verwirrung perfekt: drei Unterschiedliche Werkzeuge für ein Konzept. Da JSF2 früher als der Rest von Java EE fertig gestellt wurde, könnte man meinen, dass die JSF-basierten Annotationen durchaus sinnvoll sind. Dem ist aber nicht so. JSF verfügt zwar schon seit der Version 1.0 über einen IoC/DI „Container“, allerdings ist dieser schwach im Vergleich zu den Alternativen am Markt. Wurde beispielsweise eine Anwendung mit JSF 1.2 und Spring erstellt, so wurden nur in den seltensten Fällen die JSF Beans innerhalb der faces-config.xml verwaltet. Ähnlich sieht es mit JSF 2.0 und seinen neuen Annotations aus: Von der Idee her O. K., allerdings im praktischen Einsatz (fast) nutzlos. Daher macht es mehr Sinn, wie bereits erwähnt, die JSF Beans mit den Möglichkeiten der Standards 299/330 zu annotieren. CDI selbst bietet weitere interessante Möglichkeiten für die Injektion von 3rd-party-/legacy-Objekten oder die Bereitstellung von Extensions. Das Apache MyFaces-Projekt arbeitet derzeit mit dem OpenWebBeans Project an nützlichen Erweiterungen für den JSR 299.

Und was ist mit Spring?

Selbstverständlich läuft nicht die gesamte Java-Enterprise-Welt mit Java EE 6 ab. Somit stellt sich die Frage, inwieweit die oben beschriebenen Annotations auch von Spring unterstützt werden. Schließlich stellt Spring seit der Version 2.x eigene Annotations für „managed beans“ (oder components) sowie das Scoping bereit. Mit Spring 3.x wird der JSR 330 unterstützt, allerdings nicht CDI (JSR 299). Rein technisch hat das zur Folge, dass unsere Beispiel-Bean ein wenig anders daherkommt als bisher:

@javax.inject.Named
@org.springframework.context.annotation.Scope("request")
public class MyBean
{
  .
  @Inject private Service myService;
}

Der Unterschied zur einer Java EE Bean ist ein wenig größer: Der Bean Scope wird durch ein proprietäres Spring-API bestimmt. Ansonsten wird, wie bei Java EE auch, auf den JSR 330 zugegriffen, d. h. das Injizieren von konkreten Dependencies erfolgt auch hier mithilfe der neuen @Inject-Annotation. Die Nutzung der JavaEE Scopes innerhalb von Spring kann jedoch über eine einfache Brücke realisiert werden.

Dank des JSRs 330 kann der Programmierer somit glücklicherweise in beiden Welten auf einen kleinen, aber feinen Standard zurückgreifen, um „managed beans“ und deren injection zu realisieren.

Fazit und Ausblick

Der klare Gewinner innerhalb von Java EE 6 ist CDI (JSR 299). Er bietet innerhalb der Enterprise Edition und somit auch für JSF2 interessante Möglichkeiten, die in weiteren Kolumnen beleuchtet werden. Unabhängig von der reinen Java-EE-Welt ist der JSR 330 ein Standard, der eine Brücke zwischen verschiedenen Welten (Spring vs. Java EE) bildet. P.S: Auch ohne Spring und Java EE kann der JSR 330 mit Google Guice2 genutzt werden – mehr einheitliche und übergreifende Standards sind ein gutes Zeichen für das gesamte Java Ecosystem.

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).

Geschrieben von
Lars Röwekamp und Matthias Weßendorf
Kommentare

Schreibe einen Kommentar

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