Dec 13

Un poquito decepcionado con los ESB

esb image  Hace tiempo que oí hablar de los Enterprise Service Bus (ESB) y con ellos he estado jugueteando por mi cuenta algún tiempo, leyendo e informándome en general, hasta que ha llegado la posibilidad de aplicarlo en un proyecto real.

En mi proyecto real, antes de tomar la decisión de si meter o no ESB y cual de ellos meter, decidí hacer algunas pruebas más en serio con los casos concretos que me iba a encontrar.

El primer punto son sockets TCP/IP con protocolo propio, es decir, mensajes binarios con su propia cabecera y forma de delimitar los mensajes dentro del flujo de bytes que es un socket TCP/IP. Mi primera opción de ESB, por supuesto, los gratis y más conocidos, en concreto, Apache Servicemix, Así que con él voy a hacer la prueba. Lo primero, es que si el protocolo es binario y no un simple protocolo de texto delimitado por retornos de carro, te tienes que hacer una clase java que sea capaz de hacer este trabajo por Apache Servicemix. De acuerdo, me puse a ello y conseguí hacerla…. pero me costó un buen rato de investigación. La documentación es escasa y en ningún sitio pone cómo hacerlo. Al final rebuscando por los ejemplos y fuentes del propio Apache Servicemix encontré cómo hacerlo. Esa ha sido mi primera pega/decepción con este ESB, la documentación es bastante pobre.

Y una vez conseguido, me pongo a probar y me encuentro una segunda pega. Un ESB implementa los Enterprise Integration Patterns (EIP), Y en ellos, hay dos posibles flujos de mensajes: En los que uno sólo envía y el otro sólo recibe, es decir, una única dirección, o bien los petición/respuesta, es decir, uno pide y el otro responde, por cada mensaje de ida debe haber uno de vuelta. Y eso a mí no me vale, en mi proyecto necesito que cualquiera de los dos lados, de modo espontáneo, puedan enviar o recibir, sin necesidad de haber enviado o recibido previamente una petición.

Bien, podría convivir con eso y seguramente encontraría algún tipo de solución.

Y se me ocurre probar lo que en EIP se llama controlbus, es decir, la posibilidad de parar y re-arrancar un flujo de datos a voluntad. Pues bien, Apache Servicemix lo soporta, da métodos start y stop para parar definitivamente el canal y pause/resume para pararlo temporalmente. Casualmente, con el componente camel-netty (que es el que nos proporciona socket TCP/IP), no funciona el suspend/resume. :(

Y finalmente, decido hacer otra prueba que también necesito, socket multicast. Pues bien, aunque teóricamente están soportados por Apache Servicemix, no es cierto, símplemente no funcionan. Hay dos componentes que nos pueden dar esta funcionalidad: camel-mina y camel-netty. Camel-Mina directamente dice que no lo soporta. Camel-netty sí, pero si lo pones, salta una excepción de "bind" y no funciona. Y no, no es que el puerto ya esté ocupado. Te pones a rebuscar en el código de camel-netty y ves que el test de JUnit que verifica el multicast directamente está deshabilitado. Y si lo habilitas, falla.

Así que decido pasar de Apache Servicemix, ya que me está dando demasiados problemas: falta de documentación para tus propios desarrollos, no funcina multicast… 

Y me busco otro ESB gratis, voy por jboss-fuse, y lo descarto casi inmediatamente. Tanto Apache Servicemix como JBoss Fuse se basan por debajo en la librería apache camel y la documentación de jboss es casi una copia de la de Servicemix. Así que mismos problemas … con uno añadido. Una de las cosas que aporta Jboss fuse en un eclipse "tuneado" para Jboss fuse, que permite definir gráficamente las rutas que quieres crear en el ESB… y que falla más que una escopeta de feria al menos con el componente camel-netty. Pongo el componente gráfico, relleno los formularios que salen …. y en el xml por debajo me genera mal la URL del punto de conexión. La arreglo a mano, y en cuento me descuido, me la vuelve a estropear.

Así que voy por otro ESB. El siguiente en la lista es Mule ESB. Este está mucho más guay, mucho mejor documentado, mis pruebas fueron bien a la primera, sin demasiada complicación …. pero me da la impresión de que es un ESB de pago. Creo que  me he bajado el trial de 30 días….

Con todo esto, ya casi he desistido de poner un ESB en el proyecto. Voy a darle un vistazo a wso2, que tiene muy buena pinta, la documentación parece buena y tiene pinta de ser gratis. A ver qué tal.

He visto por encima otros como OpenESB, Talend, y Synapse, pero son quizás menos conocidos y en todos ellos, mirando por encima la documentación, he visto alguna cosilla que no me acaba de convencer.

Estoy seguro que los ESB funcionan bien, ya que son bastante conocidos y aparentemente muy usados. Pero me da la impresión de que funcionan muy bien si te atienes a los protocolos para los que están pensados, en concreto y sobre todo, Web Services, JMS, HTTP, FTP, etc.

Jun 06

Tipado fuerte y débil, dinámico y estático.

error tipado de datosTodo esto del tipado en los lenguajes de programación es algo que más o menos creía tener claro y que seguramente es lo más básico de cualquier carrera de informática actual, pero yo ya tengo mis añitos, no he estudiado estas cosas y al buscar lenguajes para aprender, he visto que hay una sutil diferencia entre estático/dinámico y fuerte/débil. Vamos a ello.

Estático vs Dinámico

En un lenguaje con tipado estático, las variables llevan asociado el tipo de dato y no se puede cambiar. En los lenguajes de tipado dinámico, el tipo va más bien asociado al valor de la variable y no a la variable en sí misma, por lo que una misma variable puede contener a lo largo de la ejecución distintos tipos de datos.

Con tipado estático, es el mismo compilador el que comprueba que se asignan valores correctos a las variables, ya que sabe de qué tipo son las variables y qué tipo de valores pueden admitir. 

Con tipado dinámico, esta comprobación debe hacerse en tiempo de ejecución. Podemos meter en cualquier variable cualquier tipo de dato, por lo que hasta la ejecución no se sabe qué tipo de valor tiene una variable.

La ventaja del tipado estático es que se pueden evitar muchos errores en tiempo de compilación, sin necesidad de esperar a la ejecución para verlos. La ventaja del tipado dinámico es su flexibilidad.

Fuerte vs Débil

No parece haber un consenso claro de lo que es fuertemente tipado y débilmente tipado, pero parece que la idea más general es si el lenguaje permite cambiar unos tipos por otros de forma más o menos automática o no lo permite, salvo quizás de forma explícita. Me explico.

En javascript podemos hacer esto sin problemas

var a=3;
var b="4";
var c=a+b;

es decir, guardamos un entero en a, una cadena en b y luego las sumamos. Javascript, sin consultar con nadie, hace una conversión del entero 3 en cadena "3" y suma las cadenas, dando como resultado en c la cadena "34". 

En java, también podemos hacer algo parecido

int a = 3;
String b = "4";
String c = a+b;

dando como resultado una cadena "34"

Vemos que ambos lenguajes son débilmente tipados (entre comillas), pero java es estáticamente tipado ya que es necesario declarar los tipos de las variables, y javascript es dinámicamente tipado, ya que no es necesario.

La afirmación de que ambos son "débilmente tipados", hay que tomarla entre comillas. Javascript es más débilmente tipado porque siempre intenta hacer las conversiones necesarias para que el código se ejecute sin problemas, aunque a veces los resultados son sorprendentes. Java en este caso de sumar entero y String es débilmente tipado, pero solo para cositas muy concretas. Convierte tipos a String cuando lo necesita, pero poco más. Por ejemplo, en javascript todo esto es válido

if ("0"==0)  // es true
if ("0")  // es true
if ("") // es false
if ("3"==3) // es true

es decir, convierte String a integer para hacer las comparaciones, convierte "" en false en el tercer caso, etc, etc. Java daría error con cualquiera de estos if, por lo que no es tan débilmente tipado como javascript.

La ventaja de un lenguaje dinámicamente tipado es evidente, ahorra muchas conversiones explícitas que en algunos casos pueden ser muy tediosas. Sin embargo, la pega es que requiere un conocimiento profundo de cómo se hacen esas conversiones, o podemos encontrarnos con errores inesperados al realizarse alguna conversión que no esperamos.

May 30

Autocompletar en los IDE

autocompletar en javascriptPara trabajar siempre me gustan más los lenguajes estáticamente tipados que los dinámicamente tipados y entre otras ventajas, una de ellas es la de autocompletar de los IDE. Pero siempre que digo esto, alguien me comenta que si el IDE está correctamente configurado, los dinámicamente tipados también tienen autocompletar.

Bien, esto es cierto, pero sólo parcialmente. Imagina el siguiente trozo de código en un lenguaje estáticamente tipado, como java

public void metodo ( UnaClase parametro) {
   parametro.???
}

Cuando empezamos a teclear en la zona de ???, el IDE sabe que parámetro es de tipo UnaClase, porque se ve claramente, así que es perfectamente capaz de darnos los métodos y atributos públicos de parámetro para que elijamos uno.

Sin embargo, en un lenguaje dinámicamente tipado, si tenemos el código equivalente

function unaFuncion (parametro) {
   parametro.???
}

aquí el IDE no tiene ni idea de qué tipo es parámetro y de hecho, no puede saberlo, porque parámetro puede ser de cualquier tipo cuando el código se esté ejecutando, se puede llamar a unaFuncion() pasándole un entero, una cadena de texto, un objeto propio que hayamos creado o cualquier otro tipo que se nos ocurra. Así que el IDE aquí es totalmente incapaz de ofrecernos opciones, salvo que el lenguaje tenga algo común en todos sus tipos.

¿Cómo se apaña entonces para autocompletar?. Bien, un caso como el que acabamos de mostrar es imposible, pero los IDEs tienen sus trucos para ofrecernos opciones de autocompletar cuando es posible. Por ejemplo, en el caso anterior, si tenemos

function unaFuncion (parametro) {
   parametro.funcion1();
   parametro.funcion2();
   var a = parametro.atributo1;
   parametro.???
}

aquí el IDE ve qué cosas usamos de parámetro, así que cuando lleguemos a los ??? nos ofrecerá las funciones y atributos que ya hemos usado (funcion1, funcion2, atributo1), sean o no correctos y de hecho, pueden no ser correctos porque nos hemos equivocado al teclear o simplemente porque en tiempo de ejecución alguien nos pasa como parámetro algo que no tenga esas funciones ni atributos.

Otro truco usado por los IDE es el siguiente

function unaFuncion () {
   var b = new UnaClase()
   b.???
}

en este caso, se ve claramente qué contiene la variable b, aunque no tenga tipo definido, ya que estamos haciendo un new de una clase concreta y metiéndola en la variable. Si el IDE es capaz de encontrar en nuestro código la definición de UnaClase, será capaz de ofrecernos sus métodos/funciones y atributos … es justo el caso de la imagen.

Así que sí, los IDE pueden autocompletar en lenguajes dinámicamente tipados, pero con ciertas limitaciones.

May 23

Cuidado al sincronizar Boolean

 Depurando código de otra persona, encontré que hacía synchronized(variable) siendo variable un Boolean con mayúscula. Me llamó la atención de que dentro del bloque synchronized cambiaba el valor de la variable, algo así

synchronized(variable) {
   …
   variable = false;
   …
}

Me sonaba mal. Eso de cambiar la variable con la que estás sincronizando no parece limpio. Si otro hilo intenta sincronizar con la variable, puede estar sincronizando con otro objeto distinto y la idea no suele ser esa. De todas formas, decidí hacer una búsqueda en google y me encontré con esta pequeña joya de por qué no debemos sincronizar con Boolean.

Por un lado menciona lo que acabo de comentar, no es buena idea cambiar dentro (ni en general en ningún lado), el objeto sobre el que se está sincronizando. Si lo cambiamos, nunca tendremos garantía de que los hilos estén sincronizando sobre el mismo objeto, que es el objetivo de un synchronized. El objeto debe ser fijo. El enlace da varias alternativas correctas, como crear un Object lock = new Object() fijo para sincronizar con él o ver si nos valdría un AtomicBoolean con el que no tendríamos que sincronizar 

Sin embargo, lo que realmente me ha llamado la atención, es el comentario de que el Boolean es además especialmente problemático. Cuando hacemos esto

Boolean variable = false;

Java hace una conversión automática de false a Boolean.FALSE, ya que la variable es Boolean con mayúscula. Y java es listo, así que no crea instancias de Boolean.FALSE según hacen falta, sino que siempre reutiliza un mismo Boolean.FALSE. Y ahí viene el problema. ¿Qué pasa si sincronizamos dos grupos de hilos que son independientes cada uno con una variable Boolean que no tiene que ver con la otra?. Pues que podemos tener problemas porque sólo hay un objeto en todo java Boolean.TRUE y solo uno Boolean.FALSE, así que esos hilos que no tienen nada que ver están en realidad sincronizándose sobre el mismo objeto. En el siguiente código

// Hilo 1
Boolean unaVariable = true;
synchronized (unaVariable) {
   …
}

// Hilo 2 que no tiene nada que ver con Hilo 1
Boolean otraVariableQueNoTieneNadaQueVerConUnaVariable = true;
synchronized (otraVariableQueNoTieneNadaQueVerConUnaVariable) {
   …
}

hay dos hilos que no tienen que ver el uno con el otro y usan variables que no tienen que ver la  una con la otra….. están sicronizándose sobre el mismo y único objeto Boolean.TRUE que hay en java. Como mínimo, es una espera inútil. En el peor de los casos, puede dar lugar a abrazos mortales.

 

May 16

ESB vs MQ vs DDS

Ando últimamente mirando herramientas estilo Enterprise Service Bus (ESB), de colas de Mensajes (MQ) y Data Distribution Systems (DDS). La primera vez que oyes hablar de ellas te preguntas ¿qué son exactamente? ¿Para que sirven?. La primera explicación que encuentras en la Web de cualquiera de ellas es la habitual : "Una herramienta maravillosa que con poco trabajo te resuelve todos tus problemas y te va a hacer el más feliz de los programadores". Si profundizas un poco más, llegas a las definiciones técnicas que nadie entiende, como "Es la implementación del estándar JSR x33, bájate y lee el estándar de dos mil páginas para saber de qué estamos hablando".

Aquí va un "pequeño" resumen de qué son y para qué sirven, según lo he entendido tras andar investigando y jugando con algunas de ellas.

¿Cual es el problema que pretenden resolver?

Todas ellas pretenden resolver más o menos el mismo problema, pero lo hacen con diferentes aproximaciones, siendo más o menos intrusivas en nuestro desarrollo.

Imagina un sistema complejo en el que varios ejecutables están corriendo en varios ordenadores. Estos ejecutables colaboran entre sí enviándose mensajes unos a otros, compartiendo datos, repartiendo tareas, etc. El esquema podría ser similar al de la siguiente figura, donde hay tres ordenadores (las cajas cuadradas), con siete ejecutables A,B,C… y las comunicaciones entre ellos

Problema que pretende resolver ESB, MQ y DDS

Cada ejecutable conoce a los demás ejecutables con los que está trabajando y establece las conexiones que necesita para colaborar con ellos. Esta aproximación tiene varios problemas:

  • Cada ejecutable debe saber las IP/hosts y puertos donde están los otros ejecutables con los que colabora
  • Los ejecutables deben ponerse de acuerdo en el formato en el que se envían los datos.
  • Si más adelante queremos ampliar o modificar el sistema añadiendo, quitando o moviendo de sitio ejecutables, tendremos que tocar todos los ejecutables afectados. Por ejemplo, imagina que añadimos un cuarto servidor con ejecutables H y J que quieren colaborar con algunos de los ya existentes, casi seguro que tendremos que tocar los ya existentes para que admitan a los nuevos.
  • ¿Y qué pasa si alguno de esos ejecutables existentes no podemos tocarlo porque es un producto comercial, nos lo hizo otra empresa o se ha ido el desarrollador que lo concoce? (triste, pero real como la vida misma, a veces se va el que lo ha hecho y nadie más se atreve a tocarlo).

Dar flexibilidad a este tipo de montajes y facilitar la conexión con nuevos ejecutables es lo que pretenden resolver todo este tipo de herramientas ESB, MQ y DDS. Empezamos a ver la solución que propone cada una de ellas, empezando de la menos intrusiva (la que nos oblgaría a hacer menos cambios en nuestros ejecutables ya existentes) a la más intrusiva (que nos obligaría prácticamente a diseñar el sistema pensando en ella).

Enterprise Service Bus (ESB)

 Hay varias herramientas gratuitas de este tipo, como Apache Service Mix, Mule ESB, JBoss Fuse, WSO2 Enterprise Service Bus.La solución que proponen estas herramientas es arrancar uno o varios ejecutables ESB de forma que todas las aplicaciones se conecten al ESB en vez de unas con otras. Es en este ESB donde configuramos las rutas de las conexiones, diciendo por ejemplo, que lo que mande el ejecutable A se debe enviar al ejecutable B. El esquema sería parecido al siguiente

Enterprise Service Bus

Las bondades de esta solución son las siguientes

  • En el ESB se establecen las rutas de qué ejecutables hablan con qué ejecutables. De esta forma, el conocimiento de qué ejecutables hay y dónde están queda centralizado en el ESB, en vez de repartido por los distintos ejecutables de nuestra aplicación.
  • Estas rutas se pueden crear, modificar y eliminar en caliente, por lo que sería posible, por ejemplo, añadir un nuevo ejecutable a nuestro sistema y establecer las rutas en caliente para que este ejecutable sea capaz de enviar/recibir de los que ya están arrancados.
  • Las rutas pueden tener "inteligencia", de forma que pueden enviar un mensaje procedente de un ejecutable a varios ejecutables a piñón fijo, o bien seguir algún tipo de criterio para decidir a cual enviarlo, filtrar para enviar unos mensajes sí y otros no, etc, etc. Por supuesto, esta "inteligencia" se puede cambiar en caliente.
  • Como parte de la "inteligencia", las rutas pueden modificar los mensajes, siendo uno de los casos más habituales el cambio de formato de mensaje. Si un ejecutable usa el protocolo FTP y el otro HTTP, la ruta podría hacer la conversión correspondiente para, por ejemplo, coger ficheros de un servidor FTP y subirlos a una web con HTTP o al revés. Si los protocolos son estándar (FTP, HTTP, SNMP, XML, …) los ESB saben tratarlos y convertir entre ellos. Si no son estándar, podemos añadir nuestro trozo de código dentro del ESB para hacer las conversiones a nuestro gusto.
  • Otra ventaja adicional es que estas herramientas permiten de alguna forma monitorizar las rutas, de forma que podemos ver qué mensajes pasan por ellas, si se utilizan o no, si hay fallos, etc.
  • Las posibilidades que implementan las rutas suelen conocerse como "Enterprise Integration Patterns" o EIP. Siguiendo el enlace puedes ver todos estos patrones que suelen implementar.

Este es el mecanismo menos intrusivo porque nuestros ejecutables siguen siendo tal cual y enviando/recibiendo los mensajes en los formatos que ya tienen. Únicamente debemos cambiar la IP/host de conexión para que sea contra ESB en vez de unos con otros y nos queda el trabajo de configurar rutas en el ESB y darles la lógica que sea necesaria (conversiones de datos, filtros y en general cualquier EIP de la lista anterior).

Colas de Mensajes MQ

 Hay varias herramientas de colas de mensajes gratuitas, siendo ActiveMQ posiblemente la más conocida. Otras son RabbitMQ o Apache Kafka. La solución planteada es similar a ESB en el sentido de que debemos arrancar uno o más ejecutables MQ y nuestras aplicaciones deben conectarse a ellos. Sin embargo, es más intrusiva que ESB en el sentido de que debemos conectarnos con el protocolo que establece MQ, no podemos seguir conectándonos usando nuestros propios protocolos.

A MQ le enviamos mensajes en el formato que admite y cualquier otro ejecutable que tenga interés puede recibirlos. El esquema de trabajo sería como el siguiente

 Message Queue

Dentro de MQ se definen "topic" y "queue" con nombres, tantos como queramos. Los ejecutables envían mensajes a estos topic o queue. Otros ejecutables se suscriben a estos topic y queue de forma que recibirán los mensajes. La diferencia entre un topic y un queue es que un topic entregará sus mensajes a todos los ejecutables que se hayan suscrito, mientras que un queue sólo lo entregará a uno de los suscriptores. Un queue se utiliza más como un reparto de tareas.

Esta aproximación me parece más sencilla y elegante que la de los ESB, pero tiene el inconveniente de que nuestros ejecutables deben estar pensados para enviar y recibir mensajes a MQ, por lo que puede ser un trabajo modificar un ejecutable existente para adaptarse a MQ.

O quizás no. Los ESB suelen entender los mensajes de los MQ, de hecho, Apache Service Mix (un ESB) lleva integrado ActiveMQ (un MQ) Nuestra aplicación puede conectarse con su protocolo normal contra ESB y en ESB podemos establecer una ruta para convertir los mensajes en el formato de la aplicación a mensajes en el formato de MQ y enviarlos a MQ. Por otro lado, en otro sitio, haremos una ruta que recoja estos mensajes MQ, los convierta al protocolo que necesite la aplicación receptora y se los despache en el formato que ella entienda.

 Data Distribution Service DDS

De este tipo de aplicaciones hay menos gratuitas, pero tenemos por ejemplo OpenDDS y OpenSplice DDS. El concepto aquí es similar a las MQ, pero va más allá. Debemos arrancar uno o más ejecutables DDS y nuestras aplicaciones deben conectarse a ellos. La diferencia con MQ es que en DDS debemos definir todos nuestros tipos de datos y nuestros datos. Por ejemplo, si nuestra aplicación controla una flota de camiones, debemos indicar a DDS que tenemos un tipo camión con los campos matrícula, carga máxima, año de fabricación, modelo, marca, etc. y debemos indicar a DDS que vamos a tener una lista de camiones en revisión, una lista de camiones en recorrido, etc, etc.

A partir de aquí, nuestros ejecutables se conectan a DDS y en formato DDS van alimentando estos datos. Cualquier ejecutable puede a su vez suscribirse a los datos para enterarse de cambios en ellos. El esquema sería el siguiente

Data Distribution Service DDS

Esta solución como se puede intuir es la más intrusiva de todas, ya que no solo nos obliga a adaptarnos al protocolo de DDS, sino que de alguna forma dejamos en DDS la responsabilidad de mantener nuestros datos. Hasta cierto punto, DDS hace las veces de una base de datos (de hecho, suele tener una base de datos detrás que respalda nuestros datos), pero con la posibilidad de suscribirse a cambios. DDS suele además poder trabajar "distribuido". Varios ejecutables DDS interconectados entre sí, de forma que si metemos datos por uno de ellos, podemos retirarlo en cualquiera de los otros.

La principal ventaja de DDS es que está pensado para ser muy eficiente, por lo que no es raro encontrarlo en sistemas de tiempo real, defensa , espacio, transporte.

May 09

He leído “ActiveMQ in Action”

ActiveMQ in actionHe leído ActiveMQ in Action, una forma de enterarse de qué va ActiveMQ. El libro en sí no me ha gustado demasiado, se hace pesado de leer. Explica un concepto (eso sí es útil), te dice que el ejemplo de código de ese concepto está en tal sitio web, que para ejecutarlo uses tal comando y luego te planta dos páginas de libro viendo el log de salida del programa. Así una y otra vez.

Sin embargo, como yo soy más de enterarme bien de los conceptos que de andar mirando el detalle del código, el libro me ha servido para saber de qué va ActiveMQ y sus posibilidades.

ActiveMQ ofrece un servicio de mensajería entre distintas aplicaciones, o incluso para distintas partes dentro de una misma aplicación. Una aplicación o una parte de ella puede enviar mensajes a ActiveMQ y otra aplicación u otra parte de la misma pueden recoger esos mensajes. Aparte de esto, las características que mas me han llamado la atención de ActiveMQ son las siguientes:

Los mensajes pueden ser persistentes, es decir, se guardan automáticamente en ficheros o base de datos, según configuremos, de forma que si paramos la aplicación ActiveMQ y la volvemos a arrancar más adelante, los mensajes no entregados cuando paramos la aplicación, se recuperan y se pueden entregar en cuanto alguien los recoja.

Tiene posibilidad de arrancar varios ActiveMQ para trabajar colaborando, bien en forma de cluster, bien en configuración maestro-esclavos. En la configuración de cluster, los ActiveMQ se interconectan entre sí, de forma que si entregamos un mensaje en uno de ellos, se puede recoger en cualquiera de los otros. La configuración de cluster es muy sencilla, tiene posibilidad de "autodescubrimiento" de forma que según se vayan arrancando aplicaciones ActiveMQ en la red local se incorporan automáticamente al clustter, o bien podemos indicar las IPs concretas donde está cada ActiveMQ, para formar un cluster fijo. En cuanto a la configuración maestro-esclavo, es también sencilla. Un ActiveMQ es el que hace de maestro y es al que se conectan las aplicaciones. Los esclavos únicamente van guardando réplicas de los mensajes. Si el maestro se cae, uno de los esclavos entra en funcionamiento y las aplicaciones deben re-conectarse al nuevo maestro. Las librerías para clientes de ActiveMQ se pueden configurar de forma que hagan esta reconexión automáticamente.

Y lo que más me ha gustado, embeber un ActiveMQ dentro de nuestra propia aplicación es casi inmediato. Si ponemos la dependencia del jar adecuado (activemq-broker y activemq-client), basta con que nuestra aplicación establezca una conexión contra ActiveMQ usando el protocolo "vm://un-nombre" y automáticamente se creará una instancia de ActiveMQ con nombre "un-nombre" dentro de nuestra aplicación, disponible para cualquier parte de ella. Si además, a esa instancia le creamos una conexión adicional  "tcp:….", otros programas externos podrán conectarse a nosotros para recibir nuestros mensajes o enviarnos los suyos propios. También podemos crearle conexiones de red adicionales, de forma que nuestra instancia embebida de ActiveMQ forme parte de un cluster externo de ActiveMQ.

En resumen, me ha gustado la herramienta, es bastante simple de poner en marcha, de montar clusters e incluso de embeberla en nuestras aplicaciones. No me ha gustado que el envío de mensajes es relativamente tedioso: hay que crear la conexión, de la conexión una sesión, de la sesión un destino que no es más que un nombre, del destino crear una cola o un topic (son dos posibles formas de distribución del mensaje), un producer (el que envía el mensaje), construir el mensaje y enviarlo. Muchos de estos pasos se pueden dejar preparados para no repetirlos muchas veces, pero no deja de ser "un pelín" engorroso. Con la recepción algo similar.

De todo esto han salido algunos tutoriales de ActiveMQ en la Chuwiki.

May 01

Jugueteando con Scala

Tras el último post "Eligiendo lenguaje … ¿Scala?" me he puesto manos a la obra. Estoy leyendo el libro "Programming Scala" de la foto y, naturalmente, jugueteando con el IDE para Scala.

En una semana de leer y juguetear en tiempos libres, por supuesto, no he avanzado mucho, pero lo que estoy viendo me gusta bastante.

El compilador de Scala genera ficheros .class compatibles con la máquina virtual java y por tanto, es posible usar librerías compiladas con java (.jar) en Scala y es posible generar librerías (.jar) con Scala para usar en java. A mí, como programador Java, esto me facilita enormemente la vida, porque puedo introducir parcialmente Scala en mis proyectos. No, no mezclar en un mismo proyecto fuentes Java y fuentes Scala, porque no me parece elegante, pero sí crear librerías Scala que utilizaré en mis proyectos Java o viceversa.

En cuanto a la sintaxis de Scala, me da la impresión de que trata de resolver muchos de los problemas que tiene la sintaxis de Java. Aparte de ser menos verboso que Java, yo creo que lo más importante es que permite hacer cosas que Java no permite de forma fácil o simplemente no permite. Hay muchos detalles y todavía no he terminado el libro, menciono sólo algunos.

En Java la estructura de directorios tiene que coincidir con la de paquetes. En Scala no es necesario para los fuentes, aunque los .class que genera sí lo necesitan por compatibilidad. ¿Esto contribuye a desorganizar el código?. Depende de nosotros, pero de mano elimina la necesidad de crear los directorios habituales correspondientes al "dominio". Quiero decir, en mi caso todas mis clase están en el paquete "com.chuidiang" y eso en Java me obliga a meter los fuentes en un directorio "chuidiang" debajo de un directorio "com". Dos directorios "inútiles" que en Scala me puedo cepillar sin problemas.

En Java hay public, protected y private con características determinadas. En Scala se amplían estas posibilidades, ya que se permiten poner cosas como private[package] que haría el atributo/método visible no solo para la clase que lo contiene, sino para cualquier clase en el paquete, o cosas como private[this] que hace que el atributo/método sólo sea visible para esa clase, y no como en Java, que también sería visible para las clases anónimas o internas declaradas dentro de esa clase.

En Scala basta declarar una clase poniéndole parámetros en la declaración. Esto crea automáticamente el constructor con esos parámetros, los atributos privados para esos parámetros y los setter y getter (aunque sin seguir la convención java de setParametro() y getParametro()) correspondientes para esos parámetros. Desde luego, mucho menos código que en java

class Point (x:Int, y:Int) {
   // No es necesario declarar atributos x,y ni sus setter y getter
   // Scala lo hace automáticamente
   …
}

Y todo esto no dejan de ser pequeños detalles, Hay otras características muy interesantes. Por ejemplo, el switch-case en Java está bastante limitado, sólo sabe de tipos primitivos (int, char, etc), enumerados y de clases que están asociadas a estos tipos (Char, Integer, …). En los case, además, sólo se pueden poner valores constantes. El equivalente en Scala al switch-case es match, que es como el switch-case, pero a lo bestia. En el match podemos poner cualquier tipo de variable, incluidas colecciones. En los case se ponen "expresiones" predefinidas pero muy potentes. Pueden ver si la variable del "match" es de un tipo u otro, si es una colección con n elementos, si el elemento número 3 es un elemento concreto, etc, etc. Los programadores Java muchas veces hemos tenido que liarnos a if-elseif porque switch-case no es lo suficientemente potente. Otro detalle interesante de match es que devuelve un valor, el que devuelva el case correspondiente.

Otro punto muy interesante de Scala son los "trait". Un "trait" no es más que una clase que se puede añadir como "pegote" a otra clase

class UnaClase extends UnPadre with UnTrait {

}

Podemos poner varios with con varios trait en la definición de la clase, con lo que la clase tendrá como "pegotes" los métodos y atributos de los traits. No es una herencia, puesto que en la clase no haríamos llamadas estilo super.metodoDelTrait(), sino que simplemente podemos llamar a metodoDelTrait() como si fuera un método de nuestra propia clase. Esto es realmente útil y un ejemplo muy claro con el que estoy harto de tropezarme es el siguiente : Patrón Observador. Hago clases Java que tiene suscriptores a eventos que pasan dentro de esa clase. En todas esas clases tengo que poner un atributo con la lista de observadores, método addObserver(), removeObserver() y fireEvent() para avisar a los observadores. No puedo meter ese código en una clase y heredar de él porque Java no admite herencia múltiple y a veces necesito que esa clase herede de otra cosa. Ayuda algo meter esa clase que mantiene la lista de observadores como un atributo de mi clase principal, así en mi clase principal sólo debería añadir métodos addObserver() y removeObserver() que llamen a los del atributo. Pero la solución del trait es la ideal. Me basta con añadir with Observers en la declaración de mi clase para tener todo listo. Por supuesto, los trait pueden ser genéricos, de forma que la interface del observador puede ser la que queramos en cada caso, en el siguiente ejemplo, esa interface sería ButtonListener

class UnaClase extends UnPadre with Observers[ButtonListener] {

Otro detalle curioso e interesante. Si una clase tiene un método con un parámetro, en la sintaxis no es obligatorio poner el punto para llamar al método ni los paréntesis para poner el parámetro. Eligiendo adecuadamente los nombres, podemos "acercarnos" mucho a un lenguaje natural. Por ejemplo, serían equivalentes cosas como

if ( unaVariable.is(7) ) {
   …
}

if ( unaVariable is 7 ) {
   …
}

Si además ese método en vez de un boolean como en el ejemplo, devuelve otra clase que a su vez tiene un método con un parámetro, podemos encadenar llamadas y así, no es raro ver en las suite de test de Scala (similares a JUnit), cosas como 

"An empty collection" should "have size 0" in ….

En fin, sigo en ello, pero de momento es un lenguaje interesante donde los haya, con muchas posibilidades, tanto "anecdóticas" en el sentido de que sólo facilitan no escribir tanto, como de "ampliación" de lo que no es fácil o posible en Java.

Apr 25

Buscando lenguaje … ¿Scala?

scala programming language Llevo muchos años trabajando con java y llevo ya un tiempo pensando que va siendo de comenzar a aprender algún lenguaje de programación  nuevo. He jugueteado algo con python, también con groovy, trabajo con javascript con cierta frecuencia, le he echado un ojo por encima a ruby … pero son lenguajes que no me acaban de convencer.  ¿El motivo? Que no son lenguajes estáticamente tipados. Eso hace que los IDEs sean bastante deficientes a la hora de autocompletar lo que estás escribiendo, que puedas cometer errores de tecleo en las variables o métodos y no los descubras hasta tiempo de ejecución.

Dicen que son menos verbosos que java y que eso ahorra tiempo, pero tengo serias dudas si el tiempo que ahorras en escribir código no lo pierdes luego corrigiendo errores tontos de tecleo arrancando una y otra vez tu programa para descubrirlos en tiempo de ejecución. Sobre todo si el programa es un programa grande que requiera todo un montaje para arrancarlo y llegar a la zona de código que quieres probar. Sí, se que existen cosas como los test unitarios, pero también tendrías los mismos problemas de tecleo al escribir test unitarios y también sé que hay cosas que son muy difíciles de probar con test unitarios.

Por la curiosidad de aprender el lenguaje sí. Javascript, que pensaba antes de conocerlo que era un lenguaje "tonto",  me ha asombrado con sus cosas y su potencia. Entiendo que groovy, ruby, python también lo son, al menos en lo poco que he visto. Pero forma parte de mi objetivo, aparte de satisfacer mi propia curiosidad por el lenguaje, el poder darle luego una utilidad práctica en el trabajo, y la experiencia de trabajar en javascript me hace ver lo importante que es usar un lenguaje estáticamente tipado.

Ayer leí Why should I learn Scala, y creo que me ha decidido a darle una oportunidad a Scala.

Es un lenguaje del que se oye bastante últimamente y que ves que se está usando. En mis proyectos maven, cuando uso plugins o librerías de terceros, veo que rápidamente van bajándose plugins de scala y que lo usan, aunque sea por debajo. Además, es compatible con java en el sentido de que genera código compilado para la máquina virtual java, por lo que podría integrarlo fácilmente en nuestros proyectos. Sé que queda feo mezclar unos módulos en java y otros en Scala, pero es una opción para que el cambio no sea brusco.

El artículo además apoya (o al menos da importancia) mi punto de vista de la necesidad de lenguajes estáticamente tipados. Siempre es mejor encontrar errores mientras se escribe en el IDE o mientras se compila, que encontrarlos a base de probar en tiempo de ejecución.

Y el artículo además menciona un pequeño detalle con el que también tengo manía: Los setter y getter. Aunque no recuerdo dónde lo leí, decían que una ventaja de groovy era que no era necesario poner setter y getter, ya que el lenguaje los generaba automáticamente y los usaba por debajo. Pero los setter y getter tienen un motivo de existir y no son sólo para que estén. Es importante poder meter lógica más adelante en el setter o en el getter, o incluso mantenerlos tal cual aunque el atributo al que referencian cambie de tipo y/o nombre. Y parece que scala tiene contemplado ese caso. Aunque no sea necesario poner getter y setter, si es posible añadir lógica cuando se asigna un atributo e, imagino, que también cuando se lee.

Así que ayer me bajé un IDE de scala y voy a juguetear unos días a ver qué tal.

Apr 18

Cómo cambian los tiempos

Los que llevamos ya unos años, quizás muchos, metidos en informática y en programación, tenemos la costumbre de poner los nombres de los directorios y de los ficheros sin espacios. Ponemos cosas como ESTO_ES_UN_DIRECTORIO o EstoEsUnFichero.txt o cualquier variante que se nos ocurra. Cualquiera que no lleve espacios.

El otro día, mi hija de 18 años, me vio crear un directorio y totalmente extrañada me preguntó

"Papá, ¿por qué pones subrayados en vez de espacios?".

Ella, como usuaria de los windows modernos, que no sabe que existe el cmd.exe, es incapaz de entender esa extraña manía de su padre. Finalmente añade

"Mi profesor de animación gráfica por ordenador hace lo mismo"

Sobran las explicaciones. 

Nov 30

Sobre angularjs

Porque me ha tocado en el curro, me he leído AngularJS by Brad Green and Shyam Seshadri y he empezado a trabajar con AngularJS. Aprovecho aquí para comentar el libro y los conceptos básicos de angularJS.

El libro

El libro no me ha hecho demasiada gracia. Los dos primeros capítulos sí me gustaron, muy sencillos y explican lo más básico de angularJS. Sin embargo, a partir del tercer capítulo, la cosa se complica y no me parece que hayan conseguido explicarla bien. Empiezan a meter mucho código con muchas de las cosas propias de angular sin dar una explicación detallada de ellas, por lo que aunque intuyes de que va el tema o cómo funciona, los detalles no te quedan claros. Imagino que con la práctica me acabe enterando.

Los conceptos

angularJS es un framework MVC javascript mantenido por google. Ya estamos con los "palabros", vamos a intentar explicarlo.

En angularJS el modelo no es más que una variable javascript llamada $scope en la que se añaden de la forma normal en javascript todos los datos (modelo) que queramos.

La vista es un HTML en el que podemos poner algunas cosas específicas de angularJS. Por ejemplo, un párrafo podría ser <p>{{unaVariable}}</p> done unaVariable es un atributo de $scope, es decir, $scope.unaVariable existe y es lo que se pondrá dentro de los tags <p> y </p>. Una característica interesante de angularJS es que esta relación es bidireccional y automática, de forma que si nuestro código javascript modifica el valor de la variable, automáticamente se refleja en la vista HTML, y si ese {{unaVariable}} lo pusieramos en un input text así <input type="text" ng-model="unaVariable">, en cuanto el usuario teclea se actualiza la variable.

El controlador es una clase javascript en cuyo constructor recibe el $scope (y otras cosas) y se encarga de rellenarlo con los datos que necesitemos. También a esa clase le ponemos todas las funciones javascript que necesitemos y a las que se podrán llamar desde los distintos eventos de HTML (onclick, submit, etc).

Por supuesto, podemos hacer un HTML principal (index.html o similar) que dentro llevará varias vistas, cada una con su propio modelo y controlador. La idea es hacer una aplicación de simple página e ir reemplazando dentro de ella los distintos trozos HTML según el usuario vaya pulsando botones y menús.

Aparte de este concepto MVC, angularJS tiene una serie de utilidades que resuelven los problemas típicos en cualquier aplicación web. Veamos los más importantes

Directivas : En angularJS podemos definir nuestras propias directivas, aparte de las que angularJS ya nos proporciona. Una directiva es una forma de reemplazar un tag a atributo de un tag html por lo que  nosotros queramos. Un ejemplo tonto sería hacer una directiva "horaActual", de forma que si en nuestro HTML ponemos <horaActual></horaActual> se reemplazará por la fecha/hora actual (porque así lo hemos codificado en la directiva). Por supuesto, el código que hay que hacer es más sencillo que andar buscando los tags HTML y reemplazándolos a pelo.

Servicios : En angularJS podemos definir servicios, que simplemente son código javascript realizado por nosotros con determinadas funciones que queremos poder aprovechar en varios sitios. Si creamos un servicio con una serie de funciones javascript, angularJS podrá pasarlo como parámetro en el constructor de los controladores, de forma que estos tendrán disponible y podrán usar las funciones javascript de nuestro servicio. Es bastante habitual hacer que los servicios sean los que hablen con el servidor, para pedirle información que debe presentarse al usuario, o enviarle las operaciones que ha realizado el usuario.

Promises : Relacionado con los Servicios cuando estos hacen llamadas al servidor, tenemos las Promises. Si el usuario hace una operación que necesita enviar y esperar respuesta del servidor, normalmente llamará a una función javascript de uno de nuestros servicios. Este función hará la llamada al servidor (con AJAX por ejemplo) y recibirá de forma asíncrona el resultado. Pues bien, nuestra función javascript del servicio puede devolver inmediatamente, sin esperar el resultado, una de estas Promises, que no es más que una instancia de una clase javascript de angularJS, y cuando tenga el resultado llamar al método resolve() de la Promise. angularJS se enterará y actualizará el modelo cuando el resultado esté disponible (hayamos llamado a resolve). Un pequeño ejemplo lo dejará más claro

function pideDatosAlServidor (…, $q) {     // $q es un objeto específico que nos pasará angularJS para trabajar con Promises
   var defer = $q.defer();            // Obtenemos un objeto deferred para manejar nuestra Promise
   $.get ("url", function (data) {          // Nuestra llamada a ajax. AngularJS tiene parte de jQuery embebido.
       // hacemos algo con los datos recibidos
      defer.resolve();                      // Indicamos que ya se dispone de los resultados.
   }
   return defer.promise;             // Devolvemos la Promise
}

Fíjate que la llamada a $.get() es una llamada AJAX que llamará a function(data) cuando se tengan los resultados. El código pideDatos() hace esta llamada y directamente, sin esperar el resultado, devuelve el defer.promise. Esto le bastará a angularJS para saber que tiene que esperar por los datos antes de refrescar la página.

Test : AngularJS está pensado para que se puedan hacer test unitarios y de integración, por lo que viene con herramientas como e2e (end to end), facilitando, con herramientas adicionales, incluso cosas como levantar un servidor para los test y ejecutarlos.

Por supuesto, angularJS tiene otro montón de cosillas típicas para ayudarnos en nuestro desarrollo, como facilidades para la internacionalización, validación de formularios, bucles en las plantillas HTML, filtros, etc, etc.

Bueno, me he quejado de que el libro no explica bien, y escribiendo esto veo que es difícil explicarlo bien, pero al menos no  he necesitado 175 páginas.