Java EE 6 @ javax.annotation.ManagedBean frente a @ javax.inject.Named frente a @ javax.faces.ManagedBean

107

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

Tenemos javax.ejbanotaciones como @Statefuly @Statelesspara crear EJB.

También existe la posibilidad @javax.annotation.ManagedBeande crear un bean administrado.

Hay anotaciones en me javax.enterprise.contextgusta @SessionScopedy @RequestScoped.

Además, también hay @ManagedBeany @SessionScoped/ @RequestScopedanotaciones en el javax.faces.beanpaquete.

Y para hacer las cosas más complicadas, hay un paquete javax.injectcon @Namedanotación.

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

¿Dónde puedo usar @EJB, @Injecto @ManagedProperypara inyectar otros granos?

Piotr Gwiazda
fuente
Ver también: stackoverflow.com/questions/4684112/…
Arjan Tijms

Respuestas:

194

Antes que nada déjame hacer algunas aclaraciones:

Definición de bean gestionado : generalmente un bean gestionado es un objeto cuyo ciclo de vida (construcción, destrucción, etc.) es gestionado por un contenedor.

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

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

Entonces podemos decir que tenemos:

  • Beans administrados JSF
  • Frijoles administrados por CDI
  • Beans gestionados por EJB
  • E incluso los Servlets son beans administrados porque son instanciados y destruidos por un contenedor, que es un contenedor de servlets.

Entonces, cuando vea la palabra Managed Bean, debe preguntar sobre el contexto o el tipo de la misma (JSF, CDI, EJB, etc.)

Entonces podría preguntarse por qué tenemos muchos de estos contenedores: AFAIK, los chicos de Java EE querían tener un marco de inyección de dependencia, pero no pudieron 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 objetivo de EJB era solo para algunos requisitos (transacción, modelo de componente distribuido, etc.).

Al mismo tiempo (en paralelo) se dieron cuenta de que también necesitaban admitir JSF, luego hicieron beans administrados por JSF y otro contenedor para beans JSF y lo consideraron un contenedor DI maduro, pero aún no era un contenedor completo y maduro.

Después de eso, Gavin King y algunos otros chicos agradables;) hicieron CDI, que es el contenedor DI más maduro que he visto. CDI (inspirado en Seam2, Guice y Spring) se hizo 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, integración SPI, muy flexible, etc. e incluso puede hacerlo qué están haciendo los beans administrados por EJB y JSF, entonces podemos tener solo un contenedor DI maduro y poderoso. ¡Pero por alguna compatibilidad con versiones anteriores y razones políticas, los chicos de Java EE quieren mantenerlos!

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

Beans administrados JSF, Beans CDI y EJB

JSF se desarrolló inicialmente con su propio bean administrado y un mecanismo de inyección de dependencia que se mejoró para JSF 2.0 para incluir beans basados ​​en anotaciones. Cuando se lanzó CDI con Java EE 6, se consideró como el marco de bean administrado para esa plataforma y, por supuesto, los EJB los desactualizaron todos después de haber existido durante más de una década.

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

Comencemos con los beans administrados JSF más simples.

Beans administrados JSF

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

Se pueden definir usando la @javax.faces.bean.ManagedBeananotación que toma un parámetro de nombre opcional. Este nombre se puede utilizar para hacer referencia al bean desde páginas JSF.

El alcance se puede aplicar al bean utilizando uno de los diferentes alcances definidos en el javax.faces.beanpaquete que incluyen la solicitud, sesión, aplicación, vista y alcances personalizados.

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

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

Frijoles CDI

CDI es el marco de administración de beans e inyección de dependencias que se lanzó como parte de Java EE 6 e incluye una instalación de bean administrada completa e integral. Los beans CDI son mucho más avanzados y flexibles que los beans administrados por JSF simples. Pueden hacer uso de interceptores, alcance de conversación, eventos, inyección segura de tipos, 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 la ruta de clases. Una vez que haga esto, cada bean del paquete se convierte en un bean CDI. Hay muchas características en CDI, demasiadas para cubrir aquí, pero como referencia rápida para características similares a JSF, puede definir el alcance del bean CDI usando uno de los alcances definidos en el javax.enterprise.contextpaquete (es decir, solicitud, conversación , ámbitos de sesión y aplicación). Si desea utilizar el bean CDI de una página JSF, puede darle un nombre usando la javax.inject.Namedanotación. Para inyectar un frijol en otro frijol, anote el campo con una javax.inject.Injectanotación.

@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 determinar si es asíncrono o no. Si bien puede usar la @Namedanotación como calificador, no debería hacerlo, ya que se proporciona para exponer los beans en EL.

CDI maneja la inyección de beans con alcances no coincidentes mediante el 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 vivo del bean con ámbito de solicitud.

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

EJB

Los EJB son anteriores a los beans CDI y de alguna manera son similares a los beans CDI y, en otros aspectos, muy diferentes. Principalmente, las diferencias entre los beans CDI y los EJB es que los EJB son:

  • Transaccional
  • Remoto o local
  • Capaz de pasivar beans con estado liberando recursos
  • Capaz de hacer uso de temporizadores
  • Puede ser asincrónico

Los dos tipos de EJB se denominan sin estado y con estado. Los EJB sin estado pueden considerarse 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, simplemente agrega una anotación javax.ejb.Statelesso javax.ejb.Statefula 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. De forma predeterminada, son transaccionales, pero puede utilizar la anotación de atributo de transacción.

Si bien los beans EJB y 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 EJB y los EJB se pueden inyectar en beans CDI. No es necesario hacer ninguna distinción al inyectar uno en el otro. Nuevamente, CDI maneja los diferentes ámbitos mediante el uso de proxy. Una excepción a esto es que CDI no admite la inyección de EJB remotos, pero eso se puede implementar escribiendo un método de productor simple para él.

javax.inject.NamedTanto la anotación como los calificadores se pueden utilizar en un EJB para hacer coincidir con un punto de inyección.

Cuando usar que frijol

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

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

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

Si necesita usarlo @ViewScopeden CDI, debe

  • utilice caras de costura o el módulo CODI de MyFaces . simplemente agregue uno de ellos a su classpath y @ViewScopedfuncionará en CDI. MyFaces CODI tiene un soporte aún más sólido de @ViewScoped
  • use MyFaces CODI's @ViewAccessScoped, es una extensión escrita sobre CDI por Apache, simplemente descárguela y use @ViewAccessScopedanotación en lugar de @ViewScoped.
  • Usa CDI @ConversationScopedy hazlo de larga duración. Consulte aquí para obtener más información .
  • Utilice la anotación Omnifaces @ViewScoped

Algunas partes robadas de aquí .

Mehdi
fuente
3
¡Esto es genial! ¡Gracias! Para estar completo, solo diga cómo inyectar CDI o EJB bean en JSF bean. ¿Es la @ManagedProperty("#{someBean})"forma correcta?
Piotr Gwiazda
2
¡No! no funcionará. simplemente convierta su bean administrado jsf en un bean administrado por CDI anotándolo usando @Namedy @javax.enterprise.context.RequestScopedy use la inyección CDI usando la anotación @Inject. no use beans administrados por jsf si no es necesario;).
Mehdi
3
> ¡¡¡Los chicos de JEE quieren quedárselos !!! - Es un poco más sutil que eso. CDI terminó bastante tarde en el ciclo de Java EE 6 y tanto JSF 2 como JAX-RS ya estaban listos. Habían mejorado resp. ya presentó su propia instalación de frijoles administrados. Si CDI hubiera estado disponible un poco antes, las cosas podrían haber sido diferentes. En Java EE 7, JSF adoptará CDI y javax.faces.bean eventualmente quedará en desuso (la desaprobación es un proceso lento en Java EE, que es tanto bueno como malo).
Arjan Tijms
3
Cuando dice: Para implementar beans CDI, debe colocar un archivo llamado beans.xml en una carpeta META-INF en la ruta de clases. Una vez que haga esto, cada bean del paquete se convierte en un bean CDI. ¿Quiere decir que cada bean también se convierte en un bean CDI además de lo que era? ¿Qué sucede si tengo JSF ManagedBeans con ManagedBean y ViewScoped? Siguen siendo Beans gestionados JSF, ¿verdad?
Koray Tugay
3
¿Alguien puede hacer una actualización para Java EE 7 en este gran artículo?
Martijn Burger
7

Sí, esto puede resultar confuso.

Por algunas razones históricas de ehm , JSF y CDI están usando las mismas anotaciones para los ámbitos, pero de diferentes paquetes.

Como probablemente adivine, los de javax.faces.beanson 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 mezcle con anotaciones CDI de javax.ejb. Esto producirá una lista infinita de errores y anomalías sutiles.

Por lo general, le recomiendo que hojee las primeras páginas (o incluso más) de la excelente documentación de Weld . Esto debería encaminarlo hacia Java EE 6.

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

Jan Groth
fuente
En realidad, tengo dos preguntas: 1. A menudo encuentro muy útil el alcance de la vista. Entonces, ¿necesito usar anotaciones JSF? 2. Significa que @javax.annotation.ManagedBeanes inútil ya que CDI trata todas las clases como beans administrados, ¿verdad?
Piotr Gwiazda
No exactamente. Deberá conectar los ámbitos JSF a CDI con, por ejemplo, Seam Faces. Y sí, @ManagedBeans no es necesario si tiene beans.xml en el archivo jar relevante. Ah, y si tiene más preguntas, es mejor comenzar un nuevo hilo antes de perdernos en la sección de comentarios.
jan groth
3

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

Por lo que reuní, JSF Managed Beans se está eliminando gradualmente a favor de CDI Beans (¿tal vez quedando obsoleto de JSF 2.3?), Por lo que supongo que ahora se @javax.annotation.ManagedBeanestá volviendo más obsoleto.

Hein Blöd
fuente
@Namedreemplazará @ManagedBeanen el futuro?
Jueves
1
He leído varias declaraciones de diferentes expertos en Java EE que predicen que los @Namedbeans CDI reemplazarán a JSF @ManagedBeans, por ejemplo, en stackoverflow.com/questions/4347374/… , BalusC dice "La expectativa es que @ManagedBean y sus amigos quedarán obsoletos según Java EE 8. ".
Hein Blöd