ActiveMQ will work with any JNDI provider capable of storing Java objects.

However it is common to require a JNDI initial context to be able to run many JMS example programs, like Sun's JMS tutorial

So we provide a simple JNDI InitialContextFactory which can be used to lookup JMS connection factory objects as well as Destination objects.

For example if you place this jndi.properties file on your classpath, you can look inside the InitialContext and lookup ConnectionFactory objects and Destinations etc.


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

# use the following property to configure the default connector
java.naming.provider.url = vm://localhost

# use the following property to specify the JNDI name the connection factory
# should appear as. 
#connectionFactoryNames = connectionFactory, queueConnectionFactory, topicConnectionFactry

# register some queues in JNDI using the form
# queue.[jndiName] = [physicalName]
queue.MyQueue = example.MyQueue


# register some topics in JNDI using the form
# topic.[jndiName] = [physicalName]
topic.MyTopic = example.MyTopic

You can edit the jndi.properties file to configure the ActiveMQConnectionFactory's properties such as brokerURL and whether or not there should be an embedded broker etc. See how to embed a broker in a connection for more details.

ActiveMQ JNDI Tutorial

This is a quick one page tutorial on how to setup and use JNDI to create a connection to ActiveMQ. The first thing is ActiveMQ does not provide a full JNDI server. This means JMS clients need to use properties files to create a jndi IntialContextFactory. If you need an example properties file, you can look the source distribution http://svn.apache.org/viewvc/activemq/trunk/activemq-core/src/test/resources/jndi.properties?view=markup. Before we proceed, here are the properties.

Name Value
java.naming.factory.initial org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url tcp://hostname:61616
topic.MyTopic example.MyTopic

Sample code

// create a new intial context, which loads from jndi.properties file
javax.naming.Context ctx = new javax.naming.InitialContext();
// lookup the connection factory
javax.jms.TopicConnectionFactory factory = (javax.jms.TopicConnectionFactory)ctx.lookup("ConnectionFactory");
// create a new TopicConnection for pub/sub messaging
javax.jms.TopicConnection conn = factory.getTopicConnection();
// lookup an existing topic
javax.jms.Topic mytopic = (javax.jms.Topic)ctx.lookup("MyTopic");
// create a new TopicSession for the client
javax.jms.TopicSession session = conn.createTopicSession(false,TopicSession.AUTO_ACKNOWLEDGE);
// create a new subscriber to receive messages
javax.jms.TopicSubscriber subscriber = session.createSubscriber(mytopic);

Notice the name of the topic in the sample is "MyTopic". ActiveMQ will read the jndi.properties files and creates the topics and queues in a lazy fashion. The prefix topic and queue is stripped, so the jndi name begins after the prefix.

Once you have the jndi.properties edited and ready, it needs to be accessible to your application. The easiest way is to add jndi.properties to a jar file. When "new InitialContext()" is called, it will scan the resources and find the file. If you get "javax.naming.NamingException", it usually means the jndi.properties file is not accessible.

You can also try to create a new initial context using either an instance of properties file or a map. For example, the approach recommended by JMS specification will work just fine.

Example recommended by specification
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
props.setProperty(Context.PROVIDER_URL,"tcp://hostname:61616");
javax.naming.Context ctx = new InitialContext(props);||

Dynamically creating destinations

For the easiest possible configuration with JNDI based programs, there are 2 dynamic contexts as follows

which allows you to lookup queues and topics using JNDI without any configuration.

e.g. if you use the following name to lookup into JNDI

dynamicQueues/FOO.BAR

you will get back an ActiveMQQueue of the name "FOO.BAR".

This can be very handy if you can easily reconfigure the JNDI name to use to lookup something in JNDI, but don't want to have to double configure a jndi.properties to matchup.

Working with embedded brokers

It is often useful to use an embedded broker in the same JVM as the JMS client. For this see How do I embed a Broker inside a Connection.

If you want to use an embedded broker with your JNDI provider you can just use the VM Transport to connect to the broker in your URL. e.g. to create a purely in JVM broker use this URI

vm://locahost

If you want to customize the broker use something like this

vm:broker:(tcp://localhost:61616)

More options are available in the VM Transport Reference

Example Java code

Once you have configured JNDI on the classpath you can run any normal JMS application such as the following example. Notice that the Java code just uses pure JMS APIs and is not in any way ActiveMQ specific


import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A simple polymorphic JMS producer which can work with Queues or Topics which
 * uses JNDI to lookup the JMS connection factory and destination
 * 
 * 
 */
public final class SimpleProducer {

    private static final Logger LOG = LoggerFactory.getLogger(SimpleProducer.class);

    private SimpleProducer() {
    }

    /**
     * @param args the destination name to send to and optionally, the number of
     *                messages to send
     */
    public static void main(String[] args) {
        Context jndiContext = null;
        ConnectionFactory connectionFactory = null;
        Connection connection = null;
        Session session = null;
        Destination destination = null;
        MessageProducer producer = null;
        String destinationName = null;
        final int numMsgs;

        if ((args.length < 1) || (args.length > 2)) {
            LOG.info("Usage: java SimpleProducer <destination-name> [<number-of-messages>]");
            System.exit(1);
        }
        destinationName = args[0];
        LOG.info("Destination name is " + destinationName);
        if (args.length == 2) {
            numMsgs = (new Integer(args[1])).intValue();
        } else {
            numMsgs = 1;
        }

        /*
         * Create a JNDI API InitialContext object
         */
        try {
            jndiContext = new InitialContext();
        } catch (NamingException e) {
            LOG.info("Could not create JNDI API context: " + e.toString());
            System.exit(1);
        }

        /*
         * Look up connection factory and destination.
         */
        try {
            connectionFactory = (ConnectionFactory)jndiContext.lookup("ConnectionFactory");
            destination = (Destination)jndiContext.lookup(destinationName);
        } catch (NamingException e) {
            LOG.info("JNDI API lookup failed: " + e);
            System.exit(1);
        }

        /*
         * Create connection. Create session from connection; false means
         * session is not transacted. Create sender and text message. Send
         * messages, varying text slightly. Send end-of-messages message.
         * Finally, close connection.
         */
        try {
            connection = connectionFactory.createConnection();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            producer = session.createProducer(destination);
            TextMessage message = session.createTextMessage();
            for (int i = 0; i < numMsgs; i++) {
                message.setText("This is message " + (i + 1));
                LOG.info("Sending message: " + message.getText());
                producer.send(message);
            }

            /*
             * Send a non-text control message indicating end of messages.
             */
            producer.send(session.createMessage());
        } catch (JMSException e) {
            LOG.info("Exception occurred: " + e);
        } finally {
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                }
            }
        }
    }
}