【问题标题】:How to create a listener on a JMS Temporary Queue in a JEE server (Wildfly)?如何在 JEE 服务器(Wildfly)中的 JMS 临时队列上创建侦听器?
【发布时间】:2018-03-18 13:21:44
【问题描述】:

我正在尝试使用 Wildfly 10 中的 JMS 2.0 和注入的连接工厂创建一个临时 JMS 队列。

我正在使用 @JMSConnectionFactory 注入我的 ConnectionFactory。这工作正常。

@Inject @JMSConnectionFactory("java:/jms/RemoteConnectionFactory") JMSContext jmsContext

创建一个临时队列也可以正常工作:

Destination jmsQueue = jmsContext.createTemporaryQueue();

创建发布者并发布消息也可以:

JMSProducer producer = jmsContext.createProducer();
TextMessage msg = jmsContext.createTextMessage(Long.toString(new Date().getTime()));
producer.send(jmsQueue, msg);

但是,如何为队列创建侦听器?我不能使用 MDB,因为临时队列没有预定义。如果我尝试创建消费者并为其分配消息侦听器,则会收到以下错误消息:

    JMSConsumer consumer = jmsContext.createConsumer(jmsQueue);
    consumer.setMessageListener(new MessageListener() {
                 ...
                 ...
            });

错误跟踪:

Caused by: javax.jms.IllegalStateException: This method is not applicable inside the application server. See the J2EE spec, e.g. J2EE1.4 Section 6.6
        at org.apache.activemq.artemis.ra.ActiveMQRASession.checkStrict(ActiveMQRASession.java:1452)
        at org.apache.activemq.artemis.ra.ActiveMQRAMessageConsumer.setMessageListener(ActiveMQRAMessageConsumer.java:123)
        at org.apache.activemq.artemis.jms.client.ActiveMQJMSConsumer.setMessageListener(ActiveMQJMSConsumer.java:59)

因此,我似乎无法使用 JEE 控制的连接工厂明确设置消息侦听器。但鉴于它是一个临时队列,我无法创建 MDB,因为目标在编译时未知。那么如何收听临时队列呢?

【问题讨论】:

    标签: java jakarta-ee jms wildfly


    【解决方案1】:

    我只能通过使用 JMS 1.0 来解决这个问题。我有类似的代码:

    TopicConnectionFactory topicConnectionFactory;
    Topic topic;
    TopicConnection topicConnection;
    
    try {
        InitialContext context = new InitialContext();
        topicConnectionFactory = (TopicConnectionFactory)jndi.lookup("jboss/DefaultJMSConnectionFactory");
        topic = (Topic)jndi.lookup("jms/myTopicName");
    
        topicConnection = topicConnectionFactory.createTopicConnection();
    
        TopicSession topicSession = topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
    
        TopicSubscriber topicSubscriber = topicSession.createSubscriber(projectTopic, null, false);
        topicSubscriber.setMessageListener(listenerClass);
        topicConnection.start();
    }
    ...
    

    其中listenerClass 是一个实现javax.jms.MessageListener 的类。

    这利用了 standalone-full.xml 中 Wildfly 中定义的预定义 JMS 连接工厂,因此我不需要设置显式连接工厂。

    作为警告 - 我最后一次运行此代码是在 Wildfly 8 中,所以有些事情可能有所改变。此外,我没有使用远程连接,所以同样可能存在一些差异。

    【讨论】:

    • 谢谢 - 我也试过了,但仍然抛出同样的异常。并不特别惊讶,因为无论是使用 JMS2 还是 JMS1 外观,客户端仍然使用相同的 ActiveMARASession。我无法想象对此没有合乎逻辑的解决方案。
    • 为什么需要一个临时队列?如果您希望容器在部署的生命周期内提供 mdb 实例,那么这也需要队列存在,否则它们将附加到什么?
    • @willt 我需要一个发布/订阅队列,该队列对我的集群中的每个节点都是唯一的。队列必须在运行时的生命周期内存在;它不需要持续重启。另外,我不想手动管理这些队列。因此临时队列的想法......但是如果没有办法听它,那么在jee中临时队列的目的是什么?
    • @EricB。 - 你的部署环境是什么样的?我最终摆脱了我的 JMS 代码,转而使用 AWS SQS 队列。它不是 100% 的替代品,因为需要轮询 SQS 队列,但对于我的代码,它运行良好。
    • @stdunbar Jboss EAP 7/Wildfly 10. 迁移到第三方 mq 代理不是在任何时候都可以选择的,但认为它会在未来成为。但现在需要一个解决方案
    猜你喜欢
    • 2017-03-28
    • 2015-12-05
    • 2017-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 2014-01-21
    • 1970-01-01
    相关资源
    最近更新 更多