Ejb Con Spring
SpringFramework trae amplio soporte para el uso de [EJB].
Contenido
Creación en EJB 2.x
Spring provee una forma simple y cómoda para crear EJBs de Stateless, Stateful y MessageDrivenBean. Esto se hace heredando la implementación de los EJB de alguna de estas clases: Abstract Stateless Session Bean Abstract Stateful Session Bean
- [Abstract Message Driven Bean]
Estas clases proveen varios beneficios:
- proveen acceso a un factory de Spring ya inicializado
- implementan ya varios métodos obligatorios de EJB
Las clases brindan un factory de Spring ya creado e inicializado, el cual se accede a través del método heredado getBeanFactory(). Este factory se configura a través de variables de entorno en el archivo ejb-jar.xml.
El método ejbCreate() se encuentra implementado (para poder inicializar el factory y otras tareas). Spring provee el método onEjbCreate() el cual implementaremos para inyectar "a mano" las dependencias de nuestro EJB.
Ejemplo de creación de un EJB Stateless
Supondremos que ya contamos con un objeto de negocio FlotaEspacialBO de la siguiente forma:
public class !FlotaEspacialBoImpl implements !FlotaEspacialBo { public Collection<Invasor> buscarInvasores(Long idFlota) { ... buscar los invasores de la flota indicada ... } }
Expondremos este EJB (el cual lo tenemos ya declarado en Spring) usando un EJB Stateless. Para el EJB crearemos todas las interafaces necesarias (Home, Remote, Local, etc). La diferencia estará en el bean:
public class !FlotaEspacialBean extends !AbstractStatelessSessionBean {
private !FlotaEspacialBo flotaEspacialBo;
public Collection<Invasor> buscarInvasores(Long idFlota) { return flotaEspcialBo.buscarInvasores(idFlota); }
@Override protected void onEjbCreate() throws !CreateException { flotaEspcialBo = (!FlotaEspacialBo) getBeanFactory().getBean("business.!FlotaEspacialBo"); } }
Como se ve, el bean hereda de !AbstractStatelessSessionBean, clase que ya provee varios métodos implementados para los EJB. Así, el EJB queda muy simple, invocando al objeto de negocio directamente para resolver la lógica. El método onEjbCreate() se encarga de inyectar las dependencias del EJB utilizando el método getBeanFactory() que viene heredado.
Falta entonces indicarle a Spring los archivos de configuración que deberá levantar el factory, lo cual va en el ejb-jar.xml
<ejb-jar> <enterprise-beans> <session> <ejb-name>!FlotaEspacialBean</ejb-name> <home>com.dosideas.business.ejb.flota.!FlotaEspacialRemoteHome</home> <remote>com.dosideas.business.ejb.flota.!FlotaEspacialRemote</remote> <ejb-class>com.dosideas.business.ejb.flota.!FlotaEspacialBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> <env-entry> <env-entry-name>ejb/!BeanFactoryPath</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>application-ejb.xml,application-negocio.xml</env-entry-value> </env-entry> </session> </enterprise-beans> </ejb-jar>
Los tag env-entry contienen la ubicación de los archivos de Spring para inicializar.
Creación en EJB 3.x
EJB 3 contiene muchas mejoras y simplificaciones al momento de crear EJBs. Integrar EJB3 y Spring es una tarea muy sencilla, que se resuelve con el uso de Anotaciones.
import javax.interceptor.Interceptors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ejb.interceptor.!SpringBeanAutowiringInterceptor;
@Stateless __@Interceptors(!SpringBeanAutowiringInterceptor.class)__ public class !PaisSessionBeanBean implements !PaisSessionBeanRemote { __@Autowired__ private !PaisBo paisBo;
public Pais buscarPaisPorId(Long id) { return paisBo.buscarPaisPorId(id); } }
La anotacion @Interceptors(!SpringBeanAutowiringInterceptor.class) prepara un factory para ser usado en el EJB. A su vez, se encarga de inyectar todos los atributos marcados con @Autowired.
El interceptor busca un archivo beanRefContext.xml en el classpath, que contenga una instancia de un !ApplicationContext, el cual referencia a los archivos de Spring a cargar. Por ejemplo:
<?xml version="1.0" encoding="UTF-8"?> <beans> <bean name="applicationContext-main" class="org.springframework.context.support.!ClassPathXmlApplicationContext"> <constructor-arg> <list> <value>application-business.xml</value> <value>application-dao.xml</value> <value>application-db.xml</value> <value>application-hibernate.xml</value> </list> </constructor-arg> </bean> </beans>
Acceso de EJBs
Uno de los usos más interesantes es la posibilidad de dejar a Spring realizar el lookup del EJB e inyectar la interfaz de negocio directamente en nuestros objetos.
Así, delegamos a Spring la localización y creación del EJB.
Para esto, se utilizan 2 clases principales:
- JndiTemplate, que contiene la información para realizar la búsqueda del EJB.
- [Simple Remote Stateless Session Proxy Factory Bean], que realizará la instanciación de nuestro EJB. Este Proxy será el que inyectaremos en nuestros otros beans.
Ejemplo de acceso
El EJB
Supongamos que tenemos un EJB llamado !PersonaServiceBean. Esta EJB está compuesto de las siguiente clases:
- com.dosideas.business.ejb.persona.!PersonaServiceRemote (interfaz de negocio remota)
- com.dosideas.business.ejb.persona.!PersonaServiceBean (implementación del EJB)
Archivo de configuración de Spring
En un archivo de Spring, podemos declarar una referencia a nuestro EJB, que luego podremos inyectar como un bean normal.
<?xml version="1.0" encoding="UTF-8"?> <beans>
<bean id="jndiTemplate" class="org.springframework.jndi.!JndiTemplate"> </bean>
<bean id="ejb.!PersonaServiceBean" class="org.springframework.ejb.access.!SimpleRemoteStatelessSessionProxyFactoryBean"> <property name="jndiName"> <value>ejb/!PersonaServiceBean</value> </property> <property name="jndiTemplate"> <ref local="jndiTemplate"/> </property> <property name="businessInterface"> <value>com.dosideas.business.ejb.persona.!PersonaServiceRemote</value> </property> </bean> </beans>
Listo! El bean con id "ejb.!PersonaServiceBean" es un proxy que cumple con la interfaz indicada en el atributo "businessInterface". En el ejemplo, se declaró la interfaz de negocio remota del EJB. Este bean puede ya ser inyectado en cualquier otro lado y utilizado normalmente.
Spring realizará la creación del bean igual que con el resto de los objetos. En este caso, al iniciarse el factory de Spring se realizará el lookup e instanciación correspondiente del EJB. Es posible demorar esta acción con los medios tradicionales que provee Spring (lazy-init, etc.).
El atributo businessInterface
El atributo businessInterface indica la interfaz que implementará el Proxy de Spring. Un detalle interesante es que esta interfaz no tiene porqué ser la interfaz de negocio del EJB.
Así, podriamos crear una interfaz "nuestra", que cumpla con los métodos que están en la interfaz de negocio del EJB. De esta manera, nuestra aplicación queda independiente de cambios en la interfaz del EJB (y la posiblidad, además, de intercambiar libremente entre interfaces remotas y locales del EJB).
Ver también
- [EJB]
- MockEjb
- JndiTemplate
Más información
- [Manual de Referencia de Spring, Capítulo 18: integración de EJB | http://static.springframework.org/spring/docs/2.5.x/reference/ejb.html ]
- [Pro Spring: Spring and EJB | http://www.javaworld.com/javaworld/jw-02-2005/jw-0214-springejb.html ]