Mostrando las entradas con la etiqueta back-end. Mostrar todas las entradas
Mostrando las entradas con la etiqueta back-end. 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 :)

Testeando cron expressions: CronMaker

Intentando entender algunas expresiones complicadas de quartz, llegué a este sencillo pero interesante servicio: CronMaker.Es un sitio web que permite construir y testear las cron expressions de quartz.
Para poder construirlo se puede seleccionar si se quiere que la expresión sea cada minuto, hora, dia, semana, mes, etc. Pero lo más interesante ​es la posibilidad de tener un "preview" de las cron expressions con el boton "Calculate next dates".


Preview de la cron expression

Un sitio interesante para bookmarkear.