RabbitMQ: cómo enviar objetos .NET y recibir objetos JAVA

June 4, 2014 by
Bacalov, Damian

RabbitMQ es un servidor de mensajería multiplataforma con clientes para una gran variedad de lenguajes incluyendo Java, .NET, Ruby, Python, PHP, Perl, C++, entre otros.

Nos permite desacoplar capas de aplicación no sólo en diferentes aplicaciones sino también en diferentes servidores e incluso localizaciones.

Existe una gran cantidad de librerías escritas en diferentes lenguajes que nos facilitan publicar y consumir mensajes utilizando RabbitMQ.

EasyNetQ

La librería más conocida para Microsoft .NET lleva por nombre EasyNetQ. Según su documentación, sus mayores logros son: enviar objetos .NET como mensajes, rutear los mensajes basados en los tipos de objetos de .NET.

Esto ciertamente hace mucho más sencilla la tarea de desarrollar de aplicaciones con .NET. Pero, ¿por qué uno haría tal cosa?

¿Por qué convertir en propietaria una herramienta multiplataforma?

Siendo una extraordinaria característica de RabbitMQ la cantidad de clientes en diferentes lenguajes y plataformas, ¿por qué integrarlo de modo que sólo Productores (quienes envían mensajes) y Consumidores (quienes reciben mensajes) programados en .NET puedan sumarse a la plataforma?

En mi opinión, lo más lógico es dejar las opciones abiertas de modo que nuestro sistema sea lo más flexible para requerimientos futuros. Y esto incluye la posibilidad de sumar Productores y/o Consumidores desarrollados en otros lenguajes.

Enviando objetos .NET y recibiéndolos como objetos JAVA

Para lograr este objetivo, me basé en la universalidad de JSON para describir objetos y en dos librerías para su procesamiento:

Jackson Mapper para Java
Newtonsoft.Json para .NET

Productor en .NET

Comenzamos con una entidad “Usuario”. Lo único a tener en cuenta es usar propiedades en minúsculas.

Clase Usuario

Luego, para enviar el objeto como mensaje RabbitMQ escribimos:

var usuario = new Usuario();
usuario.nombre = “Nombre”;
usuario.apellido = “Apellido”;
usuario.email = “[email protected]”;
usuario.etiquetas = new string[] { “vmware”,”pivotal” };
usuario.mensaje = “¡Hola mundo!”;
// Enviamos el mensaje. La clave de ruteo podría ser el tipo de objeto.
var body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(usuario));
channel.BasicPublish("route", routingKey, null, body);

Consumidor en JAVA

En mi proyecto utilizo Maven por lo que, para referenciar la librería Jackson Mapper, agregué la siguiente dependencia en el archivo pom.xml:

<dependency>
   <groupId>org.codehaus.jackson</groupId>
   <artifactId>jackson-mapper-asl</artifactId>
   <version>1.9.13</version>
</dependency>

Luego, creamos la entidad Usuario:

Usuario.JAVA

Finalmente recibimos el mensaje:

delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
// Convertimos en objeto
ObjectMapper mapper = new ObjectMapper();
Usuario u = mapper.readValue(message, Usuario.class);
// Imprimimos el objeto recibido
System.out.println("Nombre: " + u.getNombre());
System.out.println("Apellido: " + u.getApellido());
System.out.println("Email: " + u.getEmail());
System.out.println("Etiquetas: " + 
   StringUtils.arrayToCommaDelimitedString(u.getEtiquetas()));
System.out.println("Mensaje: " + u.getMensaje());

Conclusión

Enviar objetos JSON implica que los mensajes son más grandes pero, si esto no es una restricción en nuestro sistema, la ganancia en flexibilidad es enorme y bien vale la pena el costo.