无法在 java web servlet 中直接调用 ActiveMQConnection class

Can't invoke ActiveMQConnection class directly in a java web servlet

问题:

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

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 资源。我跟着 these instructions 去做了。

这是一个突出显示 link 中的步骤的列表:

  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.
    }

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

javax.jms.Connection 没有超时 setter 方法。

ActiveMQConnection JavaDoc 确实有一个 setSendTimeout(int sendTimeout)。所以我在应用程序的 pom.xml:

中包含了 ActiveMQ 依赖项
        <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)

我查看了 this link,上面说只需将 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

一定有办法解决这个问题。有人有想法吗?

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

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

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