通过连接池将 JMS 消息发送到 JBoss AS 中的远程队列 [英] Sending JMS message to remote queue in JBoss AS via connection pool

查看:40
本文介绍了通过连接池将 JMS 消息发送到 JBoss AS 中的远程队列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从一个 JBoss AS 5.1 实例向另一个实例发送 JMS 消息.对于我的测试,我让它们都在本地主机上运行,​​客户端 JBoss AS 实例具有正常的端口设置,服务器 JBoss AS 具有所有端口偏移 100 的设置.

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.

在客户端的 EAR 项目中,我在 EAR 根目录下名为 jmstest-service.xml 的文件中定义了一个 JMS 提供程序加载器,其内容如下:

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>

在名为 jmstest-ds.xml 的文件中,我为连接工厂定义了:

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>

在启动客户端 JBoss AS 实例时,我看到正在创建连接工厂.因此,我编写了以下代码来发送 JMS 消息:

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();

将 getRemoteContext() 定义为:

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);
}

到这里基本上一切正常.我从 JNDI 获取连接池和远程队列的引用.但是,当我实际尝试发送消息时,它失败并出现异常:

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)

此时我有点卡住了:(

我尝试了一点调试 JMS,它似乎失败的地方是 org.jboss.messaging.core.impl.postoffice.MessagingPostOffice#routeInternal.此方法接收我的队列名称 (nsQueue),但某些内部结构不包含对此的任何引用:

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

因此,routeInternal 方法返回 false 并抛出上述异常.

The routeInternal method thus returns false and the above mentioned exception is being thrown.

如果我从远程服务器请求(默认)连接工厂,那么一切正常.JMS 消息被服务器正确发送和正确接收.但是,出于性能原因,必须使用本地连接池.

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?

推荐答案

问题是您在提供程序加载器的定义中使用了 java:/XAConnectionFactory.即使此名称将被赋予远程 JNDI 初始上下文,它仍将转到您的 LOCAL JNDI,而不是针对您认为将被解析的远程 JNDI.这只是 JNDI 的一个奇怪之处.

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.

您收到该异常,因为您当地的邮局正在尝试查找队列(nsQueue"),而它显然不知道这一点.正在询问您当地的邮局,因为代码使用的是本地连接工厂,即使您认为它使用的是远程连接工厂.

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.

只需更改对/XAConnectionFactory 的引用,它应该可以工作.

Just change the references to /XAConnectionFactory and it should work.

这篇关于通过连接池将 JMS 消息发送到 JBoss AS 中的远程队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆