java - @Inject, @EJB, @Local, @Remote, @LocalBean, etc...: ¿confundido?
java-ee cdi (2)
Como puede ver, he declarado la anotación "@Local" en la implementación del servicio sin definir la interfaz local. ¿Es correcto?
Con EJB 3.1, se eliminó el requisito de interfaces locales. No es necesario que los escriba a menos que los necesite explícitamente.
¿Cuál es la mejor manera de inyectar un EJB en otro?
Un par de cosas para escribir aquí:
Con Java EE 6, Java Enterprise ha cambiado. Un nuevo JSR define un llamado bean administrado (no confunda con beans administrados JSF) como un tipo de componente mínimo que aún puede beneficiarse del contenedor en términos de inyección de dependencia y administración del ciclo de vida. Esto significa que: si tiene un componente y "solo" quiere usar DI y deja que el contenedor controle su ciclo de vida, no necesita usar EJB para ello. Terminará usando EJB si, y solo si, necesita explícitamente la funcionalidad EJB, como el manejo de transacciones, la puesta en común, la pasivación y la agrupación en clústeres.
Esto hace que la respuesta a su pregunta se presente en tres partes:
- Use @Inject sobre @EJB, el concepto de CDI (a) funciona para todos los beans administrados (esto incluye EJB) y (b) tiene estado y, por lo tanto, es superior al puro @EJB DI
- ¿Estás seguro de que necesitas EJB para tus componentes?
- Definitivamente vale la pena echar un vistazo a la documentation CDI
Tengo la siguiente configuración:
- 1 EAR en un GF que contiene 2 EJB-JAR con componentes EJB.
- 1 WAR en otro servidor Glassfish ( => otra JVM ) que contiene componentes web que acceden a los componentes EJB.
Tengo 2 servicios de negocios de EJB en cada EJB-JAR de mi EAR, y todos están desarrollados de esta manera:
@Remote
public interface ServiceAItf {
...
}
@Stateless
@Local
public class ServiceAImpl implements ServiceAItf {
...
}
En mi WAR, accedo a los componentes de EJB a través de un "InitialContext.lookup" explícito en la interfaz remota.
En mi EAR, estoy bastante confundido acerca de las mejores prácticas de inyección, en términos de rendimiento, arquitectura, etc. ...
Tengo las siguientes preguntas:
Como puede ver, he declarado la anotación "@Local" en la implementación del servicio sin definir la interfaz local. ¿Es correcto? Al menos no tengo ningún error en la implementación. Pero tal vez debería usar la anotación "@LocalBean" en su lugar? Supongo que la anotación "@LocalBean" simplemente permite invocar la implementación directamente como un EJB "Local" , pero debe usar la implementación en su código de esta manera:
@Stateless @Local public class ServiceBImpl implementa ServiceBItf {@EJB private ServiceAImpl serviceA; ...}
¿Cuál es la mejor manera de inyectar un EJB en otro? Funciona así:
@Stateless @Local public class ServiceBImpl implementa ServiceBItf {@EJB serviceAItf serviceA privado; ...}
Pero por lo que noté, el "servicio A" inyectado es el proxy remoto, mientras que está en la misma JVM dentro del mismo archivo EAR. Entonces, supongo que habrá un impacto en el rendimiento. Es por eso que he tratado de inyectar el servicio de esta manera:
@Stateless
@Local
public class ServiceBImpl implements ServiceBItf {
@Inject
private ServiceAItf serviceA;
...
}
Pero no funciona en GF, tengo la siguiente excepción:
WELD-001408 Unsatisfied dependencies for type [...] ...
Luego traté de crear una interfaz local, y la inyección a través de la anotación "@Inject" funciona cuando ambos servicios
Incluso si creo una interfaz local como esta, el servicio no se inyecta mediante la anotación "@Inject", sino que es nulo:
@Local
public interface ServiceALocalItf {
...
}
Leí muchos artículos donde es muy recomendable usar "@Inject" en lugar de "@EJB" cuando se trata de una invocación local. Eso me lleva a la siguiente pregunta: ¿en qué caso se recomienda (o simplemente se usa) la invocación EJB "@Local" ?
Después de todo este análisis, llego a la siguiente conclusión:
- Para cada servicio, creo una interfaz "@Local" y una "@Remote" .
- Desde WAR hasta EJB-JAR de EAR, realice una búsqueda JNDI en la interfaz remota.
- Desde EJB-JAR a EJB-JAR, realice una inyección a través de "@EJB" a la interfaz local.
- Para dos servicios dentro del mismo EJB-JAR, realice una inyección a través de "@Inject" a la interfaz local.
¿Qué piensa usted al respecto? ¿Es correcto?
@Inject
anotación @Inject
se usa para beans Java ( @EJB
) mientras que la anotación @EJB
se usa para enterprise java beans. Cuando un contenedor inyecta un ejb provisto por la anotación @EJB
a otro bean, también controla el ciclo de vida de ejb, realiza el agrupamiento para beans sin estado y demás (cuando el bean que se va a inyectar no se implementa, la referencia será nula). Si usa el mecanismo @Inject
annotation CDI, simplemente busque y cree una instancia de recurso inyectado como con un nuevo operador (si la implementación de la interfaz que se va a inyectar no existe, la referencia será nula). Puede usar calificadores con la anotación @Inject
para elegir una implementación diferente de la interfaz inyectada.