为什么我的QuendConnectionFactory的JNDI查找返回null?

Sim*_*son 7 java jndi jms geronimo java-ee

我试图寻找一个QueueConnectionFactoryQueue通过Geronimo的JNDI.在Queue获取返回正常,但QueueConnectionFactory查找始终返回null.它不会抛出一个NamingException,如果JNDI名称不正确,这就是我所期望的.

谁能看到我做错了什么?下面的测试代码输出:

true
false

import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class JndiTest
{
    private final static String QUEUE_NAME = "jca:/org.apache.geronimo.configs/activemq-ra/JCAAdminObject/SendReceiveQueue";
    private final static String FACTORY_NAME = "jca:/org.apache.geronimo.configs/activemq-ra/JCAManagedConnectionFactory/DefaultActiveMQConnectionFactory";

    public static void main(String[] args) throws NamingException
    {
        InitialContext ctx = new InitialContext();
        QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup(FACTORY_NAME);
        Queue queue = (Queue)ctx.lookup(QUEUE_NAME);
        System.out.println(factory == null);
        System.out.println(queue == null);      
    }

}
Run Code Online (Sandbox Code Playgroud)

如果它有所不同:我已将openejb-client-3.0.1.jar,geronimo-ejb_3.0_spec-1.0.1.jar和activemq-core-4.1.2-G20090207.jar添加到我的类路径中,并且我的jndi.properties文件具有以下属性:

java.naming.factory.initial = org.apache.openejb.client.RemoteInitialContextFactory
java.naming.provider.url = ejbd://127.0.0.1:4201

tec*_*zen 13

它没有抛出异常的原因是 - 访问资源时会出现ClassLoadException.

之所以发生这种情况,是因为正在通过从ResourceManager调用的ClassLoader搜索类:com.sun.jndi.url.jca.jcaURLContextFactory.

如果您将Factory名称更改为其他名称,那么您将看到NamingException - 但在查找的情况下,对于ClassNotFound/IllegalState等异常 - 不会引发异常.

因此需要分析ActiveMQ的依赖性.Update1:​​可能的原因之一是工厂对象只能在托管环境中实例化.您是否将代码作为应用程序客户端运行?

Update2:找到导致此行为的其他一些指针:

openejb jndi实现只暴露ejbs,而不是任何其他资源.如果您有一个j2ee应用程序客户端,并且您希望使用jms,则需要在客户端上部署activemq适配器的副本.然后,您可以使用j2ee java:comp/env上下文来查找您的内容.

在ActiveMQ网站上找到了这个:

ActiveMQ的JNDI实现不与命名服务器通信.它是JNDI客户端的精简版本,只允许直接从JMS实例获取主题和队列.因此,您必须提供JMS服务器地址,而不是提供命名服务器地址.大多数JNDI实现使用java.naming.provider.url属性来指定命名服务器的地址.ActiveMQ使用brokerURL.使用java.naming.provider.url将导致ActiveMQ尝试加载整个Broker.

详细了解如何使用JNDI进行连接:

解释中使用的初始上下文工厂是:org.apache.activemq.jndi.ActiveMQInitialContextFactory

可以在此处找到一些使用JNDI进行测试的示例代码

我写了一个简单的java客户端 - 注意提供者url下面是正在使用的brokerURL.

    Properties props = new Properties();            
props.put(Context.INITIAL_CONTEXT_FACTORY,
             "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
    //props.put(Context.PROVIDER_URL,"vm://localhost");//Either this or below
    props.put(Context.PROVIDER_URL,"tcp://localhost:65432"); 
    props.put("queue.SendReceiveQueue",
         "org.apache.geronimo.configs/activemq-ra/JCAAdminObject/SendReceiveQueue");

    InitialContext context = new InitialContext(props);   
    QueueConnectionFactory connectionFactory = (QueueConnectionFactory)context.lookup
                                                               ("ConnectionFactory");
    Queue q = (Queue) context.lookup("SendReceiveQueue");
    System.out.println("conn is : "  + connectionFactory.getClass().getName());
    System.out.println("queue is : " + q.getQueueName());
Run Code Online (Sandbox Code Playgroud)

该程序给出了输出:

conn是:org.apache.activemq.ActiveMQConnectionFactory队列是:org.apache.geronimo.configs/activemq-ra/JCAAdminObject/SendReceiveQueue