lunes, febrero 14, 2005

Utilización de EJBs en Spring

Desde su introducción en la especificación EJB 2.0 en Septiembre 2001, las interfaces locales de los EJBs han probado ser de gran valor para el desarrollador.
Eliminan la obligatoriedad de distribuir nuestros objetos (ya que solo en algunos pocos casos es necesario), con la consiguiente mejora de performance, y por lo tanto eliminan la necesidad de lidiar con RemoteException en cada método. Es de destacar también que las interfaces locales utilizan llamadas por referencia, a diferencia de utilizar llamadas por valor (copias de objetos serializados) en la interfaz remota. Para ello, el servidor de aplicaciones instancia nuestros EJBs en la misma JVM que, por ejemplo, la capa de presentación web desde donde son llamados.
Pero no todo es color de rosa con los EJBs, ya que seguimos teniendo clases que son difíciles de probar (con JUnit, por ejemplo), y seguimos teniendo el añadido (en contraposición a utilizar POJOs para nuestros objetos de negocio) de complicar el desarrollo con interfaces y descriptores.

Pero veamos como utilizar Spring para simplificar el desarrollo en el caso que no poder reemplazar los EJBs por POJOs + AOP/ORM/JDBC.

Para utilizar un EJB tradicionalmente se ocultan las búsquedas JNDI detrás de un Service Locator que nos devuelve un objeto EJB Home, el cual a su vez utilizamos para obtener el EJB real (local o remoto) mediante una llamada al método create.
Esto no nos libra de tener que implementar también un Business Delegate para despegar al cliente de la utilización directa de la API de EJB, y por lo tanto de las RemoteException lanzadas por su método de networking.

El método de Spring para simplificar lo anteriormente expuesto es la utilización de proxys dentro del ApplicationContext, que nos libran de escribir un nuevo Service Locator y/o Business Delegate para nuestro objeto de negocio.
Utilizando el mismo ejemplo que la documentación de Spring, lo primero que haremos será seguir las buenas prácticas y construir una Business Methods Interface para nuestro componente. Este patrón nos asegura una correcta sincronización entre el nuestro objeto de negocio y la interfaz (local o remota), ya que ambos implementan la misma Business Method Interface. Otra razón para utilizar este patrón, es que nos será mas fácil intercambiar una implementación EJB por otra POJO, si mas adelante lo consideramos necesario:

public interface MyComponent {
...
}
Luego expondremos una propiedad en el objeto cliente (un web controller en el ejemplo de Spring):

private MyComponent myComponent;

public void setMyComponent(MyComponent myComponent) {
this.myComponent = myComponent;
}
y finalmente configuraremos las dependencias en el xml de configuración de Spring:

<bean id="myComponent"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<property name="jndiName"><value>myComponent</value></property>
<property name="businessInterface"><value>com.mycom.MyComponent</value></property>
</bean>

<bean id="myController" class="com.mycom.myController">
<property name="myComponent"><ref bean="myComponent"/></property>
</bean>
Lo que sucede luego, es que Spring (gracias a AOP) crea un proxy para el EJB, el cual implementa dinámicamente nuestra Business Methods Interface (MyComponent) y hace las búsquedas JNDI necesarias para encontrar el EJB Local Home (el cual pone en cache).
Ante cada llamada del cliente a myComponent, Spring hará la llamada correspondiente a create para obtener el EJB y al correspondiente método en el objeto de negocio.

Si por cualquier razón queremos cambiar la implementación del objeto de negocio de un EJB a un POJO, simplemente cambiamos la definición del bean en Spring sin necesidad de tocar una sola linea de código en el cliente:

<bean id="myComponent"
class="com.example.MyBusinessObject">
</bean>
Esta facilidad para cambiar de EJBs a POJOs, sugiere que es posible, en una aplicación existente que utiliza extensivamente EJBs, ir reemplazando primero la infraestructura de configuración de dependencias, luego la de acceso a los objetos de negocio y finalmente la implementación misma de estos objetos. Asi resulta mucho menos traumático para el equipo de desarrollo, y menos estresante para la dirección.

Actualización: El artículo Pro Spring: Spring and EJB (en inglés) presenta el mismo tema en forma mucho mas extensa.

miércoles, febrero 09, 2005

Libros de Spring

Al mismo tiempo que el valor de Spring comienza a ser reconocido y es adoptado en las empresas, nuevos libros hacen su aparición y ayudan al proceso.
Hasta el momento:

Spring Live (€33.60 o €23.40 digital)
Spring in Action (€23.20)
Pro Spring (€23.21)

Spring Live es para iniciarse en el framework y es un libro eminentemente "práctico", casi un tutorial de alto nivel. Y tiene la ventaja de que si compramos la versión digital, obtenemos actualizaciones y nuevos capítulos en forma periódica.
Los otros dos libros son muy recientes, pero los comentarios que he oído dicen que son de libros para usuarios mas avanzados.
Y por ahora están solamente en inglés.

martes, febrero 08, 2005

El Patrón Business Methods Interface

Un problema que tenemos al desarrollar EJBs es el de sincronizar los métodos de la interfaz local o remota con los métodos de la implementación.
Ya que la interfaz y el EJB tienen una jerarquía diferente, se da comunmente el caso en el cual la interfaz tiene una firma determinada para un método, pero el EJB otra.

Para solucionar el problema y capturar esta incoherencia en tiempo de desarrollo (en la compilación), se utiliza comunmente el patrón llamado Business Methods Interface. En este patrón la interface (local o remota) y la implementación (el EJB) implementan la misma interface (business methods).


Por ejemplo, si quisiéramos implementar ciertas funcionalidades de negocio en un EJB con interfaz local, crearíamos primero una Business Methods Interface, donde definiríamos nuestro métodos de negocio:

  public interface MyBusinessInterface {

public void myBusinessMethod1 ( ... );
...
}
y en base a ella crearíamos el EJB, con la implementación de estos métodos:
  import javax.ejb.SessionBean;

public class ExampleEJB implements SessionBean,
MyBusinessInterface {
public void myBusinessMethod1 ( ... ) {
...
}
...
}
y por último la interfaz local, extendiendo también de MyBusinessInterface:
  import javax.ejb.EJBLocalObject;

public interface ExampleLocal extends EJBLocalObject,
MyBusinessInterface {
}
En el caso de necesitar una interfaz remota, los métodos de la Business Methods Interface deberían lanzar RemoteException, tal como es requerido por la especificación de EJB.

De esta forma queda asegurada en tiempo de compilación la integridad de ambos componentes entre si.