我正在尝试从 Apache Artemis 示例版本 2.19.1 部署 artemis-ra-rar 由于Java版本的原因,我只能使用这个版本。
我对 Weblogic 的了解不是很好,但我成功地部署了资源适配器的一个版本,在其中我可以看到 JNDI 树中创建的不同对象。
但是,当我尝试使用这些资源时,我遇到了两个不同的问题。
以下是当前部署的资源适配器中的文件:
ra.xml
<?xml version="1.0" encoding="UTF-8"?>
<connector xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/j2ee"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd"
version="1.5">
<description>ActiveMQ Artemis Resource Adapter</description>
<display-name>ArtemisRA</display-name>
<vendor-name>Apache Software Foundation</vendor-name>
<eis-type>JMS 2.0 Server</eis-type>
<resourceadapter-version>1.0</resourceadapter-version>
<license>
<description>
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
</description>
<license-required>true</license-required>
</license>
<resourceadapter>
<resourceadapter-class>org.apache.activemq.artemis.ra.ActiveMQResourceAdapter</resourceadapter-class>
<config-property>
<description>
The transport type. Multiple connectors can be configured by using a comma separated list,
i.e.
org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory,org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory.
</description>
<config-property-name>ConnectorClassName</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory
</config-property-value>
</config-property>
<config-property>
<description>The transport configuration. These values must be in the form of key=val;key=val;,
if multiple connectors are used then each set must be separated by a comma i.e.
host=host1;port=61616,host=host2;port=61617.
Each set of params maps to the connector classname specified.
</description>
<config-property-name>ConnectionParameters</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>host=myhost1.dev;port=61616</config-property-value>
</config-property>
<config-property>
<config-property-name>HA</config-property-name>
<config-property-type>java.lang.Boolean</config-property-type>
<config-property-value>true</config-property-value>
</config-property>
<config-property>
<config-property-name>UserName</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>tanycast</config-property-value>
</config-property>
<config-property>
<config-property-name>Password</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>(tanycast)</config-property-value>
</config-property>
<outbound-resourceadapter>
<connection-definition>
<managedconnectionfactory-class>org.apache.activemq.artemis.ra.ActiveMQRAManagedConnectionFactory
</managedconnectionfactory-class>
<config-property>
<description>The default session type</description>
<config-property-name>SessionDefaultType</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>javax.jms.Queue</config-property-value>
</config-property>
<config-property>
<description>Whether or not to participate in a JTA transaction, this is used if the RA does not
have access to the Transaction Manager
</description>
<config-property-name>InJtaTransaction</config-property-name>
<config-property-type>java.lang.Boolean</config-property-type>
<config-property-value>true</config-property-value>
</config-property>
<config-property>
<description>Try to obtain a lock within specified number of seconds; less than or equal to 0
disable this functionality
</description>
<config-property-name>UseTryLock</config-property-name>
<config-property-type>java.lang.Integer</config-property-type>
<config-property-value>0</config-property-value>
</config-property>
<connectionfactory-interface>org.apache.activemq.artemis.ra.ActiveMQRAConnectionFactory
</connectionfactory-interface>
<connectionfactory-impl-class>org.apache.activemq.artemis.ra.ActiveMQRAConnectionFactoryImpl
</connectionfactory-impl-class>
<connection-interface>javax.jms.Session</connection-interface>
<connection-impl-class>org.apache.activemq.artemis.ra.ActiveMQRASession</connection-impl-class>
</connection-definition>
<transaction-support>XATransaction</transaction-support>
<authentication-mechanism>
<authentication-mechanism-type>BasicPassword</authentication-mechanism-type>
<credential-interface>javax.resource.spi.security.PasswordCredential</credential-interface>
</authentication-mechanism>
<reauthentication-support>false</reauthentication-support>
</outbound-resourceadapter>
<inbound-resourceadapter>
<messageadapter>
<messagelistener>
<messagelistener-type>javax.jms.MessageListener</messagelistener-type>
<activationspec>
<activationspec-class>org.apache.activemq.artemis.ra.inflow.ActiveMQActivationSpec
</activationspec-class>
<required-config-property>
<config-property-name>destination</config-property-name>
</required-config-property>
</activationspec>
</messagelistener>
</messageadapter>
</inbound-resourceadapter>
<adminobject>
<adminobject-interface>javax.jms.Queue</adminobject-interface>
<adminobject-class>org.apache.activemq.artemis.jms.client.ActiveMQQueue</adminobject-class>
<config-property>
<config-property-name>Address</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>artemis.ra.test.anycast</config-property-value>
</config-property>
</adminobject>
<adminobject>
<adminobject-interface>javax.jms.ConnectionFactory</adminobject-interface>
<adminobject-class>org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory</adminobject-class>
<config-property>
<config-property-name>BrokerURL</config-property-name>
<config-property-type>java.lang.String</config-property-type>
</config-property>
</adminobject>
<adminobject>
<adminobject-interface>javax.jms.XAConnectionFactory</adminobject-interface>
<adminobject-class>org.apache.activemq.artemis.jms.client.ActiveMQXAConnectionFactory</adminobject-class>
<config-property>
<config-property-name>BrokerURL</config-property-name>
<config-property-type>java.lang.String</config-property-type>
</config-property>
</adminobject>
</resourceadapter>
</connector>
weblogic-ra.xml
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-connector xmlns="http://xmlns.oracle.com/weblogic/weblogic-connector"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-connector http://xmlns.oracle.com/weblogic/weblogic-connector/1.5/weblogic-connector.xsd">
<!-- Outbound Resource Adapter -->
<admin-objects>
<admin-object-group>
<admin-object-interface>javax.jms.Queue</admin-object-interface>
<admin-object-class>org.apache.activemq.artemis.jms.client.ActiveMQQueue</admin-object-class>
<admin-object-instance>
<jndi-name>jms/queue/ArtemisTestAnycast</jndi-name>
<properties>
<property>
<name>Address</name>
<value>artemis.ra.test.anycast</value>
</property>
</properties>
</admin-object-instance>
</admin-object-group>
<admin-object-group>
<admin-object-interface>javax.jms.ConnectionFactory</admin-object-interface>
<admin-object-class>org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory</admin-object-class>
<admin-object-instance>
<jndi-name>jms/DirectConnectionFactory</jndi-name>
<properties>
<property>
<name>BrokerURL</name>
<value>(tcp://myhost1.dev:61616)?ha=true</value>
</property>
<property>
<name>UserName</name>
<value>tanycast</value>
</property>
<property>
<name>Password</name>
<value>(tanycast)</value>
</property>
</properties>
</admin-object-instance>
</admin-object-group>
</admin-objects>
<outbound-resource-adapter>
<connection-definition-group>
<connection-factory-interface>org.apache.activemq.artemis.ra.ActiveMQRAConnectionFactory</connection-factory-interface>
<connection-instance>
<jndi-name>jms/ActiveMQConnectionFactory</jndi-name>
<connection-properties>
<properties>
<property>
<name>BrokerURL</name>
<value>(tcp://myhost1.dev:61616)?ha=true</value>
</property>
<property>
<name>UserName</name>
<value>tanycast</value>
</property>
<property>
<name>Password</name>
<value>(tanycast)</value>
</property>
</properties>
</connection-properties>
</connection-instance>
</connection-definition-group>
</outbound-resource-adapter>
</weblogic-connector>
我尝试了两种不同的方法。
jms/ActiveMQConnectionFactory
,它实例化了 org.apache.activemq.artemis.ra.ActiveMQRAConnectionFactory
我的基本网络应用程序在 Servlet 中调用它
package com.example.jms;
import javax.annotation.Resource;
import javax.jms.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/send")
public class JmsServlet extends HttpServlet {
@Resource(name = "jms/ActiveMQConnectionFactory", lookup = "jms/ActiveMQConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(name = "jms/queue/ArtemisTestAnycast")
private Queue queue;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
log("connectionFactory: " + connectionFactory);
String messageText = req.getParameter("message");
try (Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
MessageProducer producer = session.createProducer(queue);
TextMessage message = session.createTextMessage(messageText);
producer.send(message);
resp.getWriter().write("Message sent: " + messageText);
} catch (JMSException e) {
throw new ServletException("Failed to send message", e);
}
}
}
资源适配器部署并启动正常,但是当我调用我的方法时,出现以下异常:
<Dec 13, 2024 6:40:41,745 PM GMT> <Info> <Common> <BEA-000640> <Resource Pool "jms/ActiveMQConnectionFactory" resuming by external command (multi data source or console or other).>
<Dec 13, 2024 6:40:41,746 PM GMT> <Info> <ServletContext-/JMSDemoApp> <BEA-000000> <com.example.jms.JmsServlet: connectionFactory: weblogic.deployment.jms.PooledConnectionFactory@1d5f4768>
<Dec 13, 2024 6:40:41,751 PM GMT> <Error> <HTTP> <BEA-101017> <[ServletContext@33646340[app:JMSDemoApp module:JMSDemoApp.war path:null spec-version:3.1]] Root cause of ServletException.
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.ActiveMQRASessionFactoryImpl.setExceptionListener(ActiveMQRASessionFactoryImpl.java:588)
at weblogic.deployment.jms.JMSSessionPool.getConnectionHelper(JMSSessionPool.java:617)
at weblogic.deployment.jms.PooledConnectionFactory.createConnectionInternal(PooledConnectionFactory.java:426)
at weblogic.deployment.jms.PooledConnectionFactory.createConnection(PooledConnectionFactory.java:271)
at com.example.jms.JmsServlet.doPost(JmsServlet.java:25)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
>
<Dec 13, 2024 6:40:41,752 PM GMT> <Warning> <JMSPool> <BEA-169807> <There was an error while making the initial connection to the JMS resource named jms/ActiveMQConnectionFactory from within an EJB or a servlet. The server will attempt the connection again later. The error was javax.jms.IllegalStateException: This method is not applicable inside the application server. See the J2EE spec, e.g. J2EE1.4 Section 6.6>
我的理解是,
org.apache.activemq.artemis.ra.ActiveMQRAConnectionFactory
包装在特定于Weblogic的PooledConnectionFactory中,并且在调用方法setExceptionListener(ActiveMQRASessionFactoryImpl.java:588)
时失败。
DirectConnectionFactory
来实例化 org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
,希望绕过服务器创建的 PooledConnection
。通过这种方法,我最终会更进一步,与服务器的连接似乎有效,因为服务器拒绝了
null
的用户,尽管我已经设置了属性。
如果我使用以下配置部署测试 Web 应用程序:
@WebServlet("/send")
public class JmsServlet extends HttpServlet {
@Resource(name = "jms/DirectConnectionFactory", lookup = "jms/DirectConnectionFactory")
private ConnectionFactory connectionFactory;
我收到以下异常:
<Dec 13, 2024 6:59:04,366 PM GMT> <Info> <Common> <BEA-000640> <Resource Pool "jms/DirectConnectionFactory" resuming by external command (multi data source or console or other).>
<Dec 13, 2024 6:59:04,626 PM GMT> <Error> <HTTP> <BEA-101017> <[ServletContext@1888612433[app:JMSDemoApp module:JMSDemoApp.war path:null spec-version:3.1]] Root cause of ServletException.
javax.jms.JMSSecurityException: AMQ229031: Unable to validate user from 10.232.194.90:55502. Username: null; SSL certificate subject DN: unavailable
at org.apache.activemq.artemis.core.protocol.core.impl.ChannelImpl.sendBlocking(ChannelImpl.java:549)
at org.apache.activemq.artemis.core.protocol.core.impl.ChannelImpl.sendBlocking(ChannelImpl.java:443)
at org.apache.activemq.artemis.core.protocol.core.impl.ActiveMQClientProtocolManager.createSessionContext(ActiveMQClientProtocolManager.java:306)
at org.apache.activemq.artemis.core.protocol.core.impl.ActiveMQClientProtocolManager.createSessionContext(ActiveMQClientProtocolManager.java:254)
at org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryImpl.createSessionChannel(ClientSessionFactoryImpl.java:1437)
at org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryImpl.createSessionInternal(ClientSessionFactoryImpl.java:743)
at org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryImpl.createSession(ClientSessionFactoryImpl.java:324)
at org.apache.activemq.artemis.jms.client.ActiveMQConnection.authorize(ActiveMQConnection.java:661)
>
<Dec 13, 2024 6:59:04,863 PM GMT> <Warning> <JMSPool> <BEA-169807> <There was an error while making the initial connection to the JMS resource named jms/DirectConnectionFactory from within an EJB or a servlet. The server will attempt the connection again later. The error was javax.jms.JMSSecurityException: AMQ229031: Unable to validate user from 10.232.194.90:55520. Username: null; SSL certificate subject DN: unavailable>
我的理解是,网络应用程序能够连接到主机,但凭据不正确(即:无法验证来自 10.232.194.90:55502 的用户。用户名:null;)
如果有人可以的话,我将不胜感激:
Java EE 规范不允许从 servlet 容器调用
setExceptionListener
。异常消息具体说明了这一点:
This method is not applicable inside the application server. See the J2EE spec, e.g. J2EE1.4 Section 6.6
J2EE1.4 规范第 6.6 节说:
以下方法只能由应用程序组件使用 在应用程序客户端容器中执行:
方法javax.jms.Session
setMessageListener
方法javax.jms.Session
getMessageListener
方法javax.jms.Session
run
方法javax.jms.QueueConnection
createConnectionConsumer
方法javax.jms.TopicConnection
createConnectionConsumer
方法javax.jms.TopicConnection
createDurableConnectionConsumer
方法javax.jms.MessageConsumer
getMessageListener
方法javax.jms.MessageConsumer
setMessageListener
方法javax.jms.Connection
setExceptionListener
方法javax.jms.Connection
stop
方法javax.jms.Connection
setClientID