Why is my JNDI lookup for a QueueConnectionFactory returning null?

Simon Nickerson picture Simon Nickerson · Aug 26, 2009 · Viewed 36.4k times · Source

I am trying to look up a QueueConnectionFactory and Queue via Geronimo's JNDI. The Queue gets returned fine, but the QueueConnectionFactory lookup always returns null. It doesn't throw a NamingException, which is what I'd expect if the JNDI name was incorrect.

Can anyone see what I'm doing wrong? The test code below outputs:

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

}

In case it makes a difference: I've added openejb-client-3.0.1.jar, geronimo-ejb_3.0_spec-1.0.1.jar and activemq-core-4.1.2-G20090207.jar to my class path, and my jndi.properties file has the properties:

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

Answer

techzen picture techzen · Aug 30, 2009

The reason why it is not throwing an exception is that - there is a ClassLoadException that comes when the resource is accessed.

And the reason why that is happening because the class : com.sun.jndi.url.jca.jcaURLContextFactory is being searched for by the ClassLoader called from ResourceManager.

If you change the Factory name to some other name then you shall see the NamingException - but in the case of lookup , for Exceptions such as ClassNotFound/IllegalState - no exceptions are raised.

The dependencies of ActiveMQ thus need to be analysed. Update1: One of the possible reasons is that the factory object can only be instantiated in a managed environment. Are you running your code as an application client?.

Update2: Some other pointers found for the cause of this behavior:

the openejb jndi implementation only exposes ejbs, not any other resources. If you have a j2ee app client, and you wish to use jms, you need to deploy a copy of the activemq adapter on the client. You can then use the j2ee java:comp/env context to find your stuff.

Found this on ActiveMQ site:

ActiveMQ's JNDI Implementation does NOT talk to the naming server. It's a stripped down version of a JNDI client that just allows to get Topics and Queues directly from a JMS instance. So, instead of supplying the naming server address, you have to supply the JMS server address.Most JNDI implementations use the java.naming.provider.url property to specify the naming server's address. ActiveMQ uses the brokerURL one. Using the java.naming.provider.url one instead will result in ActiveMQ trying to load the whole Broker.

See more on how to Connect using JNDI:

The initial context factory used in the explanation is: org.apache.activemq.jndi.ActiveMQInitialContextFactory

Some sample code to test with JNDI can be found here

I wrote a simple java client - note below the provider url is the brokerURL that is being used.

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

This program gives the output:

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