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

时间:2009-08-26 08:37:47

标签: java java-ee jms jndi geronimo

我试图通过Geronimo的JNDI查找QueueConnectionFactoryQueueQueue返回正常,但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);      
    }

}

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

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

4 个答案:

答案 0 :(得分: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 context to find   你的东西。   

在ActiveMQ网站上找到了这个:

  

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

详细了解如何Connect using JNDI

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

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

我写了一个简单的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());

该程序提供输出:

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

答案 1 :(得分:1)

我有一个等效的配置Tomcat / Geronimo J2EE jar / Geronimo JMS Jar / ActiveMQ 4 我对你的jndi.propertie文件有点困惑。 我看起来像这样:

java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory

java.naming.provider.url = tcp://localhost:61616

connectionFactoryNames = connectionFactory , TopicConnectionFactory

显而易见的是,您的初始背景是远程的。除此之外,我必须提供connectionFactoryNames,否则我会得到一个NamingException。

答案 2 :(得分:1)

我不知道为什么,但对我来说,使用上下文并不起作用。似乎邮件已发送,但我的消费者的onMessage未被调用。

使用上下文不会抛出异常但不起作用:

import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;

public class HelloClient {

public static void main(String[] args) throws Exception {
    Properties ppt2 = new Properties();
    ppt2.put(Context.INITIAL_CONTEXT_FACTORY,
            "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
    ppt2.put(Context.PROVIDER_URL, "tcp://localhost:61616");
    ppt2.put("topic.MessageDestinationTopic", "console.jms/TopicQueue/JCAAdminObject/MessageDestinationTopic");
    Context ctx2 = new InitialContext(ppt2);

    TopicConnectionFactory factory = (TopicConnectionFactory) ctx2.lookup("ConnectionFactory");
    TopicConnection connection = factory.createTopicConnection();
    TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
    Topic topic = (Topic) ctx2.lookup("MessageDestinationTopic");

    MessageProducer producer = session.createProducer(topic);

    TextMessage msg = session.createTextMessage();
    msg.setText("this is a test message");
    producer.send(msg);
    producer.close();
    session.close();
    System.out.println("Message published. Please check application server's console to see the response from MDB");
    ctx2.close();
    System.exit(0);

}

}

使用下面的代码(没有上下文)效果很好:

import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;

public class HelloClient {

    public static void main(String[] args) throws Exception {

        TopicConnectionFactory factory = new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616");
        TopicConnection connection = factory.createTopicConnection();
        TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
        Topic topic = session.createTopic("MessageDestinationTopic");

        MessageProducer producer = session.createProducer(topic);

        TextMessage msg = session.createTextMessage();
        msg.setText("this is a test message");
        producer.send(msg);
        producer.close();
        session.close();
        System.out.println("Message published. Please check application server's console to see the response from MDB");
        System.exit(0);

    }

}

答案 3 :(得分:0)

这里有两个参与者,你正在寻找JNDI的东西。别人不得不把它放在那里。我不知道你的环境的细节,但我对这些问题的处理方法是

  • 探索命名空间 - 那里有什么?你有任何JNDI浏览工具吗?
  • 在日志中查看应该向JNDI注册的服务,是否报告任何错误?