Wildfly上的JMS 2.0 QueueBrowser不返回消息

时间:2015-07-17 13:22:17

标签: java-ee jms wildfly java-ee-7 hornetq

我有2个简单的EJB bean。 第一个是每秒调用一次的计时器方法。在这个方法中,我向TestQueue添加了10条随机消息。

@Singleton
@Startup
public class Timer {

    @Inject
    private JMSContext context;

    @Resource(mappedName = "java:/jms/queue/TestQueue")
    private Queue queue;

    @Schedule(hour = "*", minute = "*", second = "*/1", persistent = false)
    @AccessTimeout(unit = TimeUnit.DAYS, value = 1)
    public void addToQueue() {
        for(int i = 0; i<30; i++)
            context.createProducer().send(queue, "msg " + (new Random().nextInt(100)));
        printQueueSize();
    }

    public void printQueueSize() {
        QueueBrowser qb = context.createBrowser(queue);
        Enumeration enumeration = null;
        try {
            enumeration = qb.getEnumeration();
        } catch (JMSException e) {
            e.printStackTrace();
        }
        int size = 0;
        while(enumeration.hasMoreElements()) {
            enumeration.nextElement();
            size++;
        }

        System.out.println("Queue size: " + size);
    }
}

第二个bean是MDB使用者。我把Thread.sleep(100)模拟为长时间运行的任务,并确保TestQueue中有一些消息。

@MessageDriven(
activationConfig = {
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/jms/queue/TestQueue"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1")
}) 
public class Consumer implements MessageListener {

    @Override
    public void onMessage(Message msg) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

问题是控制台输出显示:

15:06:29,006 INFO  [stdout] (EJB default - 9) Queue size: 0
15:06:30,006 INFO  [stdout] (EJB default - 10) Queue size: 0
15:06:31,009 INFO  [stdout] (EJB default - 1) Queue size: 0

但是在wildfly管理控制台中我可以看到每秒都有越来越多的消息:

enter image description here

问题是,为什么QueueBrowser返回空Enumeration?它是HornetQ实现中的一个错误还是有一些原因?

3 个答案:

答案 0 :(得分:1)

虽然这不会回答你的问题,但我将在EJB服务中展示如何在HornetQ中获取队列大小:

    InitialContext initialContext = null;
    try {
        // Step 1. Create an initial context to perform the JNDI lookup.
        initialContext = getContext();

        // Step 2. Perfom a lookup on the queue
        Queue queue = (Queue) initialContext.lookup("jmx/queue/YOUR_QUEUE_NAME");


        // Step 7. Use JMX to retrieve the message counters using the
        // JMSQueueControl
        ObjectName on = ObjectNameBuilder.DEFAULT
                .getJMSQueueObjectName(queue.getQueueName());
        JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL("service:jmx:http-remoting-jmx://localhost:9990"), new HashMap<String, Object>());//this is the URL for WildFly 8.2 (should work for all 8.X)
        MBeanServerConnection mbsc = connector.getMBeanServerConnection();
        JMSQueueControl queueControl = MBeanServerInvocationHandler.newProxyInstance(mbsc, on, JMSQueueControl.class, false);

        // Step 8. List the message counters and convert them to
        // MessageCounterInfo data structure.
        String counters = queueControl.listMessageCounter();
        MessageCounterInfo messageCounter = MessageCounterInfo.fromJSON(counters);


        queueControl.getConsumerCount();//this returns consumer count
        queueControl.getMessagesAdded();//returns messages added from the last time we checked
        queueControl.isPaused();//prints out, whether the queue is paused (you can stop a queue from being processed e.g. from JMX)
        queueControl.getMessageCount();//message count so far

    } finally {
        // Step 17. Be sure to close our JMS resources!
        if (initialContext != null) {
            initialContext.close();
        }
    }

答案 1 :(得分:0)

printQueueSize()返回零,因为您是在addToQueue()内调用它。

您的消息尚未在队列中,因为在addToQueue()调用返回(没有错误)之前,在addToQueue()之前启动的事务将不会被提交。

JMS操作是事务性的。

答案 2 :(得分:0)

我几天来一直在讨论这个问题,最后发现在我们的案例中,队列被配置为transactional

这意味着根据JMS 2规范,消息被消费并放入Consumer侧的交易中,因此它们不再包含在队列中,但也不会出现在任何地方否则,它就像一个透明的缓冲区。

请参阅JMS 2 Session API docs

会话可以指定为事务处理。每个事务处理会话都支持一系列事务。每个事务*将一组消息发送*和一组消息接收*分组到一个原子工作单元中。实际上,事务组织会话的输入消息流*并将消息流输出为一系列原子单元。当事务提交时,其原子输入单元被确认,并且其相关的原子输出单元被发送。如果完成了事务回滚,则销毁事务的已发送消息并自动恢复会话的输入。

事务的输入和输出单元的内容只是*在会话的当前事务中生成*和消费的那些消息。

只需在Wildfly的配置(通常是transaction)中将属性none设置为standalone-full.xml即可解决问题:

pooled-connection-factory name="activemq-ra" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm" transaction="none"