11 July, 2008

Curso J2EE (13ª semana) spring:webflow

Semana 13ª continuamos con spring, esta vez probamos spring webflow, el modulo de spring para definir e implementar flujos de trabajo (workflow).

Atrás quedan aquellos días con jbpm, en mi opinión creo que lo habíamos comenzado a utilizar demasiado pronto (recién salida del horno la primera stable) y la documentación era muy escasa por lo que los comienzos fueron muy pero que muy difíciles. A esto (y otra vez en mi opinión) le sumamos un equipo de trabajo falto de muchos conocimientos y conceptos en los que se basa jbpm y como tantas otras veces el poco tiempo disponible para asimilarlos. Por todo esto mi anterior experiencia con jbpm no fué del todo satisfactoria, pero quien sabe, quizás un día de estos tontos lo retome y me lleve una grata sorpresa, ganas no me faltan pero tiempo todo el del mundo como a la mayoría.

En general spring webflow no me resultó complejo, lo principal es tener claro como trabaja spring.

Puedes declarar tu flujo tanto en un fichero xml como en una clase java y como en todo workflow tendrás diferentes estados y tipos de estado por los que pasará el proceso. Así por ejemplo tendremos: view-state (estados que renderizan una vista), action-state (estados de lógica de negocio), start-state (estado de comienzo), end-state (estado de fin). Podrán tener n transiciones que especificaremos por ejemplo en el fichero xml de la forma:

  1. <action-state>
  2.    <action bean="loginAction"/>
  3.    <transition on="ok" to="listadoFacturas"/>
  4.    <transition on="nok" to="login"/>
  5. </action-state>

En este caso hemos declarado un action state que por ejemplo comprobaría los datos insertados por un usuario y le mostraría un listado de facturas si son correctos o lo devolvería a la página de login.

Podríamos definir subflujos con la etiqueta subflow-state.

Debemos declarar los beans utilizados en el flujo indicado anteriormente:

  1. <bean id="loginAction" class="net.jsanroman.webflow.action.LoginAction"/>

A los enlaces html que inicien el flujo debemos pasarle el parámetro _flowId=id_del_start_state.

Una de las diferencias significativas que en un primer momento he encontrado respecto a jbpm es que spring webflow no guarda la información entre los diferentes estados de forma automática, cosa que si hace jbpm, pero bueno dependiendo de lo que necesitemos siempre podemos hacerlo a mano.

9 July, 2008

Curso J2EE (12ª semana) integración spring+struts, quartz y appfuse

Semana 12ª y continuamos integrando librerías con spring, como veis tenemos un montón y cada vez mas spring es nuestro punto de unión entre todas ellas.

Tenemos 3 formas de integrar struts y spring:

Extendiendo la clase ActionSupport:
Creamos nuestro action que extenderá de ActionSupport, dentro cargaremos el contexto de spring manualmente y obtendremos los bean necesarios y definidos en el fichero de configuración de spring:

  1. public class ObtenerFacturaAction extends ActionSupport {
  2.       public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response)
  3.             throws IOException, ServletException {
  4.             ApplicationContext ctx = getWebApplicationContext();
  5.             FacturaManager facturaManager = (FacturaManager) ctx.getBean("facturaManager");
  6. ...

Definimos nuestras acciones en struts-config.xml

  1. <action path="/obtenerFactura"
  2.         type="net.jsanroman.spring.struts.actions.ObtenerFacturaAction">
  3.           <forward name="success" path="/WEB-INF/facturas/fichaFactura.jsp"/>
  4. </action>
  5. ...

y a spring en este caso le toca proporcionar los beans que dispondremos en las clases actions:

  1. ...
  2. <bean id="facturaManager"
  3.    class="net.jsanroman.spring.struts.manager.FacturaManagerImpl"/>
  4. ...

Un gran acoplamiento entre spring y struts.

Empleando DelegatingRequestProcessor:
Debemos añadir a struts-config.xml

  1. <controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>

además de definir las acciones en struts deberemos definirlas también como beans en spring:

  1. <bean name="/obtenerFactura" class="net.jsanroman.spring.struts.actions.ObtenerFacturaAction">
  2.    <property name="facturaManager">
  3.       <ref bean="facturaManager"/>
  4.    </property>
  5. </bean>

Empleando DelegatingActionProxy:
En cada acción definida en struts-config.xml debemos añadir type = “org.springframework.web.struts.DelegatingActionProxy”. En este caso la ventaja es que podemos aprovechar las capacidades de spring, por ejemplo aop.

Pero en definitiva, un autentico coñazo cualquiera de las formas y una opción que solo deberemos utilizar en casos excepcionales.

Terminamos esta semana con un par de ejemplos primero con la libreria quartz para configurar "tareas programadas". Y el segundo con appfuse librería que nos crea todo el codigo para una completa aplicación web de gestión de una BD dada, basandose en struts (y en la última versión en struts2) tengo pendiente jugar mas con ella pues me dejó muy buen sabor.

Curso J2EE (11ª semana) spring+(aop, velocity), aspectj

Continuamos con spring y hemos aprovechado su módulo aop para introducirnos en la programación orientada a aspectos además también hemos hecho algún ejemplo con aspectj (otra implementación de este paradigma) mas potente que el módulo aop de spring. Por supuesto también tenemos implementaciones de programación orientada a aspectos para otros lenguajes (aspect#, aspect .net, aspectc, phpAspect, etc).

Esta semana también nos ha dado para conocer otra de las librerías que podemos integrar con spring, el motor de plantillas velocity, integrarlo es tan sencillo como declarar los beans de configuración:

  1. <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
  2.       <property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
  3. </bean>
  4. <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
  5.       <property name="cache" value="true"/>
  6.       <property name="prefix" value=""/>
  7.       <property name="suffix" value=".vm"/>
  8. </bean>

6 July, 2008

Curso J2EE (9ª,10ª semana) spring

Llegamos a la 9ª semana y le toca el turno a spring, nos extenderemos 2 semanas y un poquito de la siguiente debido a la gran cantidad de herramientas y frameworks con los que podemos integrarlo además aprovecharemos su módulo aop para introducir los conceptos de la programación orientada a aspectos.

Spring no es un framework al uso como los que yo había utilizado, struts, cakephp, jsf. Spring abarca todas las capas de una aplicación, y no solo de una aplicación web, podemos utilizar perfectamente spring para el desarrollo de aplicaciones de escritorio. Spring se compone de diversos módulos siendo indispensable el "core" a partir de este podemos utilizar cualquiera de los existentes dependiendo de nuestras necesidades:

- MVC: Implementación del patrón MVC.

- ORM: Integración con api's de mapeo objeto-relacional (JDO, Hibernate, iBatis).

- AOP: Implementación de programación orientada a aspectos.

- WEB: Contexto de aplicaciones orientado a web. Deberemos utilizarlo para integrar otros frameworks (struts, webwork, etc).

- DAO: JDBC.

Modulos spring

Por esto al principio me chocó un poco la idea que tenía a priori de spring, esperaba un framework típico y me encontré con algo muy diferente. Podríamos decir que spring es el encargado de unir todas las piezas de nuestra aplicación, piezas que pueden ser propias del framework (módulo mvc), o piezas de terceros que se integran a perfección (hibernate, struts, etc). Frameworks como spring se conocen como "contenedores ligeros" y no es el único: http://www.picocontainer.org.

¿Como integra spring todas estas piezas?. Dos conceptos a tener muy en cuenta: inversión de control e inyección de dependencias. Tenemos un montón de información por la red de "que es" y "hace" cada uno aunque a menudo se confunden. Pero digamos que estas dos técnicas hacen posible que spring elimine todas las dependencias y desacople los diferentes módulos que componen un programa, siguiendo el Principio de Hollywood: "no nos llames a nosotros; nosotros te llamaremos a tí".

Para spring un bean será un objecto que el podrá gestionar, lo crea lo destruye lo inyecta donde sea necesario. Así tenemos una interfaz básica BeanFactory que será la encargada de proporcionar los mecanismos necesarios para gestionar estos beans. Para aprovechar las capacidades de spring todo lo que desarrollemos serán beans, solo de esta forma spring podrá inyectar las dependencias que especifiquemos en el fichero de configuración.

Un ejemplo para verlo un poco mas claro:

Tenemos una clase Factura.java:

  1. public class Factura implements Serializable{
  2.    private Integer num;
  3.    private Double importe;
  4.    public Integer getNum() {
  5.       return num;
  6.    }
  7.    public void setNum(Integer num) {
  8.       this.num = num;
  9.    }
  10.    public Double getImporte() {
  11.       return importe;
  12.    }
  13.    public void setImporte(Double importe) {
  14.       this.importe = importe;
  15.    }
  16. }

Tenemos un FacturasManager.java que contiene una lista de facturas y un método que las pinta por pantalla:

  1. public class FacturasManager implements Serializable {
  2.    private List facturas;
  3.    public List getFacturas() {
  4.       return facturas;
  5.    }
  6.    public void setFacturas(List facturas) {
  7.       this.facturas = facturas;
  8.    }
  9.    public void pintaFacturas() {
  10.       ListIterator iterator = facturas.listIterator();
  11.       while(iterator.hasNext())
  12.       {
  13.             Factura f = (Factura)iterator.next();
  14.             System.out.println("Factura Nº:"+f.getNum()+",importe"+f.getImporte());
  15.       }
  16.    }
  17. }

Deberíamos complicarlo un poco mas pero para ilustrar los conceptos anteriores nos sirve.
Ahora tenemos el fichero xml de configuración de spring donde detallaremos los beans y las inyecciones que necesitamos hacer:

  1. <beans>
  2.     <bean id="factMan" class="net.jsanroman.facturas.FacturasManager">
  3.         <property name="facturas">
  4.             <list>
  5.                 <ref bean="factura1"/>
  6.                 <ref bean="factura2"/>
  7.                 <ref bean="factura3"/>
  8.             </list>
  9.         </property>
  10.     </bean>
  11.     <bean id="factura1" class="net.jsanroman.facturas.Factura">
  12.         <property name="num"><value>1</value></property>
  13.         <property name="importe"><value>124.3</value></property>
  14.     </bean>
  15.     <bean id="factura2" class="net.jsanroman.facturas.Factura">
  16.         <property name="num"><value>2</value></property>
  17.         <property name="importe"><value>14.3</value></property>
  18.     </bean>
  19.     <bean id="factura3" class="net.jsanroman.facturas.Factura">
  20.         <property name="num"><value>3</value></property>
  21.         <property name="importe"><value>224.3</value></property>
  22.     </bean>

Estamos instanciando 3 beans tipo Factura desde el propio xml y los estamos inyectando en la propiedad facturas de FacturasManager:

Ahora simplemente necesitamos un método que ejecute lo anterior, como veis una simple case standalone:

  1. private static FacturasManager facturasManager;
  2.    public static void main(String[] args){
  3.       ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  4.         facturasManager = (FacturasManager)ctx.getBean("factMan");
  5.         facturasManager.pintaFacturas();
  6.     }

Hemos desacoplado las clases Factura y FacturasManager, si en lugar de esas 3 instancias de facturas necesitáramos enviar un listado de las facturas de nuestra BD simplemente necesitaríamos modificar la inyección en el fichero .xml.

De esta forma también podremos integrar un montón de librerías externas.

Powered by WordPress
Bajo licencia Creative Commons
Contacto sanroman.javier at gmail.com