通过连接池将JMS消息发送到JBoss AS中的远程队列
我正在尝试从一个 JBoss AS 5.1 实例向另一个实例发送一条 JMS 消息。对于我的测试,我让它们都在 localhost 上运行,客户端 JBoss AS 实例具有正常端口设置,服务器 JBoss AS 具有所有端口偏移 100 的设置。
在客户端上的 EAR 项目中,我定义了一个JMS 提供程序加载器位于 EAR 根目录中名为 jmstest-service.xml 的文件中,其中包含以下内容:
jmstest-service.xml:
<mbean code="org.jboss.jms.jndi.JMSProviderLoader" name="jboss.messaging:service=JMSProviderLoader,name=MyJMSProvider">
<attribute name="ProviderName">MyJMSProvider</attribute>
<attribute name="ProviderAdapterClass">org.jboss.jms.jndi.JNDIProviderAdapter</attribute>
<attribute name="FactoryRef">java:/XAConnectionFactory</attribute>
<attribute name="QueueFactoryRef">java:/XAConnectionFactory</attribute>
<attribute name="TopicFactoryRef">java:/XAConnectionFactory</attribute>
<attribute name="Properties">
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=jnp://localhost:1199
</attribute>
</mbean>
在名为 jmstest-ds.xml 的文件中,我放置了一个连接工厂的定义:
jmstest-ds.xml:
<tx-connection-factory>
<jndi-name>MyJmsXA</jndi-name>
<xa-transaction/>
<rar-name>jms-ra.rar</rar-name>
<connection-definition>org.jboss.resource.adapter.jms.JmsConnectionFactory</connection-definition>
<config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property>
<config-property name="JmsProviderAdapterJNDI" type="java.lang.String">java:/MyJMSProvider</config-property>
<max-pool-size>20</max-pool-size>
<depends>jboss.messaging:service=ServerPeer</depends>
</tx-connection-factory>
当启动客户端 JBoss AS 实例时,我看到正在创建连接工厂。因此,我编写了以下代码来发送 JMS 消息:
InitialContext context = new InitialContext();
QueueConnectionFactory factory = (QueueConnectionFactory)context.lookup("java:/MyJmsXA");
QueueConnection connect = factory.createQueueConnection();
QueueSession session = connect.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = (Destination)getRemoteContext().lookup("/queue/nsQueue");
MessageProducer sender = session.createProducer(destination);
ObjectMessage message = session.createObjectMessage("bla");
sender.send(message);
connect.close();
getRemoteContext() 定义为:
InitialContext getRemoteContext() {
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory" );
env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
env.put(Context.PROVIDER_URL, "jnp://localhost:1199");
return new InitialContext(env);
}
到目前为止,基本上一切正常。我从 JNDI 获取连接池和远程队列的引用。然而,当我实际尝试发送消息时,它失败并出现异常:
ERROR [ExceptionUtil] SessionEndpoint[pa-96fhptag-1-8wtzotag-7jdzy7-110j3] send [sa-mdkvptag-1-8wtzotag-7jdzy7-110j3]
javax.jms.JMSException: Failed to route Reference[20928781172555777]:RELIABLE to nsQueue
at org.jboss.jms.server.endpoint.ServerConnectionEndpoint.sendMessage(ServerConnectionEndpoint.java:757)
at org.jboss.jms.server.endpoint.ServerSessionEndpoint.send(ServerSessionEndpoint.java:399)
at org.jboss.jms.server.endpoint.advised.SessionAdvised.org$jboss$jms$server$endpoint$advised$SessionAdvised$send$aop(SessionAdvised.java:87)
at org.jboss.jms.server.endpoint.advised.SessionAdvised$send_7280680627620114891.invokeTarget(SessionAdvised$send_7280680627620114891.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:111)
at org.jboss.jms.server.container.SecurityAspect.handleSend(SecurityAspect.java:157)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.jboss.aop.advice.PerInstanceAdvice.invoke(PerInstanceAdvice.java:122)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.server.endpoint.advised.SessionAdvised.send(SessionAdvised.java)
at org.jboss.jms.wireformat.SessionSendRequest.serverInvoke(SessionSendRequest.java:95)
at org.jboss.jms.server.remoting.JMSServerInvocationHandler.invoke(JMSServerInvocationHandler.java:143)
at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:891)
at org.jboss.remoting.transport.local.LocalClientInvoker.invoke(LocalClientInvoker.java:106)
at org.jboss.remoting.Client.invoke(Client.java:1724)
at org.jboss.remoting.Client.invoke(Client.java:629)
at org.jboss.remoting.Client.invoke(Client.java:617)
at org.jboss.jms.client.delegate.DelegateSupport.doInvoke(DelegateSupport.java:189)
at org.jboss.jms.client.delegate.DelegateSupport.doInvoke(DelegateSupport.java:160)
at org.jboss.jms.client.delegate.ClientSessionDelegate.org$jboss$jms$client$delegate$ClientSessionDelegate$send$aop(ClientSessionDelegate.java:499)
at org.jboss.jms.client.delegate.ClientSessionDelegate$send_6145266547759487588.invokeTarget(ClientSessionDelegate$send_6145266547759487588.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:111)
at org.jboss.jms.client.container.SessionAspect.handleSend(SessionAspect.java:661)
at org.jboss.aop.advice.org.jboss.jms.client.container.SessionAspect_z_handleSend_1677669648.invoke(SessionAspect_z_handleSend_1677669648.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.client.container.FailoverValveInterceptor.invoke(FailoverValveInterceptor.java:92)
at org.jboss.aop.advice.PerInstanceInterceptor.invoke(PerInstanceInterceptor.java:86)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.client.container.ClosedInterceptor.invoke(ClosedInterceptor.java:170)
at org.jboss.aop.advice.PerInstanceInterceptor.invoke(PerInstanceInterceptor.java:86)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.client.delegate.ClientSessionDelegate.send(ClientSessionDelegate.java)
at org.jboss.jms.client.container.ProducerAspect.handleSend(ProducerAspect.java:269)
at org.jboss.aop.advice.org.jboss.jms.client.container.ProducerAspect_z_handleSend_1677669648.invoke(ProducerAspect_z_handleSend_1677669648.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.client.container.ClosedInterceptor.invoke(ClosedInterceptor.java:170)
at org.jboss.aop.advice.PerInstanceInterceptor.invoke(PerInstanceInterceptor.java:86)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.client.delegate.ClientProducerDelegate.send(ClientProducerDelegate.java)
at org.jboss.jms.client.JBossMessageProducer.send(JBossMessageProducer.java:164)
at org.jboss.jms.client.JBossMessageProducer.send(JBossMessageProducer.java:207)
at org.jboss.jms.client.JBossMessageProducer.send(JBossMessageProducer.java:145)
at org.jboss.jms.client.JBossMessageProducer.send(JBossMessageProducer.java:136)
at org.jboss.resource.adapter.jms.JmsMessageProducer.send(JmsMessageProducer.java:142)
此时我有点卡住了:(
我尝试稍微调试一下 JMS,但似乎失败的地方是在 org 中.jboss.messaging.core.impl.postoffice.MessagingPostOffice#routeInternal
。此方法接收我的队列的名称 (nsQueue),但某些内部结构不包含对此的任何引用:
private boolean routeInternal(MessageReference ref, Condition condition, Transaction tx, boolean fromCluster, Set names) throws Exception {
if (trace) { log.trace(this + " routing " + ref + " with condition '" +
condition + "'" + (tx == null ? "" : " transactionally in " + tx) +
" from cluster " + fromCluster); }
boolean routed = false;
lock.readLock().acquire();
try
{
List queues = (List)mappings.get(condition);
if (queues != null) // THIS IS INDEED NULL
因此,routeInternal 方法返回 false 。
如果我从远程服务器请求(默认)连接工厂,那么服务器会正确发送并正确接收 JMS 消息,并且会引发上述异常 ?
那么,有谁知道这里出了什么问题,或者知道使用远程 JMS 队列连接池的替代方法吗
I'm trying to send a JMS message from one JBoss AS 5.1 instance to the other. For my test I have them both running on localhost, the client JBoss AS instance with the normal port settings and the server JBoss AS with the setting where all ports are offset by 100.
In an EAR project on the client, I've defined a JMS provider loader in a file called jmstest-service.xml in the root of my EAR with the following content:
jmstest-service.xml:
<mbean code="org.jboss.jms.jndi.JMSProviderLoader" name="jboss.messaging:service=JMSProviderLoader,name=MyJMSProvider">
<attribute name="ProviderName">MyJMSProvider</attribute>
<attribute name="ProviderAdapterClass">org.jboss.jms.jndi.JNDIProviderAdapter</attribute>
<attribute name="FactoryRef">java:/XAConnectionFactory</attribute>
<attribute name="QueueFactoryRef">java:/XAConnectionFactory</attribute>
<attribute name="TopicFactoryRef">java:/XAConnectionFactory</attribute>
<attribute name="Properties">
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=jnp://localhost:1199
</attribute>
</mbean>
In a file called jmstest-ds.xml I've put a definition for the connection factory:
jmstest-ds.xml:
<tx-connection-factory>
<jndi-name>MyJmsXA</jndi-name>
<xa-transaction/>
<rar-name>jms-ra.rar</rar-name>
<connection-definition>org.jboss.resource.adapter.jms.JmsConnectionFactory</connection-definition>
<config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property>
<config-property name="JmsProviderAdapterJNDI" type="java.lang.String">java:/MyJMSProvider</config-property>
<max-pool-size>20</max-pool-size>
<depends>jboss.messaging:service=ServerPeer</depends>
</tx-connection-factory>
When starting up the client JBoss AS instance I see the connection factory being created. So, I've written the following code to sent the JMS message:
InitialContext context = new InitialContext();
QueueConnectionFactory factory = (QueueConnectionFactory)context.lookup("java:/MyJmsXA");
QueueConnection connect = factory.createQueueConnection();
QueueSession session = connect.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = (Destination)getRemoteContext().lookup("/queue/nsQueue");
MessageProducer sender = session.createProducer(destination);
ObjectMessage message = session.createObjectMessage("bla");
sender.send(message);
connect.close();
With the getRemoteContext() defined as:
InitialContext getRemoteContext() {
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory" );
env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
env.put(Context.PROVIDER_URL, "jnp://localhost:1199");
return new InitialContext(env);
}
Up till here it basically all works. I get references back from JNDI for the connection pool and for the remote queue. However when I actually try to sent the message it fails with an exception:
ERROR [ExceptionUtil] SessionEndpoint[pa-96fhptag-1-8wtzotag-7jdzy7-110j3] send [sa-mdkvptag-1-8wtzotag-7jdzy7-110j3]
javax.jms.JMSException: Failed to route Reference[20928781172555777]:RELIABLE to nsQueue
at org.jboss.jms.server.endpoint.ServerConnectionEndpoint.sendMessage(ServerConnectionEndpoint.java:757)
at org.jboss.jms.server.endpoint.ServerSessionEndpoint.send(ServerSessionEndpoint.java:399)
at org.jboss.jms.server.endpoint.advised.SessionAdvised.org$jboss$jms$server$endpoint$advised$SessionAdvised$send$aop(SessionAdvised.java:87)
at org.jboss.jms.server.endpoint.advised.SessionAdvised$send_7280680627620114891.invokeTarget(SessionAdvised$send_7280680627620114891.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:111)
at org.jboss.jms.server.container.SecurityAspect.handleSend(SecurityAspect.java:157)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.jboss.aop.advice.PerInstanceAdvice.invoke(PerInstanceAdvice.java:122)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.server.endpoint.advised.SessionAdvised.send(SessionAdvised.java)
at org.jboss.jms.wireformat.SessionSendRequest.serverInvoke(SessionSendRequest.java:95)
at org.jboss.jms.server.remoting.JMSServerInvocationHandler.invoke(JMSServerInvocationHandler.java:143)
at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:891)
at org.jboss.remoting.transport.local.LocalClientInvoker.invoke(LocalClientInvoker.java:106)
at org.jboss.remoting.Client.invoke(Client.java:1724)
at org.jboss.remoting.Client.invoke(Client.java:629)
at org.jboss.remoting.Client.invoke(Client.java:617)
at org.jboss.jms.client.delegate.DelegateSupport.doInvoke(DelegateSupport.java:189)
at org.jboss.jms.client.delegate.DelegateSupport.doInvoke(DelegateSupport.java:160)
at org.jboss.jms.client.delegate.ClientSessionDelegate.org$jboss$jms$client$delegate$ClientSessionDelegate$send$aop(ClientSessionDelegate.java:499)
at org.jboss.jms.client.delegate.ClientSessionDelegate$send_6145266547759487588.invokeTarget(ClientSessionDelegate$send_6145266547759487588.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:111)
at org.jboss.jms.client.container.SessionAspect.handleSend(SessionAspect.java:661)
at org.jboss.aop.advice.org.jboss.jms.client.container.SessionAspect_z_handleSend_1677669648.invoke(SessionAspect_z_handleSend_1677669648.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.client.container.FailoverValveInterceptor.invoke(FailoverValveInterceptor.java:92)
at org.jboss.aop.advice.PerInstanceInterceptor.invoke(PerInstanceInterceptor.java:86)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.client.container.ClosedInterceptor.invoke(ClosedInterceptor.java:170)
at org.jboss.aop.advice.PerInstanceInterceptor.invoke(PerInstanceInterceptor.java:86)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.client.delegate.ClientSessionDelegate.send(ClientSessionDelegate.java)
at org.jboss.jms.client.container.ProducerAspect.handleSend(ProducerAspect.java:269)
at org.jboss.aop.advice.org.jboss.jms.client.container.ProducerAspect_z_handleSend_1677669648.invoke(ProducerAspect_z_handleSend_1677669648.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.client.container.ClosedInterceptor.invoke(ClosedInterceptor.java:170)
at org.jboss.aop.advice.PerInstanceInterceptor.invoke(PerInstanceInterceptor.java:86)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.client.delegate.ClientProducerDelegate.send(ClientProducerDelegate.java)
at org.jboss.jms.client.JBossMessageProducer.send(JBossMessageProducer.java:164)
at org.jboss.jms.client.JBossMessageProducer.send(JBossMessageProducer.java:207)
at org.jboss.jms.client.JBossMessageProducer.send(JBossMessageProducer.java:145)
at org.jboss.jms.client.JBossMessageProducer.send(JBossMessageProducer.java:136)
at org.jboss.resource.adapter.jms.JmsMessageProducer.send(JmsMessageProducer.java:142)
At this point I'm more than a little stuck :(
I've tried to debug the JMS a little and where it seems to fail is in org.jboss.messaging.core.impl.postoffice.MessagingPostOffice#routeInternal
. This method receives the name of my queue (nsQueue), but some internal structure doesn't contain any reference to that:
private boolean routeInternal(MessageReference ref, Condition condition, Transaction tx, boolean fromCluster, Set names) throws Exception {
if (trace) { log.trace(this + " routing " + ref + " with condition '" +
condition + "'" + (tx == null ? "" : " transactionally in " + tx) +
" from cluster " + fromCluster); }
boolean routed = false;
lock.readLock().acquire();
try
{
List queues = (List)mappings.get(condition);
if (queues != null) // THIS IS INDEED NULL
The routeInternal method thus returns false and the above mentioned exception is being thrown.
If I request the (default) connection factory from the remote server, then everything works. The JMS message is correctly sent and correctly received by the server. However, for performance reasons it's necessary to use a local connection pool.
So, does anyone knows what goes wrong here, or knows of an alternative method to use a connection pool for a remote JMS queue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是您在提供程序加载器的定义中使用了 java:/XAConnectionFactory。即使这个名称将被赋予远程 JNDI 初始上下文,它仍然会转到您的 LOCAL JNDI,而不是您认为它将被解析的远程 JNDI。这只是 JNDI 的一个奇怪之处。
您会得到该异常,因为您当地的邮局正在尝试查找队列(“nsQueue”),但它显然不知道这一点。正在询问您当地的邮局,因为代码正在使用本地连接工厂,即使您认为它正在使用远程连接工厂。
只需更改对 /XAConnectionFactory 的引用,它就应该可以工作。
The problem is that you used java:/XAConnectionFactory in the definition of the provider loader. Even though this name will be given to the remote JNDI initial context, it will still go to your LOCAL JNDI, not the remote JNDI against you think it will be resolved. This is just an oddity of JNDI.
You get that exception since your local post office is trying to find the queue ("nsQueue") and it obviously doesn't know about that. Your local post office is being asked, since the code is using the local connection factory, even when you think it's using the remote one.
Just change the references to /XAConnectionFactory and it should work.