Ejb Con Spring

De Dos Ideas.
Revisión del 13:03 27 jul 2008 de Admin (discusión | contribuciones) (Ejemplo de creación de un EJB Stateless)
Saltar a: navegación, buscar

Spring Framework trae amplio soporte para el uso de EJB.

Creación en EJB 2.x

Spring provee una forma simple y cómoda para crear EJBs de Stateless, Stateful y Message Driven Bean. 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:

  • Jndi Template, 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

Más información