Java 通过连接池将 JMS 消息发送到 JBoss AS 中的远程队列
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3112165/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sending JMS message to remote queue in JBoss AS via connection pool
提问by akira
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.
我正在尝试从一个 JBoss AS 5.1 实例向另一个实例发送 JMS 消息。对于我的测试,我让它们都在本地主机上运行,客户端 JBoss AS 实例具有正常的端口设置,服务器 JBoss AS 具有所有端口偏移 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:
在客户端上的一个 EAR 项目中,我在我的 EAR 根目录中名为 jmstest-service.xml 的文件中定义了一个 JMS 提供程序加载器,其内容如下:
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>
In a file called jmstest-ds.xml I've put a definition for the connection factory:
在名为 jmstest-ds.xml 的文件中,我为连接工厂定义了:
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>
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:
启动客户端 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();
With the getRemoteContext() defined as:
将 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);
}
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:
到这里基本上一切正常。我从 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)
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:
我试过稍微调试 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
The routeInternal method thus returns false and the above mentioned exception is being thrown.
因此, routeInternal 方法返回 false 并抛出上述异常。
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.
如果我从远程服务器请求(默认)连接工厂,那么一切正常。服务器正确发送和正确接收 JMS 消息。但是,出于性能原因,必须使用本地连接池。
So, does anyone knows what goes wrong here, or knows of an alternative method to use a connection pool for a remote JMS queue?
那么,有谁知道这里出了什么问题,或者知道将连接池用于远程 JMS 队列的替代方法吗?
采纳答案by Arjan Tijms
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.
问题是您在提供程序加载器的定义中使用了 java:/XAConnectionFactory 。即使此名称将被赋予远程 JNDI 初始上下文,它仍将转到您的 LOCAL JNDI,而不是针对您认为将被解析的远程 JNDI。这只是 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.
您会收到该异常,因为您当地的邮局正在尝试查找队列(“nsQueue”),而它显然不知道这一点。正在询问您当地的邮局,因为代码正在使用本地连接工厂,即使您认为它使用的是远程连接工厂。
Just change the references to /XAConnectionFactory and it should work.
只需更改对 /XAConnectionFactory 的引用,它应该可以工作。