简体   繁体   English

Active MQ + Spring 3.0-请求/响应实现-示例程序得到响应,但消息使用者计数上升且一直在等待

[英]Active MQ + Spring 3.0 - Request/Response Implementation - Sample Program got response But Message Consumer count keps going up and waiting for ever

I am trying sample projects to implement a Spring 3 + Active MQ Request/Response Synchronos.. I created a spring configuration file, a message producer that puts message in a queue and message consumer that consumes the message and returns a response... 我正在尝试示例项目以实现Spring 3 + Active MQ请求/响应同步。.我创建了一个Spring配置文件,一个消息生产者,它将消息放入队列中,消息使用者使用消息并返回响应...

I am getting the response back... But my sample program doesnt seem to end... When i check the Apache Active MQ Admin console I see that the NUmber of Consumers count keeps going up every time I run my test class... I got to terminate it manually in eclipse for the count to go down in the admin console... 我正在得到响应...但是我的示例程序似乎没有结束...当我检查Apache Active MQ Admin控制台时,我发现每次运行测试类时,消费者数量都在不断增加...我必须在eclipse中手动终止它,以便在管理控制台中减少计数...

I referred this thread here - Stack Overflow Thread - Somebody who has faced the same issue.. But looks like I already have that solution in place and still don't see my issue solved 我在这里提到了这个线程- 堆栈溢出线程 -有人遇到过同样的问题。.但是看来我已经有了该解决方案,但仍然看不到我的问题已解决

Also I referred here and here to create my solution 我也在这里这里提到创建我的解决方案

So here is my code 所以这是我的代码

    <!-- creates an activemq connection factory using the amq namespace -->

<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="tcp://localhost:61616" />
</bean>

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

<!-- CachingConnectionFactory Definition, sessionCacheSize property is the 
    number of sessions to cache -->

<bean id="connectionFactory"
    class="org.springframework.jms.connection.CachingConnectionFactory">
    <constructor-arg ref="jmsConnectionFactory" />
    <property name="exceptionListener" ref="jmsExceptionListener" />
    <property name="sessionCacheSize" value="1" />
    <property name="cacheConsumers" value="false" />
    <property name="cacheProducers" value="false" />
</bean>

<!-- JmsTemplate Definition -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <constructor-arg ref="connectionFactory" />

</bean>


<jms:listener-container connection-factory="connectionFactory">
    <jms:listener id="request.queue.listener" destination="test.request"
        ref="testMessageListener" />
</jms:listener-container>

<bean id="WorkerClient" class="com.vzwcorp.legal.eplm.active.mq.framework.WorkerClient" />

Requestor Class 请求者类别

@Component

public class Requestor { 公共类请求者{

private static final class ProducerConsumer implements
        SessionCallback<Message> {

    private static final int TIMEOUT = 5000;

    private final String msg;

    private final DestinationResolver destinationResolver;

    private final String queue;

    public ProducerConsumer(final String msg, String queue,
            final DestinationResolver destinationResolver) {
        this.msg = msg;
        this.queue = queue;
        this.destinationResolver = destinationResolver;
    }

    public Message doInJms(final Session session) throws JMSException {
        MessageConsumer consumer = null;
        MessageProducer producer = null;
        try {
            final String correlationId = UUID.randomUUID().toString();
            final Destination requestQueue = destinationResolver
                    .resolveDestinationName(session, queue + ".request",
                            false);
            final Destination replyQueue = destinationResolver
                    .resolveDestinationName(session, queue + ".response",
                            false);
            // Create the consumer first!
            consumer = session.createConsumer(replyQueue,
                    "JMSCorrelationID = '" + correlationId + "'");
            final TextMessage textMessage = session.createTextMessage(msg);
            textMessage.setJMSCorrelationID(correlationId);
            textMessage.setJMSReplyTo(replyQueue);
            // Send the request second!
            producer = session.createProducer(requestQueue);
            producer.send(requestQueue, textMessage);
            // Block on receiving the response with a timeout
            return consumer.receive(TIMEOUT);
        } finally {
            // Don't forget to close your resources
            JmsUtils.closeMessageConsumer(consumer);
            JmsUtils.closeMessageProducer(producer);
        }
    }
}

private final JmsTemplate jmsTemplate;

@Autowired
public Requestor(final JmsTemplate jmsTemplate) {
    this.jmsTemplate = jmsTemplate;
}

public String request(final String request, String queue) {
    // Must pass true as the second param to start the connection
    TextMessage message = (TextMessage) jmsTemplate.execute(
            new ProducerConsumer(request, queue, jmsTemplate
                    .getDestinationResolver()), true);
    try {
        return message.getText();
    } catch (JMSException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return "exception in requestor";
    }
}

} }

Message Listener Class 消息侦听器类

@Component

public class TestMessageListener implements MessageListener { 公共类TestMessageListener实现MessageListener {

@Autowired
private WorkerClient WorkerClient;

@Override
public void onMessage(Message arg0) {
    WorkerClient.delegateToClient(arg0);

}

} }

Worker Client Class 工人客户班

@Component

public class WorkerClient implements ApplicationContextAware { 公共类WorkerClient实现ApplicationContextAware {

private ApplicationContext ctx;

private JmsTemplate jmsTemplate;

public void delegateToClient(Message arg0) {
    MessageProducer producer = null;
    if (arg0 instanceof TextMessage) {
        try {
            final TextMessage message = (TextMessage) arg0;

            System.out.println("Message received by Listener: "
                    + message.getJMSCorrelationID() + " - "
                    + message.getText());

            jmsTemplate.setDefaultDestination(message.getJMSReplyTo());

            Session session = jmsTemplate.getConnectionFactory()
                    .createConnection()
                    .createSession(false, Session.AUTO_ACKNOWLEDGE);
            producer = session.createProducer(message.getJMSReplyTo());
            final TextMessage textMessage = session
                    .createTextMessage("I did it at last");
            textMessage.setJMSCorrelationID(message.getJMSCorrelationID());
            textMessage.setJMSReplyTo(message.getJMSReplyTo());
            producer.send(message.getJMSReplyTo(), textMessage);

        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            JmsUtils.closeMessageProducer(producer);
        }
    }
}

@Override
public void setApplicationContext(ApplicationContext arg0)
        throws BeansException {
    ctx = arg0;
    this.jmsTemplate = (JmsTemplate) ctx.getBean("jmsTemplate");
}

At Last The test class 最后的测试课

public class TestSync {

public static void main(String[] args) {

    ApplicationContext ctx = new ClassPathXmlApplicationContext(
            "activeMQConfiguration.xml");
    OrderService orderService = (OrderService) ctx.getBean("orderService");
    JmsTemplate jmsTemplate = (JmsTemplate) ctx.getBean("jmsTemplate");
     Requestor req = new Requestor(jmsTemplate);
    //CopyOfRequestor req = new CopyOfRequestor(jmsTemplate);
    String response = req.request("Hello World", "test");
    System.out.println(response);

}

} }

So how to fix the message consumer returning back and my test class ending? 那么,如何解决消息使用者返回并测试类结束的问题? Please Help.... 请帮忙....

The problem basically is that the application context remains alive probably because of the threads propagated by the JMS listener container. 基本上,问题在于应用程序上下文仍然有效,这可能是因为JMS侦听器容器传播了线程。 The fix is to explicitly call ApplicationContext.close() at the end of your main method, this should lead to orderly shutdown of all the beans (including the JMS listener). 解决方法是在main方法的末尾显式调用ApplicationContext.close(),这应导致所有bean(包括JMS侦听器)的有序关闭。

A better fix is to use Spring Test Support, which will take care of initializing and shutting down the application context instead of you needing to do it explicitly. 更好的解决方法是使用Spring Test Support,它将负责初始化和关闭应用程序上下文,而不需要您明确地进行操作。

@RunWith(SpringJUnit4Runner.class)
@ContextConfiguration(...)
public class TestSync{

    @Autowired OrderService orderService;

    @Test
    public void testJMS(){
        ...
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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