Diferencia entre revisiones de «JMS con Spring Roo»

De Dos Ideas.
Saltar a: navegación, buscar
Línea 1: Línea 1:
 
Con el uso de [[JMS]] podemos hacer asincrónica la ocurrencia de un determinado evento.
 
Con el uso de [[JMS]] podemos hacer asincrónica la ocurrencia de un determinado evento.
  
Entonces, tomamos el [[Ejemplo de proyecto web ABM con Spring Roo]] y hacemos que una vez creado un nuevo pedido de pizza, se envíe un mensaje a la consola del servidor. Esto último de manera asincrónica.
 
  
== Alternativa 1: Modificar el aspecto de la entidad "Pedido"==
+
== Comandos Roo para JMS ==
 +
 
 +
Para crear una cola en memoria:
 +
<code>
 +
jms setup --provider ACTIVEMQ_IN_MEMORY --destinationType QUEUE --destinationName unNombreJndi
 +
</code>
  
* Comentamos la anotacion en el aspecto de la entidad: 
 
  
 +
Para crear un jmsTemplate que encole mensajes en la queue creada anteriormente:
 
<code>
 
<code>
privileged aspect PedidoController_Roo_Controller {
+
field jms template --class com.dosideas.roo.unpackage.UnaClase --fieldName jmsTemplate
   
 
//@RequestMapping(value = "/pedido", method = RequestMethod.POST)
 
    public String PedidoController.create
 
 
</code>
 
</code>
  
* Agregamos un método "crear" en el Controller para crear el pedido y donde vamos a inyectar el uso de mensajeria para mandar el aviso:
 
  
 +
Para crear un listener que consuma los mensajes de la queue:
 
<code>
 
<code>
public class PedidoController {
+
jms listener class --class com.dosideas.roo.unpackage.UnaClaseListener --destinationName unNombreJndi --destinationType QUEUE
    @RequestMapping(value = "/pedido", method = RequestMethod.POST)
 
    public String crear(@Valid Pedido pedido, BindingResult result, ModelMap modelMap) {
 
    System.out.println("Estoy en PedidoController - crear");
 
        String resultado = create(pedido, result, modelMap);
 
        return resultado;
 
    }
 
}
 
 
</code>
 
</code>
 +
 +
== Integrando el envío de mensajes JMS a una aplicación Roo ==
 +
 +
Tomamos el [[Ejemplo de proyecto web ABM con Spring Roo]] y hacemos que una vez creado un nuevo pedido de pizza, se envíe un mensaje a la consola del servidor. Esto último de manera asincrónica.
 +
 +
 +
=== Alternativa 1: Agregar la lógica de envío de mensajes en el controller ===
  
 
* Ejecutamos el comando JMS de Spring Roo para crear una cola en memoria:
 
* Ejecutamos el comando JMS de Spring Roo para crear una cola en memoria:
 
 
<code>
 
<code>
 
jms setup --provider ACTIVEMQ_IN_MEMORY --destinationType QUEUE --destinationName dosIdeasQueue
 
jms setup --provider ACTIVEMQ_IN_MEMORY --destinationType QUEUE --destinationName dosIdeasQueue
Línea 41: Línea 41:
 
</code>
 
</code>
  
* Modificamos la configuración de la versión de MQ. En el archivo applicationContext-jms.xml configuramos http://activemq.apache.org/schema/core/activemq-core.xsd. Para que no muestre el error desde el IDE ver [[http://www.bigsoft.co.uk/blog/index.php/2009/02/01/invalid-activemq-schema-name-space como modificar las preferencias de Eclipse]]
+
* Modificamos la configuración de namespaces de MQ. En el archivo applicationContext-jms.xml sacamos la versión del xsd de activemq, quedando http://activemq.apache.org/schema/core/activemq-core.xsd. Para que no muestre el error desde el IDE ver [[http://www.bigsoft.co.uk/blog/index.php/2009/02/01/invalid-activemq-schema-name-space como modificar las preferencias de Eclipse]]
 
 
* Ejecutamos el comando de Spring Roo para crear el template:
 
  
 +
* Comentamos la anotacion en el aspecto de la entidad: 
 
<code>
 
<code>
field jms template --class com.dosideas.roo.oracle.web.PedidoController --fieldName jmsTemplate
+
privileged aspect PedidoController_Roo_Controller {
Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController.java
+
   
Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController.java
+
  //@RequestMapping(value = "/pedido", method = RequestMethod.POST)
Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController_Roo_Controller.aj
+
    public String PedidoController.create
 
</code>
 
</code>
  
Cada vez que se ejecuta un comando, Spring Roo re-escribe la anotación en el aspecto:
+
Cada vez que se ejecuta un comando, Spring Roo re-escribe esta anotación en el aspecto, por lo que deberá ser comentada nuevamente. De lo contrario queda anotado en el aspecto y en el controller de la entidad el mismo path y al crear un pedido en runtime, da error.
  
<code>
+
* Agregamos un método "crear" en el Controller para crear el pedido y donde vamos a inyectar el uso de mensajeria para mandar el aviso:
@RequestMapping(value = "/pedido", method = RequestMethod.POST)
 
</code>
 
 
 
Entonces, queda anotado en el aspecto y el controller de la entidad y al crear un pedido en runtime, da error.
 
 
 
* Ejecutamos el comando de Spring Roo para crear el listener:
 
  
 
<code>
 
<code>
jms listener class --class com.dosideas.roo.oracle.jms.JmsQueueListener --destinationName dosIdeasQueue --destinationType QUEUE
+
public class PedidoController {
Created SRC_MAIN_JAVA\com\dosideas\roo\oracle\jms
+
    @RequestMapping(value = "/pedido", method = RequestMethod.POST)
Created SRC_MAIN_JAVA\com\dosideas\roo\oracle\jms\JmsQueueListener.java
+
    public String crear(@Valid Pedido pedido, BindingResult result, ModelMap modelMap) {
Managed SRC_MAIN_RESOURCES\META-INF\spring\applicationContext-jms.xml
+
    System.out.println("Estoy en PedidoController - crear");
 +
        String resultado = create(pedido, result, modelMap);
 +
        return resultado;
 +
    }
 +
}
 
</code>
 
</code>
  
* En el onMessage, escribimos el mensaje que queremos enviar:
+
* Ejecutamos el comando de Spring Roo para crear el template en PedidoController:
  
 
<code>
 
<code>
public class JmsQueueListener {
+
field jms template --class com.dosideas.roo.oracle.web.PedidoController --fieldName jmsTemplate
 
+
Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController.java
    public void onMessage(Object message) {
+
Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController.java
        System.out.println("Pedido recibido por JMS: " + message);
+
Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController_Roo_Controller.aj
    }
 
}
 
 
</code>
 
</code>
  
Línea 98: Línea 93:
 
</code>
 
</code>
  
* Ejecutamos la aplicación, creamos un pedido y vemos el siguiente mensaje en consola:
+
* Ejecutamos el comando de Spring Roo para crear una clase listener que consuma los mensajes:
  
 
<code>
 
<code>
Pedido Enviado:Id: 1, Version: 0, Nombre: aa, Direccion: aa, Importe: 11.0, FechaEntrega: Tue Jul 27 00:00:00 VET 2010, Pizzas: 0
+
jms listener class --class com.dosideas.roo.oracle.jms.JmsQueueListener --destinationName dosIdeasQueue --destinationType QUEUE
 +
Created SRC_MAIN_JAVA\com\dosideas\roo\oracle\jms
 +
Created SRC_MAIN_JAVA\com\dosideas\roo\oracle\jms\JmsQueueListener.java
 +
Managed SRC_MAIN_RESOURCES\META-INF\spring\applicationContext-jms.xml
 
</code>
 
</code>
  
== Alternativa 2: Utilizar una anotacion ==
+
* En el onMessage, escribimos el mensaje recibido:
  
* Ejecutamos el comando JMS de Spring Roo para crear una cola en memoria:
+
<code>
 +
public class JmsQueueListener {
  
<code>
+
    public void onMessage(Object message) {
jms setup --provider ACTIVEMQ_IN_MEMORY --destinationType QUEUE --destinationName dosIdeasQueue
+
        System.out.println("Pedido recibido por JMS: " + message);
Created SRC_MAIN_RESOURCES\META-INF\spring\applicationContext-jms.xml
+
    }
Managed SRC_MAIN_RESOURCES\META-INF\spring\applicationContext-jms.xml
+
}
Managed ROOT\pom.xml
 
Managed ROOT\pom.xml
 
Managed ROOT\pom.xml
 
Managed ROOT\pom.xml
 
Managed ROOT\pom.xml
 
Managed ROOT\pom.xml
 
 
</code>
 
</code>
  
* Modificamos la configuración de la versión de MQ. En el archivo applicationContext-jms.xml configuramos http://activemq.apache.org/schema/core/activemq-core.xsd. Para que no muestre el error desde el IDE ver [[http://www.bigsoft.co.uk/blog/index.php/2009/02/01/invalid-activemq-schema-name-space como modificar las preferencias de Eclipse]]
 
  
* Ejecutamos el comando de Spring Roo para crear el template:
+
* Ejecutamos la aplicación, creamos un pedido y vemos el siguiente mensaje en consola:
  
 
<code>
 
<code>
field jms template --class com.dosideas.roo.oracle.web.PedidoController --fieldName jmsTemplate
+
Pedido Enviado:Id: 1, Version: 0, Nombre: aa, Direccion: aa, Importe: 11.0, FechaEntrega: Tue Jul 27 00:00:00 VET 2010, Pizzas: 0
Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController.java
 
Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController.java
 
Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController_Roo_Controller.aj
 
 
</code>
 
</code>
  
* Ejecutamos el comando de Spring Roo para crear el listener:
+
=== Alternativa 2: Utilizar una anotacion ===
 +
 
 +
* Los primeros 2 puntos son iguales a la alternativa 1.
 +
 
  
<code>
 
jms listener class --class com.dosideas.roo.oracle.jms.JmsQueueListener --destinationName dosIdeasQueue --destinationType QUEUE
 
Created SRC_MAIN_JAVA\com\dosideas\roo\oracle\jms
 
Created SRC_MAIN_JAVA\com\dosideas\roo\oracle\jms\JmsQueueListener.java
 
Managed SRC_MAIN_RESOURCES\META-INF\spring\applicationContext-jms.xml
 
</code>
 
  
* En el onMessage, escribimos el mensaje que queremos enviar:
 
  
 +
* Agregamos una capa de negocio para la funcionalidad que agregamos: Creamos una clase JmsQueueSenderBoImpl anotada con @Service y le creamos un atributo template de envío de mensajes con el comando de roo ya mencionado:
 
<code>
 
<code>
public class JmsQueueListener {
+
field jms template --class com.dosideas.roo.oracle.business.JmsQueueSenderBoImpl  --fieldName jmsTemplate
 
 
    public void onMessage(Object message) {
 
        System.out.println("Pedido recibido por JMS: " + message);
 
    }
 
}
 
 
</code>
 
</code>
  
* Agregamos una capa de negocio para la funcionalidad que agregamos:
+
La clase queda entonces así:
  
 
<code>
 
<code>
Línea 171: Línea 152:
 
</code>
 
</code>
  
* En la entidad Pedido.java, agregamos el uso de un servicio anotado en la clase de negocio:
+
* En la entidad Pedido.java, agregamos el uso de un servicio anotado en la clase de negocio: Usamos la anotación Jpa @PostPersist para indicar que primero debe persistir la entidad y luego realizar el envío del mensaje.
  
 
<code>   
 
<code>   
Línea 181: Línea 162:
 
         senderBoImpl.sendMessage("Pedido Enviado:" + this);     
 
         senderBoImpl.sendMessage("Pedido Enviado:" + this);     
 
     }
 
     }
 +
</code>
 +
 +
* Ejecutamos el comando de Spring Roo para crear una clase listener:
 +
 +
<code>
 +
jms listener class --class com.dosideas.roo.oracle.jms.JmsQueueListener --destinationName dosIdeasQueue --destinationType QUEUE
 +
</code>
 +
 +
* En el onMessage, escribimos el mensaje que recibimos:
 +
<code>
 +
public class JmsQueueListener {
 +
 +
    public void onMessage(Object message) {
 +
        System.out.println("Pedido recibido por JMS: " + message);
 +
    }
 +
}
 
</code>
 
</code>
  

Revisión del 21:09 28 jul 2010

Con el uso de JMS podemos hacer asincrónica la ocurrencia de un determinado evento.


Comandos Roo para JMS

Para crear una cola en memoria: jms setup --provider ACTIVEMQ_IN_MEMORY --destinationType QUEUE --destinationName unNombreJndi


Para crear un jmsTemplate que encole mensajes en la queue creada anteriormente: field jms template --class com.dosideas.roo.unpackage.UnaClase --fieldName jmsTemplate


Para crear un listener que consuma los mensajes de la queue: jms listener class --class com.dosideas.roo.unpackage.UnaClaseListener --destinationName unNombreJndi --destinationType QUEUE

Integrando el envío de mensajes JMS a una aplicación Roo

Tomamos el Ejemplo de proyecto web ABM con Spring Roo y hacemos que una vez creado un nuevo pedido de pizza, se envíe un mensaje a la consola del servidor. Esto último de manera asincrónica.


Alternativa 1: Agregar la lógica de envío de mensajes en el controller

  • Ejecutamos el comando JMS de Spring Roo para crear una cola en memoria:

jms setup --provider ACTIVEMQ_IN_MEMORY --destinationType QUEUE --destinationName dosIdeasQueue Created SRC_MAIN_RESOURCES\META-INF\spring\applicationContext-jms.xml Managed SRC_MAIN_RESOURCES\META-INF\spring\applicationContext-jms.xml Managed ROOT\pom.xml Managed ROOT\pom.xml Managed ROOT\pom.xml Managed ROOT\pom.xml Managed ROOT\pom.xml Managed ROOT\pom.xml

  • Comentamos la anotacion en el aspecto de la entidad:

privileged aspect PedidoController_Roo_Controller {

  //@RequestMapping(value = "/pedido", method = RequestMethod.POST)
   public String PedidoController.create

Cada vez que se ejecuta un comando, Spring Roo re-escribe esta anotación en el aspecto, por lo que deberá ser comentada nuevamente. De lo contrario queda anotado en el aspecto y en el controller de la entidad el mismo path y al crear un pedido en runtime, da error.

  • Agregamos un método "crear" en el Controller para crear el pedido y donde vamos a inyectar el uso de mensajeria para mandar el aviso:

public class PedidoController {

   @RequestMapping(value = "/pedido", method = RequestMethod.POST)
   public String crear(@Valid Pedido pedido, BindingResult result, ModelMap modelMap) {
   	System.out.println("Estoy en PedidoController - crear");
       String resultado = create(pedido, result, modelMap);
       return resultado;
   }	

}

  • Ejecutamos el comando de Spring Roo para crear el template en PedidoController:

field jms template --class com.dosideas.roo.oracle.web.PedidoController --fieldName jmsTemplate Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController.java Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController.java Managed SRC_MAIN_JAVA\com\dosideas\roo\oracle\web\PedidoController_Roo_Controller.aj

  • En el controller, agregamos el uso de la mensajería -sendMessage-:

public class PedidoController {

   @RequestMapping(value = "/pedido", method = RequestMethod.POST)
   public String crear(@Valid Pedido pedido, BindingResult result, ModelMap modelMap) {
   	System.out.println("Estoy en PedidoController - crear");
       String resultado = create(pedido, result, modelMap);
       sendMessage("Pedido Enviado:" + pedido); 
       return resultado;
   }
   public void sendMessage(Object messageObject) {
       jmsTemplate.convertAndSend(messageObject);
   }

}

  • Ejecutamos el comando de Spring Roo para crear una clase listener que consuma los mensajes:

jms listener class --class com.dosideas.roo.oracle.jms.JmsQueueListener --destinationName dosIdeasQueue --destinationType QUEUE Created SRC_MAIN_JAVA\com\dosideas\roo\oracle\jms Created SRC_MAIN_JAVA\com\dosideas\roo\oracle\jms\JmsQueueListener.java Managed SRC_MAIN_RESOURCES\META-INF\spring\applicationContext-jms.xml

  • En el onMessage, escribimos el mensaje recibido:

public class JmsQueueListener {

   public void onMessage(Object message) {
       System.out.println("Pedido recibido por JMS: " + message);
   }

}


  • Ejecutamos la aplicación, creamos un pedido y vemos el siguiente mensaje en consola:

Pedido Enviado:Id: 1, Version: 0, Nombre: aa, Direccion: aa, Importe: 11.0, FechaEntrega: Tue Jul 27 00:00:00 VET 2010, Pizzas: 0

Alternativa 2: Utilizar una anotacion

  • Los primeros 2 puntos son iguales a la alternativa 1.



  • Agregamos una capa de negocio para la funcionalidad que agregamos: Creamos una clase JmsQueueSenderBoImpl anotada con @Service y le creamos un atributo template de envío de mensajes con el comando de roo ya mencionado:

field jms template --class com.dosideas.roo.oracle.business.JmsQueueSenderBoImpl --fieldName jmsTemplate

La clase queda entonces así:

package com.dosideas.roo.oracle.business;

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.core.JmsTemplate; import org.springframework.stereotype.Service;

@Service public class JmsQueueSenderBoImpl {

   @Autowired
   private transient JmsTemplate jmsTemplate;
   public void sendMessage(Object messageObject) {
       jmsTemplate.convertAndSend(messageObject);
   }

}

  • En la entidad Pedido.java, agregamos el uso de un servicio anotado en la clase de negocio: Usamos la anotación Jpa @PostPersist para indicar que primero debe persistir la entidad y luego realizar el envío del mensaje.

   @Autowired
   private transient JmsQueueSenderBoImpl senderBoImpl;
   
   @PostPersist
   public void crear() {
       senderBoImpl.sendMessage("Pedido Enviado:" + this);     
   }

  • Ejecutamos el comando de Spring Roo para crear una clase listener:

jms listener class --class com.dosideas.roo.oracle.jms.JmsQueueListener --destinationName dosIdeasQueue --destinationType QUEUE

  • En el onMessage, escribimos el mensaje que recibimos:

public class JmsQueueListener {

   public void onMessage(Object message) {
       System.out.println("Pedido recibido por JMS: " + message);
   }

}

  • Ejecutamos la aplicación, creamos un pedido y vemos el siguiente mensaje en consola:

Pedido Enviado:Id: 1, Version: 0, Nombre: aa, Direccion: aa, Importe: 11.0, FechaEntrega: Tue Jul 27 00:00:00 VET 2010, Pizzas: 0

Ver tambien