Páginas

viernes, 26 de abril de 2013

Ejemplo JMS Topic con Spring 2.5 y ActiveMQ

Introducción

En el siguiente ejemplo montamos una demostración de cómo configurar un publicador (publisher) y un suscriptor (suscriber) sobre un topic JMS usando Spring 2.5 para configurar todo el sistema.

Como servidor JMS usaremos Apache ActiveMQ.

En una entrada anterior ya hemos comentado cómo instalar ActiveMQ, así pues, vamos directamente con el ejemplo.

Proyecto publicador (publisher)

Este jar implementa un sencillo publicador de mensajes que entrega sus mensajes a sus N suscriptores mediante una cola de tipo "topic" en un servidor JMS.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>es.ine.sgtic</groupId>
    <artifactId>inerel</artifactId>
    <version>1.0</version>
  </parent>
  <artifactId>inerel-jms-topic-productor</artifactId>
  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring</artifactId>
          <version>2.5</version>
      </dependency>
      <dependency>
          <groupId>org.apache.activemq</groupId>
          <artifactId>activemq-all</artifactId>
          <version>5.8.0</version>
      </dependency>
  </dependencies>
</project>



applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <!-- URL del servidor JMS                             -->
    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <bean id="activemq.connectionfactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://127.0.0.1:61616"/>
    </bean>

    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <!-- CONFIGURACION PRODUCTOR VOLCANDO SOBRE UNA TOPIC -->
    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Ajustamos el nombre de la TOPIC en ActiveMQ      -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <bean id="activemq.cola-topic" class="org.apache.activemq.command.ActiveMQTopic">
            <constructor-arg index="0" value="cola-topic"/>
        </bean>
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Ajustamos el JmsTemplate:                        -->
        <!--  pubSubDomain==true => Cola tipo TOPIC           -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <bean id="activemq.jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
            <property name="connectionFactory" ref="activemq.connectionfactory"/>
            <property name="pubSubDomain" value="true"/>
        </bean>
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Ajustamos el generador de peticiones             -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <bean id="productorPeticiones" class="es.ine.sgtic.jms.topic.productor.impl.ProductorPeticionesImpl">
            <property name="jmsTemplate" ref="activemq.jmsTemplate"/>
            <property name="destino" ref="activemq.cola-topic"/>
        </bean>
</beans>


AppTestProductorTopic

package es.ine.app;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;

import es.ine.sgtic.jms.topic.productor.IProductorPeticiones;

public class AppTestProductorTopic {

    public static void main(String args[]){
   
        //Instanciamos la factoría de beans
        final BeanFactory fabricaDeBeans = new XmlBeanFactory(new FileSystemResource("src/main/resources/applicationContext.xml"));
       
        //Obtenemos el bean productor de peticiones
        final IProductorPeticiones productor = (IProductorPeticiones) fabricaDeBeans.getBean("productorPeticiones");
       
        //Generamos la petición y ala enviamos
        productor.generarPeticion();
    }
}


IProductorPeticiones.java

package es.ine.sgtic.jms.topic.productor;

public interface IProductorPeticiones {
  
    public void generarPeticion();
}

ProductorPeticionesImpl .java

package es.ine.sgtic.jms.topic.productor.impl;

import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.Topic;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

import es.ine.sgtic.jms.topic.productor.IProductorPeticiones;

public class ProductorPeticionesImpl implements IProductorPeticiones {

    private static final String CAMPO_CONTENIDO = "campo-contenido";
    private static final String MENSAJE = "En un lugar de la mancha";
    private JmsTemplate jmsTemplate = null;
    private Topic destino = null;

    public void setJmsTemplate(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }

    public void setDestino(Topic destino) {
        this.destino = destino;
    }

    public void generarPeticion() {
        //Generamos y enviamos una petición
        jmsTemplate.send(this.destino,
                         new MessageCreator() {
                            public Message createMessage(Session session) throws JMSException {
                                MapMessage mensaje = session.createMapMessage();
                                mensaje.setString(CAMPO_CONTENIDO, MENSAJE);
                                return mensaje;
                            }
                        });
    }
}


Proyecto suscriptor (suscriber)

Este jar implementa un sencillo suscriptor que apunta a cierta cola JMS de tipo "topic", por lo que recibe un mensaje cada vez que un publicador deja algo en la cola.

Nosotros sólo implementamos el consumidor de los mensajes (id="consumidorPeticiones"), es Spring quien proporciona un listener (id="listenerPeticiones") sobre la cola "topic".

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>es.ine.sgtic</groupId>
    <artifactId>inerel</artifactId>
    <version>1.0</version>
  </parent>
  <artifactId>inerel-jms-topic-consumidor</artifactId>
  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring</artifactId>
          <version>2.5</version>
      </dependency>
      <dependency>
          <groupId>org.apache.activemq</groupId>
          <artifactId>activemq-all</artifactId>
          <version>5.8.0</version>
      </dependency>
  </dependencies>
</project>



applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jms="http://www.springframework.org/schema/jms"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd">

    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <!-- URL del servidor JMS                             -->
    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <bean id="activemq.connectionfactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://127.0.0.1:61616"/>
    </bean>

    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <!-- CONFIGURACION CONSUMIDOR LEYENDO DE UNA TOPIC    -->
    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Ajustamos el nombre de la TOPIC en ActiveMQ      -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <bean id="activemq.cola-topic" class="org.apache.activemq.command.ActiveMQTopic">
            <constructor-arg index="0" value="cola-topic"/>
        </bean>
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Consumidor de las peticiones                     -->      
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <bean id="consumidorPeticiones" class="es.ine.sgtic.jms.topic.consumidor.impl.ConsumidorAvisosTopicImpl"/>
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Listener de las peticiones                       -->      
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <jms:listener-container connection-factory="activemq.connectionfactory" destination-type="topic">
            <jms:listener id="listenerPeticiones" destination="cola-topic" ref="consumidorPeticiones"/>
        </jms:listener-container>
</beans> 


AppTestConsumidorTopic.java

package es.ine.sgtic.app;

import javax.jms.JMSException;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.jms.listener.DefaultMessageListenerContainer;

public class AppTestConsumidorTopic {

    public static void main(String[] args) throws JMSException {

        //Instanciamos la factoría de beans
        final BeanFactory factoriaBeans = new XmlBeanFactory(new FileSystemResource("src/main/resources/applicationContext.xml"));
       
        //Instanciamos el bean escuchador de peticiones, con esto queda activo y a la escucha
        final DefaultMessageListenerContainer listenerPeticiones = (DefaultMessageListenerContainer) factoriaBeans.getBean("listenerPeticiones");
       
        //TODO: Si necesitásemos instanciar otro consumidor podríamos invocar:
        //listenerPeticiones.initialize();
    }
}


ConsumidorAvisosTopicImpl.java

package es.ine.sgtic.jms.topic.consumidor.impl;

import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;

public class ConsumidorAvisosTopicImpl implements MessageListener {

    private static final String CAMPO_CONTENIDO = "campo-contenido";
  
    @Override
    public void onMessage(Message mensaje) {
        try {
            if (mensaje instanceof MapMessage) {
                final MapMessage mapMessage = (MapMessage) mensaje;
                System.out.println(mapMessage.getString(CAMPO_CONTENIDO));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

lunes, 22 de abril de 2013

Ejemplo JMS Queue con Spring 2.5 y ActiveMQ

Introducción

En el siguiente ejemplo montamos una demostración de cómo configurar un productor y un consumidor sobre una queue JMS usando Spring 2.5 para configurar todo el sistema.

Como servidor JMS usaremos Apache ActiveMQ.

Instalación ActiveMQ

1) Para descargar Apache ActiveMQ desde la página "http://activemq.apache.org/download.html". En la fecha de realización de este ejemplo la última versión disponible es la 5.8.0.

2) Se descomprime la distribución de ActiveMQ descargada, en el directorio que deseemos. En Ubunti se descomprime con:

     tar zxvf apache-activemq-X.X.X-bin.tar.gz

3) Arrancamos el servidor, para lo que necesitaremos lanzar el script "activemq" que tenemos en el subdirectorio bin. La forma de lanzarlo será:

     [dir-instalacion]/bin/activemq start

Nota. También podemos parar reiniciar o verificar el estado del servidor con el mismo script variando el parámetro. Están disponibles los parámetros: stop, restart o status.

4) Para verificar que tenemos correctamente iniciado el servidor, podemos acceder a la consola web del mismo en la URL: http://localhost:8161/ con el usuario/contraseña admin/admin.

5) Para acceder al área de administración del servidor deberemos hacer clic en el enlace "Manage ActiveMQ broker"

Proyecto productor

Este jar implementa un sencillo productor de mensajes que apunta a una cola a la que hemos llamado "cola-queue" en el servidor.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>es.ine.sgtic</groupId>
    <artifactId>inerel</artifactId>
    <version>1.0</version>
  </parent>
  <artifactId>inerel-jms-queue-productor</artifactId>
  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring</artifactId>
          <version>2.5</version>
      </dependency>
      <dependency>
          <groupId>org.apache.activemq</groupId>
          <artifactId>activemq-all</artifactId>
          <version>5.8.0</version>
      </dependency>
  </dependencies>
</project>



applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <!-- URL del servidor JMS                             -->
    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <bean id="activemq.connectionfactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://127.0.0.1:61616"/>
    </bean>

    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <!-- CONFIGURACION PRODUCTOR VOLCANDO SOBRE UNA QUEUE -->
    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Ajustamos el nombre de la QUEUE en ActiveMQ      -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <bean id="activemq.cola-queue" class="org.apache.activemq.command.ActiveMQQueue">
            <constructor-arg index="0" value="cola-queue"/>
        </bean>
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Ajustamos el JmsTemplate:                        -->
        <!--  pubSubDomain==false => Cola tipo QUEUE          -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <bean id="activemq.jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
            <property name="connectionFactory" ref="activemq.connectionfactory"/>
            <property name="pubSubDomain" value="false"/>
        </bean>
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Ajustamos el generador de peticiones             -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <bean id="productorPeticiones" class="es.ine.sgtic.jms.queue.productor.impl.ProductorPeticionesImpl">
            <property name="jmsTemplate" ref="activemq.jmsTemplate"/>
            <property name="destino" ref="activemq.cola-queue"/>
        </bean>
</beans>


AppTestProductorQueue

package es.ine.sgtic.app;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;

import es.ine.sgtic.jms.queue.productor.IProductorPeticiones;

public class AppTestProductorQueue {

    public static void main(String[] args) {
       
        //Instanciamos la factoría de beans
        final BeanFactory fabricaDeBeans = new XmlBeanFactory(new FileSystemResource("src/main/resources/applicationContext.xml"));
       
        //Obtenemos el bean productor de peticiones
        final IProductorPeticiones productor = (IProductorPeticiones) fabricaDeBeans.getBean("productorPeticiones");
       
        //Generamos la petición y ala enviamos
        productor.generarPeticion();
    } 
}


IProductorPeticiones.java

package es.ine.sgtic.jms.queue.productor;

public interface IProductorPeticiones {
   
    public void generarPeticion();
}


ProductorPeticionesImpl .java

package es.ine.sgtic.jms.queue.productor.impl;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Session;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

import es.ine.sgtic.jms.queue.productor.IProductorPeticiones;

public class ProductorPeticionesImpl implements IProductorPeticiones {

    private static final String CAMPO_CONTENIDO = "campo-contenido";
    private static final String MENSAJE = "En un lugar de la mancha"; 
    private JmsTemplate jmsTemplate = null;
    private Destination destino = null;

    public void setJmsTemplate(JmsTemplate jmsTemplate) { 
        this.jmsTemplate = jmsTemplate; 
    }

    public void setDestino(Destination destino) {
        this.destino = destino; 
    }

    public void generarPeticion() {
        //Generamos y enviamos una petición
        jmsTemplate.send(this.destino,
                         new MessageCreator() { 
                            public Message createMessage(Session session) throws JMSException { 
                                MapMessage mensaje = session.createMapMessage(); 
                                mensaje.setString(CAMPO_CONTENIDO, MENSAJE); 
                                return mensaje; 
                            }
                        });
    }
}


Proyecto consumidor

Este jar implementa un sencillo consumidor de mensajes que apunta a una cola a la que hemos llamado "cola-queue" en el servidor.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>es.ine.sgtic</groupId>
    <artifactId>inerel</artifactId>
    <version>1.0</version>
  </parent>
  <artifactId>inerel-jms-queue-consumidor</artifactId>
  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring</artifactId>
          <version>2.5</version>
      </dependency>
      <dependency>
          <groupId>org.apache.activemq</groupId>
          <artifactId>activemq-all</artifactId>
          <version>5.8.0</version>
      </dependency>
  </dependencies>
</project>



applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <!-- URL del servidor JMS                             -->
    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <bean id="activemq.connectionfactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://127.0.0.1:61616"/>
    </bean>

    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
    <!-- CONFIGURACION CONSUMIDOR LEYENDO DE UNA QUEUE    -->
    <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Ajustamos el nombre de la QUEUE en ActiveMQ      -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <bean id="activemq.cola-queue" class="org.apache.activemq.command.ActiveMQQueue">
            <constructor-arg index="0" value="cola-queue"/>
        </bean>
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Ajustamos el JmsTemplate:                        -->
        <!--  pubSubDomain==false => Cola tipo QUEUE          -->
        <!--  receiveTimeout==xxx => Timeout espera ms        -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <bean id="activemq.jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
            <property name="connectionFactory" ref="activemq.connectionfactory"/>
            <property name="defaultDestination" ref="activemq.cola-queue"/>
            <property name="pubSubDomain" value="false"/>
            <property name="receiveTimeout" value="1000"/>
        </bean>
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <!-- Ajustamos el consumidor de peticiones            -->
        <!-- ++++++++++++++++++++++++++++++++++++++++++++++++ -->
        <bean id="consumidorPeticiones" class="es.ine.sgtic.jms.queue.consumidor.impl.ConsumidorPeticionesImpl">
            <property name="jmsTemplate" ref="activemq.jmsTemplate"/>
        </bean>
</beans> 


AppTestConsumidorQueue.java

package es.ine.sgtic.app;

import javax.jms.JMSException;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;

import es.ine.sgtic.jms.queue.consumidor.IConsumidorPeticiones;

public class AppTestConsumidorQueue {

    public static void main(String[] args) throws JMSException { 

        //Instanciamos la factoría de beans
        final BeanFactory factoriaBeans = new XmlBeanFactory(new FileSystemResource("src/main/resources/applicationContext.xml"));
       
        //Obtenemos el bean consumidor de peticiones
        final IConsumidorPeticiones consumidor = (IConsumidorPeticiones) factoriaBeans.getBean("consumidorPeticiones");
       
        //Obtenemos y procesamos una petición
        final String peticion = consumidor.consumirPeticion();
        System.out.println(peticion);
    }
}


IConsumidorPeticiones.java

package es.ine.sgtic.jms.queue.consumidor;

import javax.jms.JMSException;

public interface IConsumidorPeticiones {
   
    public String consumirPeticion() throws JMSException;
}


ConsumidorPeticionesImpl.java

package es.ine.sgtic.jms.queue.consumidor.impl;

import javax.jms.JMSException;
import javax.jms.MapMessage;

import org.springframework.jms.core.JmsTemplate;

import es.ine.sgtic.jms.queue.consumidor.IConsumidorPeticiones;

public class ConsumidorPeticionesImpl implements IConsumidorPeticiones {
   
    private static final String CAMPO_CONTENIDO = "campo-contenido";
   
    private JmsTemplate jmsTemplate = null;
   
    public void setJmsTemplate(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }
   
    public String consumirPeticion() throws JMSException {
       
        //Descargamos y procesamos una petición
        final MapMessage mensaje = (MapMessage) jmsTemplate.receive();
        return mensaje.getString(CAMPO_CONTENIDO);
    } 
}

Introducción a JMS

Introducción

JMS (Java Message Service) es la solución tecnológica ofertada por Java para sistemas de comunicación asíncronos.

Arquitectura de JMS

En la arquitectura JMS participan las siguientes entidades:
  • Clientes JMS. Son las aplicaciones que envian y/o reciben mensajes a través de JMS.
  • Mensajes. Son los datos intercambiados.
  • Destinos JMS. Son los almacenes intermedios donde se almacenan los mensajes.
Destinos JMS

Los servicios de mensajería ofrecen dos tipos de destinos:
  • Colas (tipo queue). Una aplicación (productor) genera un mensaje, lo deposita en la cola y cuando la segunda aplicación (consumidor) se conecta al servicio de mensajería, recoge el mensaje. Habitualmente en una cola sólo participan un productor y un consumidor, pero podrían existir varios productores y varios consumidores colaborando (sistemas de alto rendimiento). En este caso lo fundamental es que cada mensaje se procesa una única vez, no importa qué consumidor lo procese. Los mensajes salen de la cola en orden de llegada, el primero que se recibió es el primero que se recoge (FIFO).

  • Publicador/Suscriptores (tipo topic). Una aplicación (publicador) genera un mensaje, lo publica en el servicio JMS y lo reciben todas las aplicaciones (suscriptores) que esten suscritas al servicio JMS en que se publicó el mensaje. Habitualmente en una cola participa un publicador y muchos suscriptores, pero podrían existir varios publicadores.

Persistencia

Dado que los servicios JMS son asíncronos, los mensajes son almacenados en las colas (tipo queue ó tipo topic) hasta ser recibidos por sus destinatarios. Se debe garantizar que ningún mensaje se pierda incluso cuando el servidor JMS se apague súbitamente. Por ello, los servidores JMS suelen ofrecer la posibilidad de persistir los mensajes en algún medio no volatil como una base de datos.

Seguridad

Como en cualquier mecanismo de comunicación, la seguridad es un aspecto fundamental que siempre debe tenerse en cuenta. Son posibles dos acciones:

Autenticación. Los servidores JMS ofrecen mecanismos para autenticar tanto a los depositantes como a receptores de los mensajes, dado que de otro modo podrían entrar en las colas de mensajes de procedencia desconocida. Lo habitual son comunicaciones SSL. Siempre es posible que las aplicaciones que se comunican a través e JMS implementen sus propios sistemas de autenticación, lo que las hace más interdependientes, pero puede ser necesario si el servidor JMS no es confiable.

Cifrado. Los sistemas de persistencia antes mencionados almacenan los mensajes en una BBDD, lo que los expone a consultas indeseables por parte de terceros. Por ello es siempre conveniente que las aplicaciones cifren los datos intercambiados. El mecanismo de cifrado también se puede dejar en manos del servidor JMS o de la BBDD que persista los mensajes, si ámbos sistemas son confiables.

Disponibilidad

Cualquier sistema de comunicaciones síncrono que pase a ser asíncrono, pasará de dos a tres entidades participando en el intercambio de datos. Si se desea garantizar la tolerancia a fallos 24x7 deberá garantizarse la tolerancia a fallos tanto en las aplicaciones que intercambian los datos como en el servidor JMS.

jueves, 4 de abril de 2013

Openssl. Generar certificado autofirmado para firmar applets

Si necesitamos un certificado autofirmado para firmar applets y poder depurarlos en el navegador podemos usar OpenSSL, que es un conjunto de utilidades de criptografía.

Para instalarlas en Ubuntu deberemos ejecutar:

$ sudo apt-get install openssl

Una vez instalada, podemos verificar si todo está correcto tecleando:

$ openssl version

Lo que nos debería generar una salida del tipo "OpenSSL 1.0.1 14 Mar 2012", que obviamente dependerá de la versión instalada.

Para generar un certificado autofirmado que nos sirva para firmar applets, necesitaremos añadir la extension digitalSignature, por lo que deberemos ejecutar:

$ openssl req -new -x509 -days 3650 -extensions v3_req -keyout key.pem -out cert.pem

Esto desencadena el procedimiento de generación del certificado, el proceso nos solicitará:

- Password (dos veces)
- Código de dos letras del país [ES]
- Provincia [Madrid]
- Ciudad [Madrid]
- Organización [Dune]
- Unidad [Java]
- Nombre [egdp1970]
- eMail [egdp1970@gmail.com]

$ openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12

Esto desencadena el procedimiento de volcado del certificado en un keystore tipo PKCS12, el proceso nos solicitará:

- Password del certificado (la misma que tecleamos antes dos veces)
- Password del keystore pkcs12 que se va a crear (dos veces)

Nota. v3_req es uno de los niveles de requisitos definicos en el fichero /etc/ssl/openssl.cnf para que el certificado autofirmado sirva para firmar applets deberemos asegurarnos de que contiene:

    [ v3_req ]
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment