Spring y JMS

Usamos Spring Framework (no Boot) yJMS (ActiveMQ). Y le estamos dando bastante caña, por lo que empezamos a sospechar si algunos de nuestros problemas de rendimiento pueden venir por ahí.

Spring trae por defecto un conversor de las clases java a XML para el envío del mensaje por JMS y luego el desparseo correspondiente en la parte de recepción. Son las clases MarshallingMessageConverter y XStreamMarshaller actuando conjuntas.

Por ver si afecta a la eficiencia y aprovechando que Spring, quizás no de forma fácil o evidente, es bastante configurable, me he hecho un par de conversores de mensajes JMS/Spring pero usando Jackson para convertir a JSON en vez de XML y otro usando Kryo para convertir a bytes de forma eficiente y ver si afectan o no al rendimiento global de la aplicación.

No tengo todavía resultados que mostrar aquí, actualizaré este post cuando corresponda, pero ambas clases de conversión las tienes en el ejemplo de spring y jms. Bastaría instanciarlas en spring y meterlas como messageConverter en los jms:listener o jmsTemplate de Spring.

Mi segunda intención, independientemente del resultado, es ver qué me cuesta cambiar la aplicación para que use la nueva versión de ActiveMQ ( ActiveMQ Artemis ) que como dice su propia página web

Apache ActiveMQ Artemis is an open source project to build a multi-protocol, embeddable, very high performance, clustered, asynchronous messaging system

Vamos, «high performance» entre otras cosas. Espero que junto con Spring sea tan sencillo como cambiar dependencias de compilado y algo de los ficheros de configuración.

Empezamos también a cambiar ActiveMQ por Hazelcast. Pero no sé si me ha convencido. Hazelcast es una de las primeras cosas que de forma extraña se nos cae cuando hay problemas de red entre los distintos PCs y por otro lado, me he encontrado con cosas como que un Map.size() devuelve números negativos en ocasiones. Se «arregló» actualizando versión de Hazelcast, pero este tipo de cosas no sé si me convencen.

Así que nada, siguen los experimentos en busca de la «high performance» 🙂

¿Sopa de piedras o capitán araña?

 

Título un poco raro. ¿qué es cada cosa?. La sopa de piedras hace referencia a una historia y una técnica para conseguir las cosas, explicada en "The pragmatic programmer". El capitán araña hace referencia al dicho "Capitán araña, que a todos embarca y a todos engaña".

En la historia de la sopa de piedras, unos soldados entran en una aldea enemiga y todos los aldeanos se esconden con toda su comida. Los soldados, hambrientos y sin posibilidad de conseguir comida de los aldeanos, cogen una olla, la llenan con agua de río y unas piedras. Lo ponen todo al fuego y empiezan a comentar lo rica que estará la sopa de piedras, típica de su país. Los aldeanos, con curiosidad por una cosa tan extraña se acercan y preguntan por la famosa sopa de piedras. Los soldados comentan que es un plato riquísimo, típico de su país, pero que no va a estar del todo buena porque le falta un poquito de sal. Los aldeanos traen la sal y entonces los soldados comentan que, para que la sope esté perfecta, necesitaría también unas patatas. Tras varias maniobras de estas, consiguen todos los condimentos para una sopa en condiciones (en cuanto sacan las piedras).

Según se comenta en el libro The pragmatic programmer, esta es una forma de conseguir las cosas. Cuando quieres conseguir algo y no encuentras apoyos, lo mejor es empezarlo tú mismo hasta donde puedas y enseñar los resultados a los demás. De esta forma, es más fácil que los demás estén dispuestos a añadir su granito de arena que tener que hacer ellos todo el trabajo.

Hace algún tiempo rubén puso un comentario en este blog indicando que le gustaba mi técnica de marketing viral para propagar las cosas entre mis compañeros de trabajo. Yo prefiero pensar que hago sopas de piedras. Que creo que es bueno usar Spring Framework, comienzo/modifco un proyecto para que use Spring Framework y le enseño a los demás como funciona y sus ventajas. Que creo que es bueno usar Javahelp, preparo la estructura por debajo, hago la ayuda de las primeras ventanas y enseño lo bonito que queda. Que creo que es bueno usar redmine, lo instalo, meto algún proyecto y lo enseño a la gente.

Pero claro, también está la versión de mi compañero de trabajo. Viene a decir algo así como "Empiezas las cosas hasta que ya no se puede volver atrás y luego no nos queda már remedio que seguir el camino que has empezado". Vaya, lo del capitán araña.

En fin, a mi me gusta más pensar en lo de la sopa de piedras y espero que mi "compa" me lo diga en broma, pero claro, también es mi opinión y es más subjetiva….

Puzzle inverso

Normalmente, en un puzzle, tienes las piezas y "sólo" hay que encajarlas. Sin embargo, estos días he estado codificando un poco (¡¡ pof fin!!) y estoy haciendo en el proyecto una pequeña funcionalidad. El proyecto usa Spring Framework e iBatis. Y el puzzle es "inverso".

Resulta que Spring ya tiene cosas hechas, con iBatis hay cosas que se hacen solas, y con algunas de las librerías que tenemos también. Sólo hay que implementar determinadas interfaces y pasárselas a todo esto. Y eso es lo curioso de este puzzle, esas implementaciones son las piezas que faltan, tienen sus huecos asignados y sólo tienes que hacerte las piezas.

Me explico. Un fichero xml para iBatis con las consultas. Una implementación de DAO que llame a iBatis. Unas clases para convertir los datos devueltos por iBatis a datos propios de la aplicación. Una configuración para el DataSource, etc, etc, etc. Y milagrosamente, tras hacer trozos sueltos de código aquí y allí y meterlo todo en su sitio… ¡¡ funciona !!.

La verdad es que si estás acostumbrado a esas herramientas, se hace todo en un "pis-pas" y con cierta garantía de que funcionará. La pega es que el programar se hace un pelín más aburrido, ya que hay poco que pensar y sólo tienes que hacer clases mecánicas con poco o nada de código interesante.

Cambiando de tema, ¿por qué estoy codificando ahora?. Muy sencillo. Después de que me dieran una especificación adecuada ("no sé qué quiero, pero debe estar para mañana"), yo he hecho un diseño adecuado a esa especificación ("vete haciendo, que luego ya hablaremos") y los codificadores han hecho un código según el diseño

public class ElProyecto {
   public static void main (String [] args) {
      // To be defined.
   }
}

Hoy ya es mañana, así que toca que todos como locos quitemos el "to be defined": y rellenemos el código de dentro.

Pensamientos sobre proyectos grandes y Spring Framework

En su día, para nuestros proyectos grandes, teníamos muchas librerías y módulos separados. Cada programador solía ser responsable de uno de los módulos y tenía su proyecto independiente, con sus programas de prueba, simuladores y todo lo que le hiciera falta.

Eso estaba bien, pero tenía una ligera pega. No usábamos algo como maven y no teníamos control ninguno de dependencias cruzadas. Cada programador ponía sus dependencias de otros módulos según lo necesitaba. El problema, al final, es que no había forma de compilar eso desde cero, ya que era fácil que un módulo necesitara del jar de otro módulo, que a su vez necesitaba de un tercero y tras una cadena más o menos larga, había un módulo que necesitaba del jar del que estamos compilando. Sí, ya sé que es una falta grave de diseño y debería haberse pensado al principio y dejar claras esas dependencias, pero también es cierto que entre lo que lo pensado antes y la realidad después hay muchas diferencias.

Al usar maven, decidimos hacer un proyecto grande con subproyectos debajo (uno por módulo). Así maven comprueba las dependencias y si un programador pone una dependencia que no debe, maven le protesta. Sin embargo, esto también tiene una gran pega. El compilado desde cero se hace desde arriba del todo y el fallo de un módulo hace que los demás ni siquiera intenten compilar. Además, la dependencia se hace entre fuentes, por lo que para estar a la última, necesitas hacer update de todos los fuentes. Eso, en un proyecto grande, puede ser un buen rato casi todos los días.

Al descubrir que se puede usar el core de Spring Framework, aunque sean aplicaciones de escritorio, para instanciar los módulos y usar los eventos de Spring Framework para comunicarlos entre sí, me da la impresión de que se puede hacer relativamente fácil que los módulos hablen entre ellos y se pasen datos sin necesidad de que tengan dependencias entre ellos. Los primeros mini-proyectos en la que hemos usado este framework y hemos hecho módulos indpendientes totalmente, comunicados a través del framework y de código de transformación de tipos de datos de un módulo a los tipos del otro en el main, están resultando una pequeña maravilla en cuanto a organización.

Así que me estoy planteando el volver a módulos separados, en proyectos independientes, y con prohibición de poner dependencias de otros módulos, salvo algunos muy concretos pensados más como librerías comunes que como módulos a instanciar como beans de Spring Framework.

La pega es la de siempre, la paliza de mover todos los repositorios de CVS para que tengan otra estructura y el retocar todo el código, sobre todo quitando dependencias de unos módulos con otros. Todo se andará, poco a poco.

Una pequeña aclaración sobre las dependencias entre módulos. Suponamos que tenemos modulo1.jar y modulo2.jar y que modulo1.jar necesita llamar a cosas de modulo2.jar. Para no meter la dependencia a lo bestia, normalmente hacemos una InterfaceModulo2 con las llamadas a las cosas del módulo2 que sean de interés desde fuera. Por supuesto, esa interface está en modulo2.jar. Y por supuesto, los parámetros y retornos de los métodos de la interface son tipos primitivos de java o bien tipos que están en modulo2.jar. Pues bien, eso hace que modulo1 dependa de modulo2, ya que ve al menos a la interface y a los tipos de parámetros y retornos. Por supuesto, una opción es hacer un tercer módulo InterfaceModulo2.jar con la interface y los tipos, pero me parece multiplicar el número de jars a lo tonto.

La opción que estamos planteando ahora es que modulo1 no vea en absoluto a modulo2. Cuando necesite algo de módulo2 (en realidad, cuando necesite algo, lo que sea), debe lanzar un "evento" indicándolo. Es el código del main el encargado de recoger ese evento y hacer la petición a modulo2, para pasar luego los resultados a módulo1. Esto puede parecer costoso, sobre todo si hay mucha necesidad de cosas de modulo2 por parte de modulo1, pero… si hay tanta necesidad de cosas ¿no estará mal pensado hacer dos modulos? ¿no estará mal pensada la funcionalidad de cada módulo?.

En fin, un pequeño rollo, pero como indico en el título, son símplemente "pensamientos".