Mostrando las entradas con la etiqueta arquitectura. Mostrar todas las entradas
Mostrando las entradas con la etiqueta arquitectura. Mostrar todas las entradas

Que son las transacciones declarativas?

Varios conocen como se configuran las transacciones en Spring o frameworks similares, pero no muchos saben las ventajas por las cuales conviene utilizar este tipo específico de demarcación de transacciones. Voy a intentar contarles un poco acerca de que problemas soluciona este tipo de configuración, en contraposición a manejar las transacciones de forma programática.
Hace mucho, mucho tiempo, en una galaxia muy lejana, los programadores se encontraron frente al desafío de tener que lidiar con transacciones, según la definición wikipedista: "Una transacción es una interacción con una estructura de datos compleja, compuesta por varios procesos que se han de aplicar uno después del otro. La transacción debe realizarse de una sola vez y sin que la estructura a medio manipular pueda ser alcanzada por el resto del sistema hasta que se hayan finalizado todos sus procesos."

El enfoque programático

Para poder permitir que esa estructura a "medio manipular" pueda ser alcanzada por el resto del sistema, el primer aproach, fue el de utilizar dos sentencias para poder definir el inicio y el fin de la porción de código que lidiaba con un fragmento transaccional: es decir los famosos "begin" & "commit", con su infaltable contraparte "rollback".
Esas tres sentencias se usaron por mucho tiempo para manejar transacciones, y hoy en día mucha gente piensa que es la forma mediante la cual hay que lidiar con las mismas. En realidad no hay problemas en utilizar esto, pero a medida que los sistemas aumentan en complejidad, comienzan a notarse las falencias de este enfoque.
El primer gran problema es que claramente esto se trata de un "aspecto" del código que desarrollamos, y como tal, puede traer problemas si no es siempre tratado de similar manera. Por lo tanto es necesario implementarlo de forma separa de nuestro código para evitar olvidos o la posibilidad de codificarlo de forma diferente para cada funcionalidad.
Pero el verdadero gran problema es que el código tiene a complicarse mucho, si tenemos el caso de varias clases con diferentes métodos de lógica de negocio que se invocan entre sí. Cuando esto sucede, lo que normalmente se requiere, es que los métodos puedan "compartir" las transacciones entre sí, de tal manera de que solo uno de los métodos la inicie (el primero en ser invocado por la capa de presentación) y luego los otros utilicen este contexto transaccional ya creado. Esto normalmente se conoce como "propagación" de la transacción.
Si esto no se implementa de una forma declarativa, es decir "declarando" como cada método va a utilizar el aspecto de la transaccionalidad, es muy dificil de lograr un comportamiento similar, sin caer en el caso de tener que usar varios flags que se pasen como parámetro y cadenas de if que aumentan su complejidad a medida de que se van encadenando más y más métodos.

Declaremos

Utilizando Spring, como framework de inyección de dependencias, existen tres maneras de utilizar el enfoque declarativo, al momento de definir las transacciones de nuestro código:
  • Utilizando Proxys: Este es el enfoque más antiguo. Lo que hacemos es generar de forma dinámica un sustituto de nuestro Servicio, que lo que hace es agregar el manejo de transacciones, antes de cada método que respete un patrón de nombres que podemos especificar. Estos proxys se definen de una manera similar a la siguiente:
1:       <bean id="abstractTransactionManager" abstract="true">  
2:            <property name="transactionAttributes">  
3:                 <props>  
4:                      <prop key="save*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED</prop>  
5:                      <prop key="remove*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED</prop>  
6:                      <prop key="update*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED</prop>  
7:                      <prop key="ejecutar*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED</prop>  
8:                      <prop key="*">PROPAGATION_REQUIRED,readOnly,ISOLATION_READ_COMMITTED</prop>  
9:                 </props>  
10:            </property>  
11:       </bean>  
12:       <bean id="feriadosManager" parent="abstractTransactionManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">  
13:            <property name="target">  
14:                 <bean id="feriadosService" class="com.example.mysystem.service.FeriadosService">  
15:                      <property name="feriadosDAO" ref="feriadosDAO" />  
16:                 </bean>  
17:            </property>  
18:            <property name="transactionManager" ref="transactionManager_gateweb" />  
19:            <property name="proxyTargetClass" value="true" />  
20:       </bean>  

  • Utilizando Spring AOP: Como Spring tiene el "poder" de instanciar nuestras clases, el mecanismo de proxys se puede implementar de una forma aún más dinámica, definiendo la teoría de aspect-oriented-programming, con el sabor de Spring:
1:       <tx:advice id="commonTxAdvice" transaction-manager="transactionManager">  
2:            <tx:attributes>  
3:                 <tx:method name="save*" propagation="REQUIRED" />  
4:                 <tx:method name="remove*" propagation="REQUIRED" />  
5:                 <tx:method name="delete*" propagation="REQUIRED" />  
6:                 <tx:method name="update*" propagation="REQUIRED" />  
7:                 <tx:method name="execute*" propagation="REQUIRED" />  
8:                 <tx:method name="*" read-only="true" />  
9:            </tx:attributes>  
10:       </tx:advice>  
11:       <aop:config>  
12:            <!-- Pointcut -->  
13:            <aop:pointcut id="servicePointCut" expression="execution(* com.example.mysystem.service.impl.*.*(..))" />  
14:            <!-- Advisor -->  
15:            <aop:advisor advice-ref="commonTxAdvice" pointcut-ref="servicePointCut" />  
16:       </aop:config>  

De esta manera no es necesario recordar envolver a nuestros beans de servicio con un proxy transaccional, ya que se hace de manera automática de acuerdo al nombrado de los paquetes y de los nombres de los métodos. Esta manera es, según mi opinión, la mejor, ya que requiere mucho menos código y es más fácil de implementar.
  • Utilizando anotaciones: En este caso, utilizamos una anotación sobre el servicio que queremos que posea un comportamiento transaccional. La anotación utilizada es @Transactional:
1:  @Transactional  
2:  public class DefaultFooService implements FooService {  
3:    Foo getFoo(String fooName);  
4:    Foo getFoo(String fooName, String barName);  
5:    void insertFoo(Foo foo);  
6:    void updateFoo(Foo foo);  
7:  }  

Lo bueno de todo esto, es que los tres approachs se pueden usar side-by-side, sin ningún problema.
Igualmente hay que recordar, que dependiendo del enfoque, hay que tener en cuenta algunas configuraciones especiales. Lo mejor es, después de este artículo, pegarle una leída a la documentación oficial, que debería ser el primer lugar al cual referirse cuando se quiere conocer como se implementa algo utilizando un framework basado en una comunidad.
Antes que me olvide: no nos olvidemos que spring no es el primer framework y/o estándar en aplicar esta forma de manejar las transacciones, esto ya se viene implementando de una forma similar, desde los tiempos de los EJBs. Otros frameworks de DI, también tienen aproachs similares.
Nos vemos en el próximo post!

Mapeos más dinámicos: Fluent NHibernate

Como muchos saben, la herramienta de ORM más conocida en el mundo JAVA, Hibernate, tiene su port, bastante actualizado por cierto, en el mundo .NET. Hace poco tuvimos que empezar un proyecto en esta plataforma, y un integrante del equipo, sugirió utilizar Fluent NHibernate. Se trata básicamente de una librería, con un enfoque “fluent” para construir los mappings de las entidades.
Al principio pensé que quizá no era una buena idea utilizar otra manera de hacer mapeos, ya que si teníamos algún problema quizá iba a ser un poco más difícil pedir soporte a otros equipos que tenían más experiencia, pero igualmente decidimos ir para adelante, por lo menos inicialmente, para probar que tan difícil era armarlos.
Por suerte para crear los primeros mapeos pudimos utilizar una herramienta generadora de código, que tenía soporte para crear los mapeos con Fluent. Igualmente fue necesario retocar lo generado, como siempre suele suceder con este tipo de herramientas.
Luego de un tiempo, al final creo que fue una buena idea, y se me ocurrió buscar si había algo parecido en el mundo JAVA, y lamentablemente no pude encontrar nada similar.
La idea básica de este framework es tener una clase con código fuente (en este caso c#) que define el mapeo. Ejemplo:

1:  public class CatMap : ClassMap<Cat>  
2:  {  
3:   public CatMap()  
4:   {  
5:    Id(x => x.Id);  
6:    Map(x => x.Name)  
7:     .Length(16)  
8:     .Not.Nullable();  
9:    Map(x => x.Sex);  
10:    References(x => x.Mate);  
11:    HasMany(x => x.Kittens);  
12:   }  
13:  }  

Lo bueno de este enfoque, comparado con archivos XML, es que muchas cosas se resuelven en tiempo de compilación. La otra ventaja, es que utilizando el Intellisense de la IDE (VisualStudio en este caso), podemos tener rápidamente un vistazo de los diferentes atributos de cada parte del mapeo que estamos construyendo, y contextualizados al campo que estamos mapeando.El startup time, además, es bastante bueno y rápido. 
En fin, esto demuestra que las buenas ideas, traspasan todas las plataformas, y así como .NET se vió beneficiado con el port de uno de los mejores frameworks de persistencia, JAVA podría verse beneficiado con otra forma interesante de construir mapeos si alguien se anima a hacer un port de esta librería en el mundo JAVA :)

Maven: Dependencia entre wars

Por lo general, en todo proyecto empresarial JAVA, surge al momento de definir la arquitectura del aplicativo, definir el concepto de modulo, subsistema, y por que no, sistema. Al momento de tomar estas definiciones con un aplicativo en particular, surgen muchas maneras de realizar esta división, pero si tenemos en mente el stack de tecnologías JAVA estándares, para la Web, en algún momento, sobre todo dependiendo del tamaño del proyecto, vamos a llegar a la pregunta del millón: conviene separar mi capa de presentación por módulos?
Desde el comienzo, incluido en todo lo que nos ofreció el stack de tecnologías para aplicaciones empresariales de JAVA, nunca hubo un buen soporte para realizar esto, que a simple vista resulta prácticamente básico, poder “partir” mi aplicación en módulos independientes, pero en cierta manera “unidos” entre si, mediante el concepto de aplicación empresarial. Si bien se podían embeber varios paquetes “war” dentro de un único bundle “ear”, eran aplicaciones prácticamente independientes, y, era muy difícil por ejemplo, reutilizar código, ya que un WAR no es una librería (JAR) como tal.
Con la aparición de Maven, el WAR comenzó a ser un módulo más, por lo que surgió naturalmente el concepto de tratarlo como un paquete de código en si. De todas maneras los primeros intentos por lograr la tan ansiada dependencia, no vinieron de los plugins “core” sino de terceros, por ejemplo el goal maven:uberwar de cargo, o el plugin warpath de AppFuse.
Estos plugins si bien lograban su cometido, no eran la forma más natural de poder establecer dependencias entre los módulos WAR y así lograr por ejemplo, la reutilización de código de capa de presentación.
Igualmente ustedes dirán, “pero si queremos reutilizar, porque no metemos el código en librerías JAR?”, el problema viene justamente por lo que decía al principio, hasta hace no tanto, el estándar JEE, no permitía que, por ejemplo, las páginas JSPs u otros recursos WEB vengan embebidas en librerías. Si podríamos reutilizar ese código y tener en un componente principal recursos comunes, y en otros componentes simplemente referenciarlos, se disminuiría un montón el código de varias aplicaciones similares o módulos de una aplicación grande.
Otro problema venía por el lado de las IDEs, si bien podíamos resolverlo quizá, con los plugins que mencioné anteriormente, la IDE por lo general no se “daba cuenta” de esta dependencia, y había que lograr que funcione usando trucos extraños.

La solución

Por suerte se logró solucionar este problema con la última versión del plugin que administra la construcción de archivos war de maven, el maven-war-plugin.
Ahora para poder reutilizar código, podemos usar tranquilamente la dependencia entre wars, que funciona de la siguiente manera.
Supongamos que tenemos un proyecto WAR, denominado “proyecto-comun”, el cual posee clases y recursos comunes a ser reutilizados en otros modulos WAR.Además tenemos un proyecto WAR, denominado “proyecto-nuevo”, el cual necesita reutilizar clases bases y recursos existentes en el proyecto anterior. Para lograr la dependencia, tenemos que agregar las siguientes configuraciones: En el “proyecto-comun”, debemos agregar lo siguiente en el pom.xml:

 <plugin>  
      <groupId>org.apache.maven.plugins</groupId>  
      <artifactId>maven-war-plugin</artifactId>  
      <configuration>  
           <attachClasses>true</attachClasses>  
           <webModule>  
                <groupId>com.miempresa</groupId>  
                <artifactId>proyecto-comun</artifactId>  
                <contextRoot>/proyecto-comun</contextRoot>  
           </webModule>  
      </configuration>  
 </plugin>  

Acá lo importante es el tag “attachClasses”, que le dice a maven que cree un artefacto secundario con las clases del proyecto, las que más adelante nos van a servir para poder compilar el mismo.
Luego en el “proyecto-nuevo”, tenemos que agregar lo siguiente:

 <dependency>  
      <groupId>com.miempresa</groupId>  
      <artifactId>proyecto-comun</artifactId>  
      <version>1.0.0-SNAPSHOT</version>  
      <type>jar</type>  
      <classifier>classes</classifier>  
 </dependency>  
 <dependency>  
      <groupId>com.miempresa</groupId>  
      <artifactId>proyecto-comun</artifactId>  
      <version>1.0.0-SNAPSHOT</version>  
      <type>war</type>  
 </dependency>  

La primer dependencia, indica que las clases se deben compilar teniendo en cuenta el JAR generado automáticamente por el primer proyecto, y la segunda, que luego de compilar, primero copie los recursos del war anterior y luego sobre ese, los recursos del war actual, reutilizando archivos jsps, css, imagenes, xmls, etc.
Lo bueno de esta técnica, es que funciona correctamente con Eclipse (por las dudas usar siempre la última versión), utilizando el plugin m2eclipse, que por el momento es lo mejorcito que existe para trabajar con proyectos maven. La IDE correctamente interpreta la dependencia, y si tenemos los dos proyectos importados, ni siquiera hay que ejecutar el comando “mvn install” sobre el “proyecto-comun” para que tome los cambios, los toma automáticamente.

Que falta

De todas maneras existen algunos puntos sin resolver todavía:

  • No tenemos soporte para “mergear” el archivo web.xml, por lo que el web.xml del “proyecto-comun” va a ser pisado por el del “proyecto-nuevo”
  • Hay que tener cuidado de no crear clases en los mismos paquetes y con los mismos nombres, porque van a ser ignoradas (suponiendo que el application server le de prioridad a las clases del directorio “classes”)

Igualmente es una mejora substancial con lo que había antes, y permite tratar el código de presentación, prácticamente como si se tratase de una librería común, respetando su propio ciclo de vida, relacionado a las versiones, empaquetado, etc.