ActiveMQ JMSListener

时间:2016-12-28 17:00:59

标签: java jms activemq spring-integration spring-jms

我是这个话题的新手。我正在使用JMS侦听器来侦听包含拆分消息的Active MQ。我需要收听队列直到最后一条消息,然后将它们一起发送到UI。我能够收听队列并抓取消息,但我不知道有多少分裂消息可用,所以我无法将它们全部发送出去。有没有办法让听众做上述操作?就像队列中没有可用的消息一样,jms监听器会产生空值吗?任何想法或帮助都会非常有用。

我正在使用以下代码使用JMS侦听器侦听Queue。

 private static final String ORDER_RESPONSE_QUEUE = "mail-response-queue";

@JmsListener(destination = ORDER_RESPONSE_QUEUE)
public void receiveMessage(final Message<InventoryResponse> message) throws JMSException {
    LOG.info("+++++++++++++++++++++++++++++++++++++++++++++++++++++");
    MessageHeaders headers =  message.getHeaders();
    LOG.info("Application : headers received : {}", headers);

    InventoryResponse response = message.getPayload();
    LOG.info("Application : response received : {}",response);  
    LOG.info("+++++++++++++++++++++++++++++++++++++++++++++++++++++");
}

我可以使用JMS Listener获取队列信息吗?

1 个答案:

答案 0 :(得分:0)

通过jmx,您可以访问有关目的地的信息,例如,您可以知道消息在队列中的待处理方式。

请注意,如果发送新邮件,则可能会发生这种情况

  

长   org.apache.activemq.broker.jmx.DestinationViewMBean.getQueueSize()

     

@MBeanInfo(value =&#34;目的地中的消息数量尚未   消费。可能被派遣但未被承认。&#34;)

     

返回此目标中尚未发送的消息数   consume返回:返回此目标中的消息数   尚待消费的

import java.util.HashMap;
import java.util.Map;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.activemq.broker.jmx.BrokerViewMBean;
import org.apache.activemq.broker.jmx.QueueViewMBean;

public class JMXGetDestinationInfos {

    public static void main(String[] args) throws Exception {
        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://host:1099/jmxrmi");
        Map<String, String[]> env = new HashMap<>();
        String[] creds = {"admin", "activemq"};
        env.put(JMXConnector.CREDENTIALS, creds);
        JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
        MBeanServerConnection conn = jmxc.getMBeanServerConnection();

        ObjectName activeMq = new ObjectName("org.apache.activemq:type=Broker,brokerName=localhost");

        BrokerViewMBean mbean = MBeanServerInvocationHandler.newProxyInstance(conn, activeMq, BrokerViewMBean.class,
                true);
        for (ObjectName name : mbean.getQueues()) {
            if (("Destination".equals(name.getKeyProperty("destinationName")))) {
                QueueViewMBean queueMbean = MBeanServerInvocationHandler.newProxyInstance(conn, name,
                        QueueViewMBean.class, true);
                System.out.println(queueMbean.getQueueSize());
            }
        }
    }
}

为什么不消费消息,当没有收到消息时你会显示?如果没有收到消息,你有下面的方法在超时后返回null。

  

ActiveMQMessageConsumer.receive(长时间超时)                   throws JMSException接收在指定的超时间隔内到达的下一条消息。此调用阻止直到   消息到达,超时到期,或此消息使用者是   关闭。超时为零永不过期,并且调用阻塞   无限期。指定者:在接口MessageConsumer中接收   参数:timeout - 超时值(以毫秒为单位),超时   零永远不会过期。返回:为此生成的下一条消息   消息使用者,如果超时到期或此消息,则为null   消费者同时关闭

<强>更新

可能是这样的:

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.activemq.broker.jmx.BrokerViewMBean;
import org.apache.activemq.broker.jmx.QueueViewMBean;

public class JMXGetDestinationInfos {

    private QueueViewMBean queueMbean;

    {
        try {
            JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://host:1099/jmxrmi");
            Map<String, String[]> env = new HashMap<>();
            String[] creds = { "admin", "activemq" };
            env.put(JMXConnector.CREDENTIALS, creds);
            JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
            MBeanServerConnection conn = jmxc.getMBeanServerConnection();

            ObjectName activeMq = new ObjectName("org.apache.activemq:type=Broker,brokerName=localhost");

            BrokerViewMBean mbean = MBeanServerInvocationHandler.newProxyInstance(conn, activeMq, BrokerViewMBean.class,
                    true);
            for (ObjectName name : mbean.getQueues()) {
                if (("Destination".equals(name.getKeyProperty("destinationName")))) {
                    queueMbean = MBeanServerInvocationHandler.newProxyInstance(conn, name, QueueViewMBean.class, true);
                    System.out.println(queueMbean.getQueueSize());
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @JmsListener(destination = ORDER_RESPONSE_QUEUE)
    public void receiveMessage(final Message<InventoryResponse> message, javax.jms.Message amqMessage) throws JMSException {
        LOG.info("+++++++++++++++++++++++++++++++++++++++++++++++++++++");
        MessageHeaders headers =  message.getHeaders();
        LOG.info("Application : headers received : {}", headers);

        InventoryResponse response = message.getPayload();
        LOG.info("Application : response received : {}",response);  
        LOG.info("+++++++++++++++++++++++++++++++++++++++++++++++++++++");
        //queueMbean.getQueueSize()  is real time, each call return the real size
        ((org.apache.activemq.command.ActiveMQMessage) amqMessage ).acknowledge();
        if(queueMbean != null && queueMbean.getQueueSize() == 0){
            //display messages ??
        }
    }
}
  

因为getQueueSize()返回了中的邮件数量   尚未消费的目的地。 潜在派遣但是   未确认。

一种解决方案是将resumeledgeMode更新为org.apache.activemq.ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE,以便在您的弹簧DefaultMessageListenerContainer.sessionAcknowledgeModeName中创建会话,并单独确认每条消息,然后检查大小== 0(大小== 0表示所有消息)被派遣并承认。)