¿Backing beans (@ManagedBean) o CDI Beans (@Named)?

109

Acabo de comenzar a leer Core JavaServer Faces, 3rd Ed. y dicen esto (énfasis mío):

Es un accidente histórico que haya dos mecanismos separados, beans CDI y beans administrados JSF, para beans que se pueden usar en páginas JSF. Le sugerimos que utilice beans CDI a menos que su aplicación deba funcionar en un corredor de servlet simple como Tomcat.

¿Por qué? No proporcionan ninguna justificación. He estado usando @ManagedBeanpara todos los beans en una aplicación prototipo que se ejecuta en GlassFish 3, y realmente no he notado ningún problema con esto. No me importa especialmente migrar de @ManagedBeana @Named, pero quiero saber por qué debería molestarme .

Matt Ball
fuente
4
@Bozho: esa pregunta es bastante similar, pero después de leer la respuesta de Pascal varias veces, todavía no entiendo por qué CDI es muy superior. No conozco CDI y estoy feliz de aprenderlo ya que es "mejor". ¿Por qué es mejor?
Matt Ball
"a menos que su aplicación deba funcionar en un corredor de servlets simple como Tomcat" Solo uso tomcat y recomiendo encarecidamente CDI. Tomcat puede soportarlo muy bien
Karl Kildén
1
@ KarlKildén "corredor de servlet simple" se refiere a un contenedor de servlet que no es compatible con CDI. En el momento de escribir este artículo, Tomcat no era compatible con CDI, excepto con un poco de magia.
Thorbjørn Ravn Andersen

Respuestas:

64

Se prefiere CDI sobre JSF simple porque CDI permite la inyección de dependencias en todo JavaEE. También puede inyectar POJO y dejar que se administren. Con JSF solo puede inyectar un subconjunto de lo que puede con CDI.

Bozho
fuente
Entonces, básicamente, puedo inyectar una instancia de casi cualquier clase (siempre que tenga "las cosas correctas", ¿qué es, solo un constructor sin argumentos? ) Con CDI, mientras que tengo que usar @ManagedBeansi quiero inyectarlo con JSF?
Matt Ball
3
@MattBall Matt después de sus años, ¿puede comentar sobre esta migración?
Koray Tugay
5
@KorayTugay No he tocado este código desde junio de 2011, pero me cambié a CDI y las cosas funcionaron bien. Me complace responder a cualquier pregunta específica de la mejor manera posible, si las tiene.
Matt Ball
170

Utilice CDI.

Según JSF 2.3, @ManagedBeanestá en desuso . Consulte también el número de especificaciones 1417 . Esto significa que no hay más de una razón para elegir @ManagedBeanmás @Named. Esto se implementó por primera vez en Mojarra 2.3.0 versión beta m06.

ingrese la descripción de la imagen aquí


Historia

La diferencia principal es que @ManagedBeanestá administrado por el marco JSF y solo está @ManagedPropertydisponible para otros beans administrados por JSF. @Namedes administrado por el servidor de aplicaciones (el contenedor) a través de marco CDI y está vía @Injectdisponible para cualquier tipo de artefacto gestionadas por contenedor como @WebListener, @WebFilter, @WebServlet, @Path, @Stateless, etc, e incluso una JSF @ManagedBean. Desde el otro lado en, @ManagedPropertyno no trabajar dentro de una@Named o de cualquier otro artefacto logrado contenedor. Funciona realmente solo por dentro@ManagedBean .

Otra diferencia es que CDI en realidad inyecta proxies que se delegan en la instancia actual en el alcance de destino por solicitud / hilo (como en la forma en que se inyectan los EJB). Este mecanismo permite inyectar un bean de alcance más estrecho en un bean de alcance más amplio, lo que no es posible con JSF @ManagedProperty. JSF "inyecta" aquí la instancia física directamente al invocar a un establecedor (esa es exactamente la razón por la que se requiere un establecedor, mientras que no se requiere con@Inject ).

Si bien no es directamente una desventaja, hay otras formas, el alcance @ManagedBeanes simplemente limitado. Desde la otra perspectiva, si no desea exponer "demasiado" @Inject, también puede mantener sus beans administrados @ManagedBean. Es como protectedversuspublic . Pero eso realmente no cuenta.

Al menos, en JSF 2.0 / 2.1, la principal desventaja de administrar beans de respaldo JSF por CDI es que no hay un equivalente CDI de @ViewScoped. Se @ConversationScopedacerca, pero aún requiere iniciar y detener manualmente y agrega un cidparámetro de solicitud feo a las URL de resultado. MyFaces CODI lo hace más fácil al unir de forma totalmente transparente JSF javax.faces.bean.ViewScopeda CDI para que pueda hacerlo @Named @ViewScoped, sin embargo, eso agrega un windowIdparámetro de solicitud feo a las URL de resultados, también en la navegación simple de página a página. OmniFaces resuelve todo esto con un verdadero CDI @ViewScopedque realmente vincula el alcance del bean al estado de la vista JSF en lugar de a un parámetro de solicitud arbitrario.

JSF 2.2 (que se publica 3 años después de esta pregunta / respuesta) ofrece una nueva @ViewScopedanotación totalmente compatible con CDI lista para usar en formato javax.faces.view.ViewScoped. JSF 2.2 incluso viene con un CDI solo @FlowScopedque no tiene @ManagedBeanequivalente, lo que empuja a los usuarios de JSF hacia CDI. La expectativa es que @ManagedBeany los amigos quedarán obsoletos según Java EE 8. Si todavía lo está utilizando @ManagedBean, se recomienda encarecidamente que cambie a CDI para estar preparado para futuras rutas de actualización. CDI está disponible en contenedores compatibles con Java EE Web Profile, como WildFly, TomEE y GlassFish. Para Tomcat, debe instalarlo por separado, exactamente como ya lo hizo para JSF. Consulte también ¿Cómo instalar CDI en Tomcat?

BalusC
fuente
4
Creé beans.xml, convertí @ManagedBeanfrijoles de respaldo @Namedy convertí @ManagedPropertya @Inject. Todo esta bien con el mundo. Sin embargo, si cambio mis @EJBanotaciones a @Inject, la implementación falla ( org.jboss.weld.exceptions.DeploymentException) con message WELD-001408 Injection point has unsatisfied dependencies. ¿Debería utilizarlo @Injectpara inyectar EJB sin interfaz en un @Namedbean, o debería seguir @EJB? Los EJB están empaquetados en un EJB JAR, en el mismo EAR que el WAR que contiene mis beans CDI.
Matt Ball
Debería funcionar. ¿Sigue enfrentando este problema con la versión actual de Weld?
BalusC
Por desgracia, no podría decirlo. Esta pregunta es de 2 empleadores y> 2 años atrás. Según mi antiguo comentario sobre la respuesta de Bozho, debo haber cambiado a CDI / @Named.
Matt Ball
"MyFaces CODI lo hace más fácil al unir de forma totalmente transparente javax.faces.bean.ViewScoped de JSF a CDI para que pueda hacerlo @Named @ViewScoped, sin embargo, eso agrega un parámetro de solicitud de windowId feo a las URL de resultados, también en la navegación simple de página a página". Tenga en cuenta que con DeltaSpike esto ya no es cierto. Puede deshabilitar los parámetros URL dsId y windowId, si no necesita Window Scope.
EneM
1
@Jan: Y mientras tanto, OmniFaces también tiene un JSF 2.2-like @ViewScopedpara JSF 2.0 / 2.1: showcase.omnifaces.org/cdi/ViewScoped
BalusC
16

Con Java EE 6 y CDI tiene diferentes opciones para Managed Beans

  • @javax.faces.bean.ManagedBeanse refiere a JSR 314 y se introdujo con JSF 2.0. El objetivo principal era evitar la configuración en el archivo faces-config.xml para usar el bean dentro de una página JSF.
  • @javax.annotation.ManagedBean(“myBean”) está definido por JSR 316. Generaliza los beans administrados JSF para su uso en otros lugares de Java EE
  • @javax.inject.Named(“myBean”) son casi iguales que el anterior, excepto que necesita un archivo beans.xml en la carpeta web / WEB-INF para activar CDI.
h2mch
fuente
1
¿Cuál es la diferencia entre los dos primeros?
Matt Ball
El objetivo de la primera anotación es / era reemplazar la configuración del bean en faces-config.xml para su uso en JSF. El segundo copia el concepto en el "contenedor java ee 6". Tiene más funciones (como @PostConstruct y @PreDestroy anotaciones), pero también es accesible por la página JSF (con Expression Language).
h2mch
1
¿Por qué necesitas un beans.xmlarchivo? ¿Es esto todavía cierto hoy?
-Thufir
2
No, con JavaEE7 ya no necesitas beans.xml. consulte docs.oracle.com/javaee/7/tutorial/doc/cdi-adv001.htm
h2mch
1
Con JavaEE7 no necesita beans.xml: docs.oracle.com/javaee/7/tutorial/cdi-adv001.htm (enlace correcto) blogs.oracle.com/theaquarium/entry/… ( Habilitación de CDI predeterminada en Java EE 7)
M. Atif Riaz
2

Estaba usando CDI en GlassFish 3.0.1, pero para que funcionara tuve que importar el marco Seam 3 (Weld). Eso funcionó bastante bien.

En GlassFish 3.1, CDI dejó de funcionar y Seam Weld dejó de funcionar. Abrí un error en esto pero aún no lo he solucionado. Tuve que convertir todo mi código para usar las anotaciones javax.faces. * Pero planeo volver a CDI una vez que lo hagan funcionar.

Estoy de acuerdo en que debe usar CDI, pero un problema que aún no he visto resuelto es qué hacer con la anotación @ViewScoped. Tengo mucho código que depende de eso. No está claro si @ViewScoped funciona si no está usando @ManagedBean con él. Si alguien me puede aclarar esto se lo agradecería.

AlanObject
fuente
-1

Una buena razón para cambiarse a CDI: podría tener un recurso de ámbito de sesión común (perfil de usuario, por ejemplo) @Injectintegrado tanto en beans administrados por JSF como en servicios REST (es decir, Jersey / JAX-RS).

Por otro lado, @ViewScopedes una razón convincente para seguir con JSF @ManagedBean, especialmente para cualquier cosa con AJAX significativo. No hay un reemplazo estándar para esto en CDI.

Parece que puede tener algún soporte para una @ViewScopedanotación similar a la de los beans CDI, pero no he jugado con ella personalmente.

http://seamframework.org/Seam3/FacesModule

wrschneider
fuente