首页 > 解决方案 > 无法在 java web servlet 中直接调用 ActiveMQConnection 类

问题描述

问题:

我正在尝试使用ActiveMQConnection对象设置超时以调用setSendTimeout我的 Java servlet 中的方法,但是当调用该代码时,我得到:

Warning:   RAR5038:Unexpected exception while creating resource for pool jms_amq_conn_pool. Exception : javax.resource.ResourceException: Could not create connection.
Warning:   RAR5117 : Failed to obtain/create connection from connection pool [ jms_amq_conn_pool ]. Reason : com.sun.appserv.connectors.internal.api.PoolingException: Could not create connection.

我怎样才能解决这个问题?

更详细的问题:

我有一个 Payara 服务器,它加载了我调用的 servlet 的 activemq-rar 资源。我按照这些说明进行操作。

这是一个列表,突出显示了该链接中的步骤:

  1. 获取 activemq rar 文件以部署到 Payara 服务器。
  2. 配置 ActiveMQ 连接器
  3. 创建 JMS 连接池
  4. 通过创建 JMS 资源来创建到 JMS 连接池的 JNDI 映射。

我有看起来像这样的 Java servlet 代码,当我希望它发送消息时可以正常工作:

    /**
    * Creates a connection using Payara resource then creates a producer/consumer then sends a message.
    */
    public void sendAMQMessage() {
        javax.jms.ConnectionFactory connectionFactory = InitialContext.doLookup("servlet_jms_amq_conn_factory");
        javax.jms.Connection connection = connectionFactory.createConnection();

        // creation is created, now set the client id and start it
        connection.setClientID("test_client_id");
        connection.start();

        javax.jms.Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        javax.jms.TemporaryQueue queue = session.createTemporaryQueue();

        javax.jms.MessageConsumer consumer = session.createConsumer(queue);

        consumer.setMessageListener(this);

        javax.jms.Queue serviceQueue = session.createQueue("queue_name");

        javax.jms.MessageProducer producer = session.createProducer(serviceQueue);

        producer.send("data");
    
    }


    @Override
    public void onMessage(Message message) {
        // receives data back from the initial request.
    }

当前的 Web 应用程序pom.xml没有引用 ActiveMQ 库,因为上面的代码没有导入任何 ActiveMQ 类。但是我想对 Java servlet 发送的消息实现超时,以便如果接收应用程序在一定时间内没有响应,我可以处理它。

javax.jms.Connection没有超时设置方法。

ActiveMQConnectionJavaDoc确实有setSendTimeout(int sendTimeout)一个. 所以我在应用程序中包含了 ActiveMQ 依赖项pom.xml

        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-all</artifactId>
            <version>5.10.0</version>
            <type>jar</type>
        </dependency>

然后当我更新sendAMQMessage上面的方法以使用setSendTimeout(int sendTimeout)

int milliseconds = 10000; // 10,000 ms = 10 seconds
((ActiveMQConnection)connection).setSendTimeout(milliseconds);

然后运行我得到这些警告和异常消息的代码:

Warning:   RAR5038:Unexpected exception while creating resource for pool jms_amq_conn_pool. Exception : javax.resource.ResourceException: Could not create connection.
Warning:   RAR5117 : Failed to obtain/create connection from connection pool [ jms_amq_conn_pool ]. Reason : com.sun.appserv.connectors.internal.api.PoolingException: Could not create connection.
Warning:   RAR5038:Unexpected exception while creating resource for pool jms_amq_conn_pool. Exception : javax.resource.ResourceException: Could not create connection.
Warning:   RAR5117 : Failed to obtain/create connection from connection pool [ jms_amq_conn_pool ]. Reason : com.sun.appserv.connectors.internal.api.PoolingException: Could not create connection.

javax.jms.JMSException: Error in allocating a connection. Cause: Could not create connection.
    at org.apache.activemq.ra.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:101)
    at org.apache.activemq.ra.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:67)

我查看了这个链接,它说只需将 jar 复制到 Payara 服务器的domains/domain1/ilb/ext文件夹。所以我这样做了,activemq-all-5.10.0.jar然后当我运行上面的代码时,我得到了这个异常:

java.lang.ClassCastException: org.apache.activemq.command.ActiveMQQueue cannot be cast to javax.jms.Queue

必须有办法解决这个问题。有人有想法吗?

标签: javamavenweb-applicationsactivemqpayara

解决方案


您所指的超时与收到消息的消费者“响应”所需的时间无关。超时只是关于发送客户端将等待代理确认它确实已收到消息的时间。这发生在消费者收到消息之前。

如果您使用 JMS 实现请求/响应功能,那么您应该使用相关 ID 或临时回复队列遵循正确的模式。

鉴于您使用的是 ActiveMQ JCA 资源适配器,您的客户端实际上从 JNDI 查找中获得的连接实现很可能会被容器的 JCA 实现包装。您不太可能简单地将其转换为 ActiveMQ 实现。此外,所有 ActiveMQ 客户端类都打包在 JCA 资源适配器存档中并与您的应用程序隔离。ClassCastException如果您将这些相同的类放在运行时环境中的其他位置,您可能会得到奇怪的类加载行为(例如意外)。Java EE 应用服务器旨在提供对 Java EE API(例如 JMS、JDBC、JNDI 等)的访问。访问底层实现来做不可移植的事情通常是困难和不鼓励的。


推荐阅读