SBCD - Inyección de Dependencia en EJB 3.0

(Imagen: Diego Rivera - Mujer moliendo maíz)

La inyección de dependencia es uno de los tantos servicios del contenedor EJB, y nos permite eliminar los lookups JNDI de nuestro código dejando nuestros EJB's limpios y conteniendo sólamente lógica de negocio. Dado que es un servicio del contenedor, sólamente está disponible para las clases qye el contenedor administra. Esas clases son:
  • EJB 's (a que esa no se la sabían), Interceptors, Servlets, Filters, ServletListeners, JSF Managed Beans, Web Services Endpoints y Handlers
Por ende, la inyección de dependencia no funciona en JSP ni Beans JSP. Aquí un ejemplo clásico, en el que se inyectará un origen de datos (previamente registrado en el Contenedor) a un ejb:

@Resource
(name = "Foo")
private DataSource ds;

La otra salida hubiera sido realizar el lookup JNDI correspondiente... pero es menos ...elegante. Ahora, como dije en otro post, todo lo que se hace mediante anotaciones se puede hacer mediante el Descriptor de Despliegue., donde la jugada sería mas o menos así:

<resource-ref>
<res-ref-name> Foo </res-refname>
<res-ref-type> javax.sql.DataSource </res-ref-type>
<injection-target>
<injection-target-class> com.acme.FooBean </injection-target-class>
<injection-target-name> ds </injection-target-name>
</injection-target>

Una vez inyectado el recurso deseado (ej. el dataSource) en la clase (ej. un EJB) se pueden realizar tareas de inicialización en un método que posea la anotación @PostConstruct (por ejemplo, obtener una conexión del datasource obtenido, y almacenarlo en una variable de instancia). La inyección de dependencia se puede realizar a nivel de atributo (como el ejemplo), a nivel de método (que haría lo mismo que la inyección por atributo más un método @PostConstruct) y a nivel de clase.

Hay que tener en cuenta que la inyección de dependencia no nos protege de temas de concurrencia. Por eso, en el caso de los Servlets, que son singletons y que se ejecutan en varios threads, se debe tener especial cuidado:

public class MyServlet ... {
private @EJB StatelessEJB stateless; //OK
private @EJB StatefulEJB stateful; // peligro!!!
}

La variable stateful nos podría dar problemas de inconsistencia, dado que va a ser modificada por todos los threads del servlet, y un Stateful Session Bean mantiene estado conversacional. Una situacxión similar sucede con los Contextos de Persistencia (PersistenceContext). Para salvar esos casos, se recomienda realizar un lookup JNDI, y almacenar el objeto en sesión, de modo que se preserve un objeto por thread. Así:

public class MyServlet ... {
EntityManager em = ctx.lookup("java:comp/env/pc");
httpSession.setAttribute("entityManager", em);
}


Por último, la inyección de dependencia rara vez crea problemas de performance... así que úsenla con confianza nomás, y acuérdense que la inyección se realiza al momento de crear el objeto; y para cuestiones de inicialización se utiliza @PostConstruct. En el próximo post veremos un pcoo más del ciclo de vida de los EJB's. Hasta otra!!

Publicar un comentario