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
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
I have a somewhat equivalent configuration Tomcat/Geronimo J2EE jar / Geronimo JMS Jar / ActiveMQ 4 And i'm a little bit confused about your jndi.propertie file. Mine looks like this :
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url = tcp://localhost:61616
connectionFactoryNames = connectionFactory , TopicConnectionFactory
The big difference is obviousely that your initial context is remote. Beside that, i must provide a connectionFactoryNames, or i get a NamingException.
I don't know why, but for me, using a context didn't work. It seems that the message is sent, but the onMessage of my consumer is not called.
Using a context don't throw exception but don't work :
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);
}
}
Using the code below ( without context ) works well :
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With