Banear

lunes, 30 de diciembre de 2013

sábado, 21 de diciembre de 2013

Analizar dureza de tracks: IBP Index

Podéis analizar vuestros tracks (tcx, por ejemplo) y ver qué puntuación de dureza tienen. Por ejemplo, de mayor a menor dureza, me salen estos:

ANDAR

  1. san andrés: 277
  2. cedeira:  165
  3. vuelta ría larga: 69
  4. vuelta ría: 52

CORRER

  1. ruta naval: 64
  2. carrefour: 55
  3. nocturna: 45
  4. contra cáncer: 35

BICI

  1. ferrol-bruma: 227
  2. caaveiro: 173
  3. miñoidayvuelta: 166
  4. marraxón: 151
  5. brión: 138
  6. molinos: 110
  7. ares: 109
  8. ártabra: 106
  9. pontedeume: 105
  10. montefaro:  102
  11. marraxonlight: 97
  12. bruma-santiago: 96
  13. valdoviño: 96
  14. lagoavela: 87
  15. pedroso: 85

En general es bastante indicativo, pero naturalmente no tiene en cuenta si vas por una pista de asfalto, tierra, piedras, barro... Aquí está la herramienta: http://www.ibpindex.com/index.asp

sábado, 14 de diciembre de 2013

domingo, 8 de diciembre de 2013

Camino Inglés a Santiago desde Ferrol en Bici (en invierno) - BTT

Qué llevar

  • Cepillo de dientes
  • Cartera con documentación y dinero
  • Móvil
  • Cargador del móvil (en el albergue de Bruma tenéis enchufes)
  • Saco de dormir
  • Chándal
  • Impermeable
  • Calcetines
  • Gallumbos o equivalente
  • Camiseta
  • Tenis
  • Toalla
  • Camiseta/Maillot repuesto bici
  • Peine
  • Clínex / Pañuelos
  • Herramientas de la bici (desmontables, cámara, bombín, típicamente)
  • Linterna
  • Luces bici recargables (por si se os hace de noche)
  • Llaves de vuestra casa/garaje
  • Candado bici (y aseguraros antes de cerrarlo que tenéis la llave :D)
  • Bidón
  • Cuerda / Pulpos
  • Pequeño botecito con champú / jabón
  • Chanclas
  • Algunas barritas para evitar pájaras (azúcar!)

Trucos

  • En general, usar el sentido común. Es decir, si llegáis a la plaza de Betanzos y no véis marcas del Camino a Santiago de Compostela, preguntar a un taxista por ejemplo, que estará "cansado" de ver peregrinos :). Es todo recto ;)
  • Ojo con las marcas, a veces son un poco confusas y no se sabe bien si dicen hacia la derecha o de frente. Si estáis en medio del monte al lado de un río y la alternativa es ir por un camino menos cerrado de maleza aunque sea una cuesta de la leche, va a ser por ahí.
  • Cuánto menos peso mejor, hay gente que prefiere llevarlo en las alforjas, otros como yo si son pocos días y no sufrís demasiados problemas de espalda, pues mochila con saco atado con una cuerda a la espalda (bien fijado para que se mueva poco para los lados). El máximo deberían ser unos 5-10 kilos, un 10% de vuestro peso.

Observaciones

  • Al llegar a Miño, no sigáis las indicaciones para ir al albergue, que os desvían del camino y no bajéis muy deprisa porque cerca de un parque hay que girar hacia la izquierda (hay un mojón que pasa bastante desapercibido)
  • Al salir de Betanzos, por la plaza todo recto hasta que salgáis de la ciudad dónde ya está marcado.
  • Antes del Mesón do Vento, cuando tenéis un río por la izquierda, hay flechas confusas que no se sabe muy bien si indican seguir de frente -camino bastante cerrado con un tronco tirado- o subir un cuestón a la derecha. Hay que subir el cuestón.

Primera etapa (Ferrol - Bruma) - 62,76 km

Si vais por las pías, salen unos 63 km, si decidís ir por Neda, son unos 75 km. Es una etapa durilla, principalmente porque vais a llevar unos 10 kilos de carga. Si no salís de Betanzos antes de las 15.30, plantearos seriamente si no es mejor quedaros en el albergue de Betanzos, especialmente en invierno que anochece pronto.

Recomendado comer ya en Betanzos aunque sea un poco pronto, porque luego escasean mucho los bares, además es preferible subir el "Mesón do Vento" con la digestión hecha.

Cuando lleguéis al albergue de Bruma (unas 22 literas), hay un número escrito a la izquierda de la puerta, al que llamáis y os atenderá un matrimonio muy amable que vive allí al lado. Para cenar, por 10 € os traen la comida al albergue (primero, segundo, postre, pan, bebida y cubiertos). Sino, a 2-3 km tenéis el pueblo.

Perfil primera etapa (Ferrol - Bruma)


Tracks de la primera etapa

Segunda etapa (Bruma - Santiago de Compostela) - 42 km

Etapa facilita aunque rompepiernas a partir de Sigüeiro. Se recomienda comer un poco antes de llegar a Santiago, en las proximidades del polígono, para evitar que os claven cerca de la catedral. Sino, por la plaza roja no es mala opción.

Perfil segunda etapa (Bruma - Santiago)


Tracks de la segunda etapa



sábado, 9 de noviembre de 2013

I CARRERA CARREFOUR - FERROL - 10KM

Carrera para promocionar la apertura del nuevo Carrefour en Ferrol. Son 10km y el recorrido oficial final es este:

Para inscribirse (acaba en unos 4 días el plazo desde la publicación de esta entrada): http://www.championchipnorte.com/evento/detalle/id/64/CARRERA-POPULAR-Carrefour---Ferrol 

miércoles, 11 de septiembre de 2013

Big Data - Configurar HBase

Definición de HBase

  • NoSQL (Not Only SQL)
  • Es la implementación de código abierto de BigTable de Google
  • Podemos definir HBase como un HashMap (pares clave-valor) persistente, distribuido, multidimensional (es decir, podemos tener valores que a su vez sean HashMaps -mapa de mapas-) y ordenado (a nivel de claves)
  • Comparándolo con Java, podríamos decir que sería algo bastante parecido a esto:
    HashMap<String, HashMap<String, Valor>>, pero adicionalmente las claves estarían ordenadas para tener datos posiblemente relacionados "cerca".

Palabras clave

Para referirnos a los distintos niveles de anidación, usaremos un ejemplo relacionado con la temática del blog:


"carrera memorial lolete" :
{
"papidal" :
{
"tiempo" : "42:00:00",
"distancia" : "8000",
}
;

Clave: carrera memorial lolete (1º nivel)
Familia de columna: papidal (2º nivel)
Columnas de “papidal”: tiempo y distancia (3º nivel)
Clasificación (qualifier): tiempo, distancia

Si queremos consultar el tiempo de papidal, sería algo de este estilo: “papidal:tiempo”

Instalando y configurando HBase en Ubuntu


  • cd /home/hduser
  • sudo tar -zxf /home/hduser/hbase-0.94.11-security.tar.gz
  • sudo chown -R hduser:hadoop hbase-0.94.11-security/
  • sudo ln -s hbase-0.94.11-security hbase
  • sudo chown -R hduser:hadoop hbase
  • Editar conf/hbase-env.sh, para usar la versión de Java deseada, en mi caso, le pongo la misma que había utilizado con hadoop (export JAVA_HOME=/usr/lib/jvm/java-6-sun/)
  • start-hbase.sh
  • Consultar el log hbase-hduser-master-ubuntu.out, si os encontráis un error del estilo "org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed setting up proxy interface org.apache.hadoop.hbase.ipc.HRegionInterface to localhost/127.0.0.1"
  • Vais a etc/hosts y editais el fichero. Típicamente será sustituir el 127.0.1.1 por 127.0.0.1, tanto localhost (que generalmente ya estará correcto) como la ip asociada al nombre de la máquina que uséis (que generalmente tendréis que cambiar por 127.0.0.1)
  • Volvéis a lanzar "start-hbase.sh" para levantar el servicio y hbase shell (si queréis) para hacer pruebecillas con los comandos list, scan, ...
  • También se recomienda editar la configuración del directorio raíz en hbase-site.xml:
<configuration> <property> <name>hbase.rootdir</name> <value>file:///home/hduser/hbase</value> </property> </configuration>

Integrando HBase y Java

Necesitaremos añadir a nuestro proyecto el jar hbase-0.94.11-security.jar que está en el directorio de hbase. 
Además, también nos harán falta unos pocos jars más que encontraremos en la carpeta lib, como el de zookeeper, slf4j, protobuf y alguno más (por el error que nos vaya indicando lo vamos añadiendo al classpath).
Una vez hecho esto, podéis partir de esta clase como base para hacer vuestras pruebas:
package papidal.hbase;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.util.Bytes;
 
public class HBaseTest {
 
    private static Configuration conf = null;
        static {
        conf = HBaseConfiguration.create();
    }
 
    public static void createTable(String tableName, String[] familys)
            throws Exception {
        HBaseAdmin admin = new HBaseAdmin(conf);
        if (admin.tableExists(tableName)) {
            System.out.println("La tabla todavía existe!");
        } else {
            HTableDescriptor tableDesc = new HTableDescriptor(tableName);
            for (int i = 0; i < familys.length; i++) {
                tableDesc.addFamily(new HColumnDescriptor(familys[i]));
            }
            admin.createTable(tableDesc);
            System.out.println("Creada tabla " + tableName);
        }
    }
 
    public static void deleteTable(String tableName) throws Exception {
        try {
            HBaseAdmin admin = new HBaseAdmin(conf);
            admin.disableTable(tableName);
            admin.deleteTable(tableName);
            System.out.println("Eliminada tabla " + tableName);
        } catch (MasterNotRunningException e) {
            e.printStackTrace();
        } catch (ZooKeeperConnectionException e) {
            e.printStackTrace();
        }
    }
 
    public static void addRecord(String tableName, String rowKey,
            String family, String qualifier, String value) throws Exception {
        try {
            HTable table = new HTable(conf, tableName);
            Put put = new Put(Bytes.toBytes(rowKey));
            put.add(Bytes.toBytes(family), Bytes.toBytes(qualifier), Bytes
                    .toBytes(value));
            table.put(put);
            System.out.println("Insertado registro " + rowKey + " en la tabla "
                    + tableName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
   
    public static void deleteRecord(String tableName, String rowKey)
            throws IOException {
        HTable table = new HTable(conf, tableName);
        List<Delete> list = new ArrayList<Delete>();
        Delete del = new Delete(rowKey.getBytes());
        list.add(del);
        table.delete(list);
        System.out.println("Eliminado registro " + rowKey + " de la tabla "+tableName);
    }
 
    
    public static void getOneRecord (String tableName, String rowKey) throws IOException{
        HTable table = new HTable(conf, tableName);
        Get get = new Get(rowKey.getBytes());
        Result rs = table.get(get);
        for(KeyValue kv : rs.raw()){
            System.out.print(new String(kv.getRow()) + " " );
            System.out.print(new String(kv.getFamily()) + ":" );
            System.out.print(new String(kv.getQualifier()) + " " );
            //System.out.print(kv.getTimestamp() + " " );
            System.out.println(new String(kv.getValue()));
        }
    }
    
    public static void getAllRecord (String tableName) {
        try{
             HTable table = new HTable(conf, tableName);
             Scan s = new Scan();
             ResultScanner ss = table.getScanner(s);
             for(Result r:ss){
                 for(KeyValue kv : r.raw()){
                    System.out.print(new String(kv.getRow()) + " ");
                    System.out.print(new String(kv.getFamily()) + ":");
                    System.out.print(new String(kv.getQualifier()) + " ");
                    //System.out.print(kv.getTimestamp() + " ");
                    System.out.println(new String(kv.getValue()));
                 }
             }
        } catch (IOException e){
            e.printStackTrace();
        }
    }
 
    public static void main(String[] agrs) {
        try {
            String tablename = "corredor";
            String[] familys = { "carrera", "localidad"};
            HBaseTest.createTable(tablename, familys);
 
            // registro identificado por segundo parámetro
            HBaseTest.addRecord(tablename, "papidal", "carrera", "memorial lolete", "43:00:00");
            HBaseTest.addRecord(tablename, "papidal", "localidad", "", "Ferrol");
            HBaseTest.addRecord(tablename, "papidal", "carrera", "ruta naval", "54:00:00");
  
            HBaseTest.addRecord(tablename, "juan", "carrera", "ruta naval", "30:00:00");
            HBaseTest.addRecord(tablename, "juan", "localidad", "", "Foz");
 
            System.out.println("===========Consultar datos papidal========");
            HBaseTest.getOneRecord(tablename, "papidal");
 
            System.out.println("===========Mostrar todos los registros========");
            HBaseTest.getAllRecord(tablename);
 
            System.out.println("===========Eliminar un registro y mostrar resultado========");
            HBaseTest.deleteRecord(tablename, "juan");
            HBaseTest.getAllRecord(tablename);
 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
} 

sábado, 7 de septiembre de 2013

lunes, 2 de septiembre de 2013

II CARRERA NOCTURNA CORRE POR FERROL. MEMORIAL LOLETE - SIMULACIÓN

Fecha: 14/09/2013 (finalizada)
Distancia: 8 km
Hora salida: 21:00 (en la Calle Real, a la altura de la Plaza de Armas)


Mapa


Perfil


Tracks

El mapa, perfil y tracks obtenidos de este enlace: http://connect.garmin.com/activity/374273543

Resultados y vídeo de entrada en meta
http://www.championchipnorte.com/resultados-externos/tiempos/id/447/rp/20?c=ADULTOS.%20DISTANCIA:%208000%20M

Simulación previa utilizando crawler casero y hadoop
https://docs.google.com/file/d/0B8mQN199zkq4VmxHaFY1aUZyaWM/edit?usp=sharing

Aunque los nombres recogidos están de forma pública en la red (simplemente realizando una búsqueda con google se puede comprobar), si alguno desea que el suyo no se muestre aquí, dejar un comentario y lo elimino de listado.

martes, 27 de agosto de 2013

Playas próximas a Ferrol, Meirás, Pontedeume y Ares

Probablemente iré editando esta entrada, pero de momento pongo por aquí unas pocas en orden de preferencia:

1. Playa de Chanteiro (Ares)
Una de las mejores playas que conozco en cuanto a pureza de agua y limpieza de arena en general. Tiene muchas rocas a los márgenes para investigar bichejos y tiene pocas olas. Lo peor quizás sea el acceso si se va en coche, ya que es una carretera asfaltada pero con curvas un poco cerradas y estrecha aunque de doble dirección. Cerca está Montefaro (con excelentes vistas a la ría y al puerto exterior) y el castillo de la Palma. Cuidado con las "fanecas bravas".

2. Playa de Esmelle
Playa bastante grande, adyacente a San Jorge. Con olas pero poco fuertes. Generalmente no es excesivamente ventosa y está unida a otras dos pequeñas playas, "O Vilar" y "Fragata". El agua es clara y fresca. En general, de las menos masificadas, con buenos accesos y carril bici hasta el desvío a Doniños



3. Playa de Santa Comba
Próxima a la playa de Ponzos y a la playa de Sartaña. Por esta zona está indicado el sendero de la costa Ártabra (por ejemplo tenemos un indicador que refleja que hay 10 km hasta la playa de Campelo). El acceso quizás no sea de los mejores (carretera estrecha de doble dirección con curvas).



4. Playa del Raso-Seselle (Ares)
Están unidas, lo que hace que tengamos más de 1km de playa para andar. No tiene prácticamente olas y el agua es fresquita. Resguardada del viento. La arena cerca del agua tiene bastantes piedrecitas y conchas y según el día el agua está cristalina o algo turbia por algas. Playa idónea para ir con los cativos.


5. Playa de Valdoviño (Frouxeira)
Playa muy grande, que también se presta a paseos. Bastante aparcamiento aunque también suele tener bastante ocupación. Poco resguardada y con fuerte oleaje, aunque dispone de un lago. Muy buenos accesos.

6. Playa de Cabañas (Pontedeume)
Está al lado de Pontedeume, aproximadamente de 1km. Prácticamente sin olas y el agua es fresquita. Resguardada del viento y con un pinar al lado. El agua no está mal, pero las tengo visto mejores :). Playa idónea también para ir con los cativos.


7. Playa de Campelo
Playa de tamaño medio-pequeña, bastante resguardada, limpia y con un oleaje medio. El acceso es a través de escaleras muy verticales de cemento.

8. Playa de Doniños
Playa masificada, próxima a Ferrol, con oleaje generalmente bastante fuerte y poco resguardada del viento salvo en zonas de dunas. Idónea para la práctica del surf.

Dejo por aquí un mapa con unas cuantas playas:


lunes, 26 de agosto de 2013

Colas de mensajería (Maven, Spring-JMS y ActiveMQ)

En esta entrada vamos a ver como configurar (de forma rápida), como configurar colas con Spring y un gestor de colas, como es el caso de Apache ActiveMQ, para enviar y recibir mensajes. Para ello, podéis descargar:

- La versión 5.7.0 de ActiveMQ
- Tomcat 7

Os creáis un proyecto Maven con la siguiente configuración:

En el pom.xml, la dependencia a Spring y al core de ActiveMQ:
<?xml version="1.0"?>
<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/maven-v4_0_0.xsd">
 <artifactId>spring-activemq-sample</artifactId>
 <modelVersion>4.0.0</modelVersion>
 <packaging>war</packaging>
 <groupId>papidal</groupId>
 <version>1.0</version>
  <properties> 
        <releaseCandidate>1</releaseCandidate>
        <spring.version>3.1.1.RELEASE</spring.version>
        <java.version>1.5</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.javadoc.reporting.version>2.7</maven.javadoc.reporting.version>
        <commons.logging.version>1.1.1</commons.logging.version>
        <log4j.version>1.2.16</log4j.version>
        <context.path>spring-activemq-sample</context.path>
    </properties>
 <build> 
  <resources>
   <resource>
    <directory>src/main/resources</directory>
    <filtering>true</filtering>
   </resource>
  </resources>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
     <warName>${context.path}</warName>
    </configuration>
   </plugin>
  </plugins>
 </build>
 <dependencies>
  <dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>${log4j.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-core</artifactId>
    <version>5.7.0</version>
  </dependency>
  <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-jms</artifactId>
     <version>${spring.version}</version>
  </dependency>
  <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-jms</artifactId>
     <version>3.1.0.RELEASE</version>
     <scope>compile</scope>
  </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-asm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>${spring.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>${spring.version}</version>
  </dependency>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.4</version>
  </dependency>
 </dependencies>
</project>

Un contexto, context.xml, en el que estarán vuestras colas de entrada y salida, así como la conexión al gestor de colas:

<?xml version="1.0" encoding="UTF-8"?>
<Context>

   <!--
     Conexión ActiveMQ
   -->
   <Resource name="jms/mqConnectionFactory"
      auth="Container"
      type="org.apache.activemq.ActiveMQConnectionFactory"
      description="JMS Connection Factory"
          factory="org.apache.activemq.jndi.JNDIReferenceFactory"
          brokerURL="tcp://localhost:61616" />

   <!-- Cola 1 -->
   <Resource name="jms/testQueueOne"
      auth="Container"
      type="org.apache.activemq.command.ActiveMQQueue"
          factory="org.apache.activemq.jndi.JNDIReferenceFactory"
          physicalName="TestQueueOne"/>

   <!-- Cola 2 -->
   <Resource name="jms/testQueueTwo"
      auth="Container"
      type="org.apache.activemq.command.ActiveMQQueue"
          factory="org.apache.activemq.jndi.JNDIReferenceFactory"
          physicalName="TestQueueTwo"/>

</Context>

El resto de configuración, en spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:jee="http://www.springframework.org/schema/jee"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/jee
          http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">


 <!-- Recursos jndi -->
 <jee:jndi-lookup id="mqConnectionFactory" jndi-name="java:comp/env/jms/mqConnectionFactory" />
 <jee:jndi-lookup id="testQueueOne" jndi-name="java:comp/env/jms/testQueueOne" />
 <jee:jndi-lookup id="testQueueTwo" jndi-name="java:comp/env/jms/testQueueTwo" />

 <!-- Clase que recibe los mensajes -->
 <bean id="testMessageListener" class="papidal.TestMessageListener">
     <property name="testMessageSender" ref ="testMessageSender" />
    </bean>

 
 <bean id="poiMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
     <property name="connectionFactory" ref ="mqConnectionFactory" />
     <property name="destination" ref ="testQueueOne"/>
  <property name="messageListener" ref ="testMessageListener"/>
  <property name="concurrentConsumers" value="2" />
    </bean>

 <!-- Clase que envía los mensajes -->
 <bean id="testMessageSender" class="papidal.TestMessageSender">
  <property name="jmsTemplate" ref="jmsTemplate"/>
  <property name="testQueue" ref="testQueueTwo"/>
 </bean>

 <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
  <property name="connectionFactory" ref="mqConnectionFactory" />
 </bean>

</beans>

En el web.xml, indicáis dónde tenemos la configuración de spring:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                       http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   id="WebApp_ID"
   version="2.5">

 <!--
  Fichero de configuración de spring
 -->
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
   /WEB-INF/config/spring-config.xml
  </param-value>
 </context-param>

 <!--
  Cargamos el contexto de Spring
 -->
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

</web-app>

La clase que escucha en la cola 1, los mensaje que llegan:

package papidal;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import org.apache.log4j.Logger;


public class TestMessageListener implements MessageListener
{

 private TestMessageSender messageSender_i;

 private static final Logger logger_c = Logger.getLogger(TestMessageListener.class);


 //Escucha los mensajes
 public void onMessage(Message message)
 {
  logger_c.info("Recibo mensaje de la cola [" + message +"]");

  if (message instanceof TextMessage)
  {
   try
   {
    String msgText = ((TextMessage) message).getText();
    logger_c.debug("Mensaje recibido: " + msgText);

    messageSender_i.sendMessage(msgText);

   }
   catch (JMSException jmsEx_p)
   {
    String errMsg = "Error obteniendo el mensaje";
    logger_c.error(errMsg, jmsEx_p);
   }
  }
  else
  {
   String errMsg = "El mensaje no es del tipo TextMessage";
   logger_c.error(errMsg);
   throw new RuntimeException(errMsg);
  }
 }

 
 public void setTestMessageSender(TestMessageSender messageSender_p)
 {
  this.messageSender_i = messageSender_p;
 }
}


La clase que usamos para enviar los mensajes recibidos hacia la cola 2:

package papidal;

import javax.jms.JMSException;
import javax.jms.Queue;
import org.apache.log4j.Logger;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;

// Enviamos mensajes a una cola
@Service
public class TestMessageSender
{
 private JmsTemplate jmsTemplate_i;
 private Queue testQueue_i;
 private static final Logger logger_c = Logger .getLogger(TestMessageSender.class);

 
 // Envio del mensaje
 public void sendMessage(String message_p) throws JMSException
 {
  logger_c.debug("Ponemos el mensaje en la cola[" + testQueue_i.toString() + "] Mensaje[" + message_p + "]");
  jmsTemplate_i.convertAndSend(testQueue_i, message_p);
 }

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

 
 public void setTestQueue(Queue queue)
 {
  this.testQueue_i = queue;
 }
}



Levantáis el gestor de colas:
"D:\apache-activemq-5.7.0\bin\activemq.bat"

Para administrar:

Simplemente con levantar el servidor ya veremos la cola 1 (en mi caso, un Tomcat 7) con 2 consumidores.

Le damos a "send To", metemos cualquier cosa (típicamente un xml)  y vemos que por la consola de Tomcat hemos recibido el mensaje correctamente, que hemos enviado por la cola 1 y que lo hemos a su vez enviado a la cola 2. 

En el ActiveMQ podemos verlo también (fijaros en la columna de encolados y desencolados. Como la cola para enviar mensajes es la dos, y nosotros escuchamos sólo la 1, la cola 2 no tiene consumidores activos ya que sólo la usamos para enviar mensajes. Si algún modulo quiere escucharla, no hay problema). 

Acordaros de darle a F5 para refrescar la pantalla ;)



A partir de aquí, se pueden definir canales, jugar con el xpath para aceptar o descartar mensajes en función del identificador del envoltorio, usar jaxb para hacer marshall/unmarshall, definir el encoding del parseo de xml a clases Java y viceversa, ...