Backing Beans (@ManagedBean) oder CDI Beans (@Named)?

109

Ich habe gerade angefangen, Core JavaServer Faces, 3. Ausgabe, durchzulesen. und sie sagen dies (Hervorhebung von mir):

Es ist ein historischer Zufall, dass es zwei separate Mechanismen gibt, CDI-Beans und JSF-verwaltete Beans für Beans, die in JSF-Seiten verwendet werden können. Wir empfehlen, CDI-Beans zu verwenden, es sei denn, Ihre Anwendung muss auf einem einfachen Servlet-Runner wie Tomcat ausgeführt werden.

Warum? Sie liefern keine Rechtfertigung. Ich habe @ManagedBeanfür alle Beans in einer Prototyp-Anwendung verwendet, die auf GlassFish 3 ausgeführt wird, und ich habe keine wirklichen Probleme damit bemerkt. Es macht mir nichts aus @ManagedBean, von nach zu migrieren @Named, aber ich möchte wissen, warum ich mich darum kümmern sollte .

Matt Ball
quelle
4
@Bozho: Diese Frage ist ziemlich ähnlich, aber nachdem ich Pascals Antwort einige Male durchgelesen habe, verstehe ich immer noch nicht, warum CDI weit überlegen ist. Ich kenne CDI nicht und bin froh, es zu lernen, da es "besser" ist. Warum ist es besser?
Matt Ball
"Es sei denn, Ihre Anwendung muss auf einem einfachen Servlet-Runner wie Tomcat funktionieren." Ich verwende nur Tomcat und empfehle dringend CDI. Tomcat kann es gut unterstützen
Karl Kildén
1
@ KarlKildén "einfacher Servlet-Runner" bezieht sich auf einen nicht CDI-fähigen Servlet-Container. Zum Zeitpunkt des Schreibens unterstützte Tomcat CDI nur mit ein wenig Magie.
Thorbjørn Ravn Andersen

Antworten:

64

CDI wird gegenüber einfachem JSF bevorzugt, da CDI eine JavaEE-weite Abhängigkeitsinjektion ermöglicht. Sie können auch POJOs injizieren und verwalten lassen. Mit JSF können Sie nur eine Teilmenge dessen einfügen, was Sie mit CDI können.

Bozho
quelle
Grundsätzlich kann ich eine Instanz von fast jeder Klasse (vorausgesetzt, sie hat "das richtige Zeug" - was ist das, nur ein Konstruktor ohne Argumente? ) Mit CDI @ManagedBeaninjizieren , während ich sie verwenden muss, wenn ich sie mit Plain injizieren möchte JSF?
Matt Ball
3
@MattBall Matt, können Sie nach Ihren Jahren diese Migration kommentieren?
Koray Tugay
5
@KorayTugay Ich habe diesen Code seit Juni 2011 nicht mehr berührt, aber ich war zu CDI gewechselt und die Dinge funktionierten einwandfrei. Gerne beantworte ich bestimmte Fragen nach bestem Wissen und Gewissen, wenn Sie sie haben.
Matt Ball
170

Verwenden Sie CDI.

Gemäß JSF 2.3 @ManagedBeanist veraltet . Siehe auch Spezifikationsausgabe 1417 . Dies bedeutet , dass es nicht mehr ein Grund , wählen @ManagedBeanüber @Named. Dies wurde erstmals in der Beta-Version m06 von Mojarra 2.3.0 implementiert.

Geben Sie hier die Bildbeschreibung ein


Geschichte

Der Hauptunterschied besteht darin, dass @ManagedBeanes vom JSF-Framework verwaltet wird und nur über @ManagedPropertyandere JSF-verwaltete Beans verfügbar ist. @Namedwird durch Anwendungsserver (der Behälter) über CDI Rahmen und ist über verwaltete zur @InjectVerfügung , um jede Art von einem Container verwaltet Artefakt wie @WebListener, @WebFilter, @WebServlet, @Path, @Stateless, etc. und sogar ein JSF @ManagedBean. Von der anderen Seite auf, @ManagedPropertywird nicht funktionieren innerhalb einer @Namedoder einem anderen Container verwaltet Artefakt. Es funktioniert wirklich nur drinnen @ManagedBean.

Ein weiterer Unterschied besteht darin, dass CDI tatsächlich Proxys, die an die aktuelle Instanz delegiert werden, im Zielbereich pro Anforderung / Thread injiziert (z. B. wie EJBs injiziert wurden). Dieser Mechanismus ermöglicht das Injizieren einer Bean eines engeren Bereichs in eine Bean eines breiteren Bereichs, was mit JSF nicht möglich ist @ManagedProperty. JSF "injiziert" hier die physische Instanz direkt durch Aufrufen eines Setters (genau deshalb ist auch ein Setter erforderlich, während dies bei nicht erforderlich ist @Inject).

Obwohl dies nicht direkt ein Nachteil ist - es gibt andere Möglichkeiten -, ist der Umfang @ManagedBeaneinfach begrenzt. Aus der anderen Perspektive können Sie, wenn Sie nicht "zu viel" aussetzen möchten, @Injectauch einfach Ihre verwalteten Bohnen behalten @ManagedBean. Es ist wie protectedgegen public. Das zählt aber nicht wirklich.

Zumindest in JSF 2.0 / 2.1 besteht der Hauptnachteil der Verwaltung von JSF-Backing-Beans über CDI darin, dass es kein CDI-Äquivalent zu gibt @ViewScoped. Das @ConversationScopedkommt nahe, erfordert aber immer noch das manuelle Starten und Stoppen und hängt einen hässlichen cidAnforderungsparameter an die Ergebnis-URLs an. MyFaces CODI macht es einfacher, indem JSFs vollständig transparent javax.faces.bean.ViewScopedmit CDI verbunden werden, sodass Sie dies einfach tun können. Dabei @Named @ViewScopedwird jedoch ein hässlicher windowIdAnforderungsparameter an die Ergebnis-URLs angehängt , auch bei der einfachen Vanilla-Navigation von Seite zu Seite. OmniFaces löst dies alles mit einer echten CDI, @ViewScopeddie den Gültigkeitsbereich der Bean wirklich an den JSF-Ansichtsstatus anstatt an einen beliebigen Anforderungsparameter bindet.

JSF 2.2 (das 3 Jahre nach dieser Frage / Antwort veröffentlicht wird) bietet eine neue, vollständig CDI-kompatible @ViewScopedAnnotation im Geschmack von javax.faces.view.ViewScoped. JSF 2.2 wird sogar mit einem CDI-only geliefert, @FlowScopeddas kein @ManagedBeanÄquivalent hat, wodurch JSF-Benutzer in Richtung CDI gedrängt werden. Es wird erwartet, dass @ManagedBeanFreunde gemäß Java EE 8 veraltet sind. Wenn Sie derzeit noch verwenden @ManagedBean, wird dringend empfohlen, auf CDI zu wechseln, um sich auf zukünftige Upgrade-Pfade vorzubereiten. CDI ist in Java EE Web Profile-kompatiblen Containern wie WildFly, TomEE und GlassFish verfügbar. Für Tomcat müssen Sie es separat installieren, genau wie Sie es bereits für JSF getan haben. Siehe auch Wie installiere ich CDI in Tomcat?

BalusC
quelle
4
Ich habe erstellt beans.xml, konvertieren @ManagedBeanTräger Bohnen @Namedund umgewandelt @ManagedPropertyzu @Inject. Alles ist gut mit der Welt. Wenn ich jedoch meine @EJBAnmerkungen in ändere @Inject, schlägt die Bereitstellung org.jboss.weld.exceptions.DeploymentExceptionmit der Nachricht fehl ( ) WELD-001408 Injection point has unsatisfied dependencies. Sollte ich tatsächlich verwenden @Inject, um EJBs ohne Schnittstelle in eine @NamedBean zu injizieren , oder sollte ich dabei bleiben @EJB? Die EJBs sind in einer EJB-JAR verpackt, in derselben EAR wie die WAR, die meine CDI-Beans enthält.
Matt Ball
Es sollte einfach funktionieren. Stehen Sie bei der aktuellen Weld-Version immer noch vor diesem Problem?
BalusC
Leider konnte ich nicht sagen. Diese Frage stammt von 2 Arbeitgebern und vor> 2 Jahren. Aufgrund meines alten Kommentars zu Bozhos Antwort muss ich auf CDI / umgestellt haben @Named.
Matt Ball
"MyFaces CODI macht es einfacher, indem JSFs javax.faces.bean.ViewScoped vollständig transparent mit CDI verbunden wird, sodass Sie dies einfach tun können. Dabei @Named @ViewScopedwird jedoch ein hässlicher windowId-Anforderungsparameter an Ergebnis-URLs angehängt, auch bei der einfachen Vanilla-Navigation von Seite zu Seite." Beachten Sie, dass dies mit DeltaSpike nicht mehr gilt. Sie können die URL-Parameter dsId und windowId deaktivieren, wenn Sie den Fensterbereich nicht benötigen.
JanM
1
@Jan: Und in der Zwischenzeit OmniFaces hat auch eine JSF 2.2-like @ViewScopedfür JSF 2.0 / 2.1: showcase.omnifaces.org/cdi/ViewScoped
BalusC
16

Mit Java EE 6 und CDI haben Sie verschiedene Optionen für Managed Beans

  • @javax.faces.bean.ManagedBeanbezieht sich auf JSR 314 und wurde mit JSF 2.0 eingeführt. Das Hauptziel war es, die Konfiguration in der Datei flags-config.xml zu vermeiden, um die Bean in einer JSF-Seite zu verwenden.
  • @javax.annotation.ManagedBean(“myBean”) wird durch JSR 316 definiert. Es verallgemeinert die von JSF verwalteten Beans zur Verwendung an anderer Stelle in Java EE
  • @javax.inject.Named(“myBean”) sind fast identisch mit der obigen, außer dass Sie eine beans.xml-Datei im web / WEB-INF-Ordner benötigen, um CDI zu aktivieren.
h2mch
quelle
1
Was ist der Unterschied zwischen den ersten beiden?
Matt Ball
Das Ziel der ersten Annotation ist / war es, die Bean-Konfiguration in der Datei sites-config.xml für die Verwendung in JSF zu ersetzen. Der zweite kopiert das Konzept in den "Java Ee 6 Container". Es hat mehr Funktionen (wie @PostConstruct- und @ PreDestroy-Annotationen), ist aber auch über die JSF-Seite (mit Ausdruckssprache) erreichbar.
h2mch
1
Warum brauchst du eine beans.xmlDatei? Gilt das heute noch?
Thufir
2
Nein, mit JavaEE7 benötigen Sie die beans.xml nicht mehr. siehe docs.oracle.com/javaee/7/tutorial/doc/cdi-adv001.htm
h2mch
1
Mit JavaEE7 benötigen Sie die beans.xml nicht: docs.oracle.com/javaee/7/tutorial/cdi-adv001.htm (korrekter Link) blogs.oracle.com/theaquarium/entry/… (Standard-CDI-Aktivierung in Java EE 7)
M. Atif Riaz
2

Ich habe CDI in GlassFish 3.0.1 verwendet, aber um es zum Laufen zu bringen, musste ich das Seam 3-Framework (Weld) importieren. Das hat ziemlich gut funktioniert.

In GlassFish 3.1 funktionierte CDI nicht mehr und die Nahtschweißung funktionierte nicht mehr damit. Ich habe einen Fehler in diesem Bereich geöffnet, aber noch keinen Fehler behoben. Ich musste meinen gesamten Code in die Annotationen javax.faces. * Konvertieren, aber ich plane, wieder zu CDI zu wechseln, sobald sie funktionieren.

Ich bin damit einverstanden, dass Sie CDI verwenden sollten, aber ein Problem, das ich noch nicht gelöst habe, ist die Vorgehensweise mit der Annotation @ViewScoped. Ich habe viel Code, der davon abhängt. Es ist nicht klar, ob @ViewScoped funktioniert, wenn Sie @ManagedBean nicht damit verwenden. Wenn jemand dies klarstellen kann, würde ich es begrüßen.

AlanObject
quelle
-1

Ein guter Grund, auf CDI umzusteigen: Möglicherweise haben Sie eine gemeinsame Ressource mit Sitzungsbereich (z. B. Benutzerprofil) @Inject, die sowohl in JSF-verwaltete Beans als auch in REST-Services (z. B. Jersey / JAX-RS) integriert ist.

Auf der anderen Seite @ViewScopedist dies ein überzeugender Grund, sich an JSF zu halten @ManagedBean- insbesondere für alles, was mit AJAX zu tun hat. In CDI gibt es dafür keinen Standardersatz.

Es scheint, dass es eine Unterstützung für eine @ViewScopedähnliche Annotation für CDI-Beans gibt, aber ich habe nicht persönlich damit gespielt.

http://seamframework.org/Seam3/FacesModule

wrschneider
quelle