Java EE 6 @ javax.annotation.ManagedBean vs. @ javax.inject.Named vs. @ javax.faces.ManagedBean

Siento que hay un pequeño lío en la especificación Java EE 6. Hay varios conjuntos de anotaciones.

Tenemos anotaciones de javax.ejb como @Stateful y @Stateless para crear EJB.

También hay un @javax.annotation.ManagedBean para crear un bean administrado.

Hay anotaciones en javax.enterprise.context como @SessionScoped y @RequestScoped .

Además, hay anotaciones @SessionScoped y @SessionScoped / @RequestScoped en el paquete javax.faces.bean .

Y para complicar más las cosas, existe un paquete javax.inject con anotación @Named .

¿Alguien puede describir cómo se relacionan entre sí?

¿Dónde puedo usar @EJB , @Inject o @Inject para inyectar otros beans?

Antes que nada déjame hacer algunas aclaraciones:

Definición manejada del frijol: generalmente un frijol administrado es un objeto que su ciclo de vida (construcción, destrucción, etc.) es administrado por un contenedor.

En Java ee tenemos muchos contenedores que administran el ciclo de vida de sus objetos, como contenedor JSF, contenedor EJB, contenedor CDI, contenedor Servlet, etc.

Todos estos contenedores funcionan de forma independiente, inician en la inicialización del servidor de aplicaciones y escanean las clases de todos los artefactos, incluidos jar, ejb-jar, war y ear en el momento del despliegue, y recostackn y almacenan metadatos sobre ellos, luego cuando necesita un objeto de una clase en tiempo de ejecución le darán instancias de esas clases y después de terminar el trabajo, las destruirán.

Entonces podemos decir que tenemos:

  • Judías administradas JSF
  • Frijoles administrados CDI
  • EJB manejó frijoles
  • E incluso los Servlets son beans administrados porque son instanciados y destruidos por un contenedor, que es un contenedor de servlet.

Entonces, cuando veas la palabra Managed Bean, deberías preguntar sobre el contexto o el tipo de la misma (JSF, CDI, EJB, etc.)

Entonces podría preguntar por qué tenemos muchos de estos contenedores: AFAIK, los chicos de Java EE querían tener un marco de dependency injection, pero no podían reunir todos los requisitos en una especificación porque no podían predecir los requisitos futuros y crearon EJB 1.0 y luego 2.0 y luego 3.0 y ahora 3.1, pero el objective de EJB era solo para algunos requisitos (transacción, modelo de componentes distribuidos, etc.).

Al mismo tiempo (en paralelo) se dieron cuenta de que necesitaban también compatibilidad con JSF, luego crearon beans gestionados de JSF y otro contenedor de beans JSF y lo consideraron un contenedor DI maduro, pero aún así no era un contenedor completo y maduro.

Después de eso, Gavin King y otros chicos buenos;) hicieron CDI, que es el contenedor DI más maduro que he visto. CDI (inspirado en Seam2, Guice y Spring) fue creado para llenar el vacío entre JSF y EJB y muchas otras cosas útiles como inyección de pojo, métodos de producción, interceptores, decoradores, SPI de integración, muy flexible, etc. e incluso puede hacer lo que hacen los beans manejados por EJB y JSF, entonces podemos tener un solo contenedor DI maduro y poderoso. ¡¡Pero por alguna razón retrocompatible y razones políticas, los chicos de Java EE quieren mantenerlos !!!

Aquí puede encontrar la diferencia y casos de uso para cada uno de estos tipos:

JSF Managed Beans, CDI Beans y EJBs

JSF se desarrolló inicialmente con su propio mecanismo administrado de inyección de beans y dependencias mejorado para que JSF 2.0 incluyera beans basados ​​en anotaciones. Cuando se lanzó CDI con Java EE 6, se consideró como el marco administrado de frijoles para esa plataforma y, por supuesto, los EJB superaron a los anteriores ya que existían desde hacía más de una década.

El problema, por supuesto, es saber cuál usar y cuándo usarlos.

Comencemos con los beans gestionados más simples de JSF.

Frijoles gestionados JSF

En resumen, no los use si está desarrollando para Java EE 6 y usando CDI. Proporcionan un mecanismo simple para la dependency injection y la definición de los beans de respaldo para las páginas web, pero son mucho menos poderosos que los beans CDI.

Se pueden definir utilizando la anotación @javax.faces.bean.ManagedBean que toma un parámetro de nombre opcional. Este nombre se puede usar para hacer referencia al bean de las páginas JSF.

El scope se puede aplicar al bean utilizando uno de los diferentes ámbitos definidos en el paquete javax.faces.bean , que incluye la solicitud, la sesión, la aplicación, la vista y los ámbitos personalizados.

 @ManagedBean(name="someBean") @RequestScoped public class SomeBean { .... .... } 

Los beans JSF no se pueden mezclar con otros tipos de granos sin algún tipo de encoding manual.

Frijoles CDI

CDI es el marco de administración de beans y de dependency injections que se lanzó como parte de Java EE 6 e incluye una instalación de beans administrada completa e integral. Los beans CDI son mucho más avanzados y flexibles que los beans manejados por JSF. Pueden hacer uso de interceptores, scope de conversación, eventos, tipo de inyección segura, decoradores, estereotipos y métodos de producción.

Para implementar beans CDI, debe colocar un archivo llamado beans.xml en una carpeta META-INF en classpath. Una vez que haces esto, cada grano en el paquete se convierte en un frijol CDI. Hay muchas características en CDI, demasiadas para cubrirlas aquí, pero como referencia rápida para características similares a JSF, puede definir el scope del bean CDI usando uno de los ámbitos definidos en el paquete javax.enterprise.context ( a saber, scope de solicitud, conversación, sesión y aplicación). Si desea utilizar el bean CDI desde una página JSF, puede asignarle un nombre utilizando la anotación javax.inject.Named . Para inyectar un bean en otro bean, anota el campo con javax.inject.Inject annotation.

 @Named("someBean") @RequestScoped public class SomeBean { @Inject private SomeService someService; } 

La inyección automática como la definida anteriormente se puede controlar mediante el uso de calificadores que pueden ayudar a que coincida con la clase específica que desea inyectar. Si tiene varios tipos de pago, puede agregar un calificador para si es asincrónico o no. Si bien puede usar la anotación @Named como calificador, no debe hacerlo ya que se proporciona para exponer los beans en EL.

CDI maneja la inyección de frijoles con scopes desiguales a través del uso de proxies. Debido a esto, puede inyectar un bean con ámbito de solicitud en un bean con ámbito de sesión y la referencia seguirá siendo válida en cada solicitud porque para cada solicitud, el proxy se vuelve a conectar a una instancia en tiempo real del bean con ámbito de solicitud.

CDI también tiene soporte para interceptores, eventos, el nuevo scope de conversación y muchas otras características, lo que lo hace una opción mucho mejor que los beans administrados JSF.

EJB

Los EJB son anteriores a los beans CDI y en algunos casos son similares a los beans CDI y en otros aspectos son muy diferentes. En primer lugar, las diferencias entre los beans CDI y los EJB son que los EJB son:

  • Transaccional
  • Remoto o local
  • Capaz de pasivar granos con estado liberando recursos
  • Capaz de hacer uso de temporizadores
  • Puede ser asíncrono

Los dos tipos de EJB se llaman sin estado y con estado. Los EJB sin estado se pueden considerar como beans de un solo uso seguros para subprocesos que no mantienen ningún estado entre dos solicitudes web. Los EJB con estado mantienen el estado y se pueden crear y permanecer durante el tiempo que sean necesarios hasta que se eliminen.

Definir un EJB es simple, solo agrega una anotación javax.ejb.Stateless o javax.ejb.Stateful a la clase.

 @Stateless public class BookingService { public String makeReservation(Item Item, Customer customer) { ... ... } } 

Los beans sin estado deben tener un ámbito dependiente, mientras que un bean de sesión con estado puede tener cualquier ámbito. Por defecto son transaccionales, pero puede usar la anotación de atributo de transacción.

Si bien los EJB y los beans CDI son muy diferentes en términos de características, escribir el código para integrarlos es muy similar, ya que los beans CDI se pueden inyectar en los EJB y los EJB se pueden inyectar en los beans CDI. No es necesario hacer ninguna distinción al inyectar uno en el otro. Una vez más, los diferentes ámbitos son manejados por CDI mediante el uso de proxying. Una excepción a esto es que CDI no admite la inyección de EJB remotos, pero puede implementarse escribiendo un método de productor simple para ello.

La anotación javax.inject.Named así como cualquier calificador se pueden usar en un EJB para que coincida con un punto de inyección.

Cuándo usar qué frijol

¿Cómo sabes cuándo usar qué frijol? Sencillo.

Nunca use beans administrados JSF a menos que esté trabajando en un contenedor de servlets y no quiera intentar que CDI funcione en Tomcat (aunque hay algunos arquetipos Maven para eso, así que no hay excusa).

En general, debe usar beans CDI a menos que necesite la funcionalidad avanzada disponible en los EJB, como funciones transaccionales. Puedes escribir tu propio interceptor para hacer que los beans CDI sean transaccionales, pero por ahora, es más sencillo usar un EJB hasta que CDI obtenga frijoles CDI transaccionales que están a la vuelta de la esquina. Si está atascado en un contenedor de servlets y está utilizando CDI, entonces las transacciones escritas a mano o su propio interceptor de transacciones es la única opción sin EJB.

Si necesita usar @ViewScoped en CDI, debería

  • use Seam-faces o el módulo MyFaces CODI . solo agregue uno de ellos a su classpath y @ViewScoped funcionará en CDI. MyFaces CODI tiene un soporte aún más sólido de @ViewScoped
  • use MyFaces CODI @ViewAccessScoped , es una extensión escrita por Apache sobre CDI, simplemente descárguelo y use la anotación @ViewAccessScoped lugar de @ViewScoped .
  • Use CDI @ConversationScoped y @ConversationScoped funcionar durante mucho tiempo. Mira aquí para más información .
  • Usar la anotación Omnifaces @ViewScoped

Algunas partes robadas desde aquí .

Sí, esto puede ser confuso.

Para algunos motivos históricos ehm JSF y CDI están utilizando las mismas anotaciones para ámbitos, pero de diferentes paquetes.

Como probablemente adivine que los de javax.faces.bean son de la especificación JSF, y no están relacionados con CDI. No los use a menos que tenga una muy buena razón para hacerlo. Y nunca los mezcles con anotaciones CDI de javax.ejb . Esto producirá una gran cantidad de listas interminables de errores y anomalías sutiles.

Generalmente recomiendo que lea las primeras (o incluso más) páginas de la excelente documentación de Weld . Esto debería encaminarte hacia Java EE 6.

Y no dude en publicar más preguntas aquí.

Dado que no hay respuestas específicas sobre @javax.annotation.ManagedBean , aquí hay un enlace a la respuesta de una pregunta similar: Backing beans (@ManagedBean) o CDI Beans (@Named)? . La especificación se puede encontrar en http://download.oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/ . Por lo tanto, me parece que @javax.annotation.ManagedBean fue una generalización de @javax.faces.bean.ManagedBean .

Por lo que he deducido, JSF Managed Beans se está eliminando progresivamente a favor de CDI Beans (¿tal vez se está desaprobando de JSF 2.3?), Así que supongo que @javax.annotation.ManagedBean está quedando obsoleto ahora.