| <div class="wiki-content maincontent"><p>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 <a shape="rect" class="external-link" href="http://java.sun.com/products/jms/tutorial/1_3_1-fcs/doc/jms_tutorialTOC.html" rel="nofollow">Sun's JMS tutorial.</a></p><p>So we provide a simple JNDI <strong><code>InitialContextFactory</code></strong> which can be used to lookup JMS connection factory objects as well as Destination objects. For example if you place this <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/activemq/trunk/activemq-unit-tests/src/test/resources/jndi.properties">jndi.properties</a> file on your classpath, you can look inside the <strong><code>InitialContext</code></strong> and lookup <strong><code>ConnectionFactory</code></strong> objects and <strong><code>Destinations</code></strong> etc.</p><plain-text-body>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</plain-text-body><p>You can edit the <strong><code>jndi.properties</code></strong> file to configure the <strong><code>ActiveMQConnectionFactory</code></strong>'s properties such as <strong><code>brokerURL</code></strong> and whether or not there should be an embedded broker etc. See <a shape="rect" href="how-do-i-embed-a-broker-inside-a-connection.xml">how to embed a broker in a connection</a> for more details.</p><h3 id="JNDISupport-ActiveMQJNDITutorial">ActiveMQ JNDI Tutorial</h3><p>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 <strong><code>IntialContextFactory</code></strong>. If you need an example properties file, you can look the source distribution <a shape="rect" class="external-link" href="https://github.com/apache/activemq/blob/master/activemq-unit-tests/src/test/resources/jndi.properties" rel="nofollow">https://github.com/apache/activemq/blob/master/activemq-unit-tests/src/test/resources/jndi.properties</a>. Before we proceed, here are the properties.</p><div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Name</p></th><th colspan="1" rowspan="1" class="confluenceTh"><p>Value</p></th></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><code>java.naming.factory.initial</code></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><code>org.apache.activemq.jndi.ActiveMQInitialContextFactory</code></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><code>java.naming.provider.url</code></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><code>tcp://hostname:61616</code></p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p><code>topic.MyTopic</code></p></td><td colspan="1" rowspan="1" class="confluenceTd"><p><code>example.MyTopic</code></p></td></tr></tbody></table></div><p>Make sure to add <strong><code>activemq-<em><version></em>.jar</code></strong> and <strong><code>spring-1.x.jar</code></strong> to your classpath. If the libraries are not in the classpath, you will get a <strong><code>ClassNotFoundException</code></strong> at runtime. If you get <strong><code>ClassNotFoundException</code></strong>, try printing out the classpath and check it is present. You can also run ActiveMQ with <strong><code>-verbose</code></strong> option to verify the jar was loaded correctly.</p><p><strong>Sample Code</strong></p><parameter ac:name="language">java</parameter><plain-text-body>// 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); |
| </plain-text-body><p>Notice the name of the topic in the sample is <strong><code>MyTopic</code></strong>. ActiveMQ will read the <strong><code>jndi.properties</code></strong> 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.</p><p>Once you have the <strong><code>jndi.properties</code></strong> edited and ready, it needs to be accessible to your application. The easiest way is to add <strong><code>jndi.properties</code></strong> to a jar file. When <strong><code>new InitialContext()</code></strong> is called, it will scan the resources and find the file. If you get <strong><code>javax.naming.NamingException</code></strong>, it usually means the <strong><code>jndi.properties</code></strong> file is not accessible.</p><p>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.</p><div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Example Recommended by Specification</p></th></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><parameter ac:name="language">java</parameter><plain-text-body>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);|| |
| </plain-text-body></td></tr></tbody></table></div><p>If ActiveMQ is embedded within an EJB container, you will need to look at the containers documentation for the correct JNDI values.</p><h3 id="JNDISupport-DynamicallyCreatingDestinations">Dynamically Creating Destinations</h3><p>For the easiest possible configuration with JNDI based programs, there are two dynamic contexts, namely:</p><ul><li><strong><code>dynamicQueues</code></strong></li><li><strong><code>dynamicTopics</code></strong></li></ul><p>These allow you to lookup queues and topics using JNDI without any configuration.</p><p>For example, if you use the following name to lookup into JNDI:</p><plain-text-body>dynamicQueues/FOO.BAR |
| </plain-text-body><p>you will get back an <strong><code>ActiveMQQueue</code></strong> of the name <strong><code>FOO.BAR</code></strong>. 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 <strong><code>jndi.properties</code></strong> to match.</p><h3 id="JNDISupport-WorkingWithEmbeddedBrokers">Working With Embedded Brokers</h3><p>It is often useful to use an embedded broker in the same JVM as the JMS client. For this see <a shape="rect" href="how-do-i-embed-a-broker-inside-a-connection.xml">How do I embed a Broker inside a Connection</a>.</p><p>If you want to use an embedded broker with your JNDI provider you can just use the <a shape="rect" href="vm-transport-reference.xml">VM Transport</a> to connect to the broker in your URL. e.g. to create a purely in JVM broker use this URI</p><plain-text-body>vm://locahost |
| </plain-text-body><p>If you want to customize the broker use something like this:</p><plain-text-body>vm:broker:(tcp://localhost:61616) |
| </plain-text-body><p>More options are available in the <a shape="rect" href="vm-transport-reference.xml">VM Transport Reference</a></p><h3 id="JNDISupport-ExampleJavaCode">Example Java Code</h3><p>Once you have configured JNDI on the classpath you can run any normal JMS application such as the following <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/incubator/activemq/trunk/activemq-unit-tests/src/test/java/org/apache/activemq/demo/SimpleProducer.java">example</a>. Notice that the Java code just uses pure JMS APIs and is not in any way ActiveMQ specific</p><parameter ac:name="language">java</parameter><plain-text-body>/** |
| * The SimpleQueueSender class consists only of a main method, |
| * which sends several messages to a queue. |
| * |
| * Run this program in conjunction with SimpleQueueReceiver. |
| * Specify a queue name on the command line when you run the |
| * program. By default, the program sends one message. Specify |
| * a number after the queue name to send that number of messages. |
| */ |
| package org.apache.activemq.demo; |
| |
| 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; |
| ConnectionFactory connectionFactory; |
| Connection connection; |
| Session session; |
| Destination destination; |
| MessageProducer producer; |
| String destinationName; |
| 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 the 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 ignored) {} |
| } |
| } |
| } |
| } |
| </plain-text-body></div> |
| |