简体   繁体   中英

Camel as a JMS to JMS bridge - Not showing as an AMQ consumer

I'm pretty new to JMS and have a requirement to bridge between AMQ and WMQ, I saw in the Camel documentation that rather than using the JMS to JMS bridge that they recommend to use Camel.

To start with I'm trying to get my application to take messages off the AMQ and simply log that it is doing so but whenever I start my application in Jetty it doesn't show as a consumer on the apiToTopsQueue and hence doesn't take messages off the queue.

My application-context.xml (which loads the camel-context)

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="classpath:tops-bridge.properties" />

    <import resource="classpath:camel-context.xml" />

    <bean id="log4jInitialization"
          class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
        <property name="targetMethod" value="initLogging" />
        <property name="arguments">
            <list>
                <value>classpath:log4j.xml</value>
                <value>60000</value> <!-- Refresh Log4j config every 60 seconds -->
            </list>
        </property>
    </bean>
</beans>

Then this is the camel-context.xml (I've been commenting in and out random code from tutorials so it might seem odd)

<?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:camel="http://camel.apache.org/schema/spring"
       xmlns:broker="http://activemq.apache.org/schema/core"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://camel.apache.org/schema/spring
                           http://camel.apache.org/schema/spring/camel-spring.xsd
                           http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">

    <camel:camelContext id="defaultCamelContext">
        <camel:routeBuilder ref="bridgeRouteConfig"/>
        <!--<camel:jmxAgent id="agent" createConnector="true"/>-->
    </camel:camelContext>

    <bean id="bridgeRouteConfig" class="com.caci.asg.rail.tops.bridge.TopsBridgeRouteBuilder">
        <constructor-arg name="amqToBridgeQueue" value="${topsBridgeRouteBuilder.route.amqToBridgeRoute}"/>
        <constructor-arg name="bridgeToWmqQueue" value="${topsBridgeRouteBuilder.route.bridgeToWmqRoute}"/>
        <constructor-arg name="wmqToBridgeQueue" value="${topsBridgeRouteBuilder.route.wmqToBridgeRoute}"/>
        <constructor-arg name="bridgeToAmqQueue" value="${topsBridgeRouteBuilder.route.bridgeToAmqRoute}"/>
    </bean>

    <bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="${application.activemq.url}"/>
        <property name="useAsyncSend" value="true"/>
    </bean>

    <bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
          init-method="start" destroy-method="stop">
        <property name="maxConnections" value="8"/>
        <property name="connectionFactory" ref="jmsFactory"/>
    </bean>

    <bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
        <property name="connectionFactory" ref="pooledConnectionFactory"/>
        <property name="concurrentConsumers" value="10"/>
    </bean>


    <!-- lets configure the ActiveMQ JMS broker server -->
    <broker:broker useJmx="true" persistent="false" brokerName="myBroker">
        <broker:transportConnectors>
            <!-- expose a VM transport for in-JVM transport between AMQ and Camel on the server side -->
            <broker:transportConnector name="vm" uri="vm://myBroker"/>
            <!-- expose a TCP transport for clients to use -->
            <broker:transportConnector name="tcp" uri="${application.activemq.url}"/>
        </broker:transportConnectors>
    </broker:broker>

    <!-- lets configure the Camel ActiveMQ to use the embedded ActiveMQ broker declared above -->
    <bean id="jms" class="org.apache.activemq.camel.component.ActiveMQComponent">
        <property name="brokerURL" value="vm://myBroker"/>
    </bean>

</beans>

The camel-context.xml makes use of some properties which are as follows (the ones referring to wmq are placeholders at the moment until I get AMQ working).

application.activemq.url=tcp://localhost:61616

topsBridgeRouteBuilder.route.amqToBridgeRoute=jms:apiToTopsQueue
topsBridgeRouteBuilder.route.bridgeToWmqRoute=mq:toWmq
topsBridgeRouteBuilder.route.wmqToBridgeRoute=mq:fromWmq
topsBridgeRouteBuilder.route.bridgeToAmqRoute=jms:topsToApiQueue

The route builder is in Java as follows

import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;

public class TopsBridgeRouteBuilder extends RouteBuilder {

    private final String amqToBridgeQueue;
    private final String bridgeToWmqQueue;
    private final String wmqToBridgeQueue;
    private final String bridgeToAmqQueue;

    public TopsBridgeRouteBuilder(String amqToBridgeQueue, String bridgeToWmqQueue, String wmqToBridgeQueue,  String bridgeToAmqQueue) {
        this.amqToBridgeQueue = amqToBridgeQueue;
        this.bridgeToWmqQueue = bridgeToWmqQueue;
        this.wmqToBridgeQueue = wmqToBridgeQueue;
        this.bridgeToAmqQueue = bridgeToAmqQueue;
    }

    @Override
    public void configure() throws Exception {
//        from(amqToBridgeQueue).to(bridgeToWmqQueue).log(LoggingLevel.INFO, "Message moving to " + bridgeToWmqQueue);
//        from(wmqToBridgeQueue).to(bridgeToAmqQueue).log(LoggingLevel.INFO, "Message moving to " + bridgeToAmqQueue);

        from(amqToBridgeQueue).log(LoggingLevel.WARN, "Consuming message from" + amqToBridgeQueue);
    }
}

So I'm not really sure why it isn't listed as a consumer of apiToTopsQueue when I start Jetty. My pom includes dependencies for the AMQ/WMQ/camel libraries. The dependencies are as follows (inheriting version/scope from parent pom)

<dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-jms</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ibm.mq</groupId>
            <artifactId>com.ibm.mq.jmqi</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ibm.mq</groupId>
            <artifactId>com.ibm.mqjms</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ibm.mq</groupId>
            <artifactId>connector</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ibm.mq</groupId>
            <artifactId>dhbcore</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-all</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-pool</artifactId>
        </dependency>

I wrote this test to see that I could put messages on and take them off the AMQ from my bridge - this worked and on the AMQ admin page I could see the enqueued/dequeued message count incremented.

import org.apache.activemq.ActiveMQConnectionFactory;
import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

import javax.jms.*;

public class TopsBridgeRouteBuilderTest {

    @Test
    public void testAMessageAddedToAmqCanBeRetrieved() throws JMSException {

        String brokerURL = "tcp://localhost:61616";
        String amqQueue = "apiToTopsQueue";
        String messageToSend = "Test message";

        // Put a message on the AMQ
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerURL);
        Connection connection = connectionFactory.createConnection();
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createQueue(amqQueue);
        MessageProducer producer = session.createProducer(destination);
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
        TextMessage tm = session.createTextMessage(messageToSend);
        producer.send(tm);

        // Create read only consumer to take the message off the queue
        ActiveMQConnectionFactory connectionFactoryReadOnly = new ActiveMQConnectionFactory(brokerURL);
        Connection connectionReadOnly = connectionFactoryReadOnly.createConnection();
        connectionReadOnly.start();
        Session sessionReadOnly = connectionReadOnly.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageConsumer consumer = sessionReadOnly.createConsumer(destination);
        final TextMessage message = (TextMessage) consumer.receive();

        System.out.println("Message retrieved = " + message.getText());
        assertThat(message.getText(), is(messageToSend));
    }
}

Is there something wrong in my configuration that means that the Camel routing isn't working or looking at AMQ when I start Jetty?

Thanks.

Turns out I was missing this section in my web.xml. Lesson learnt for the future!

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM