title: Mule-embedded: use the container's own jndiInitialFactory
body: <p>Consider the following mule configuration and having mule embedded in a Web (Java EE) Application:</p>
  
  <pre><code>&lt;jms:connector
          name="jmsConnector"
          connectionFactory-ref="jmsConnectionFactory"&gt; &lt;!-- From spring --&gt;
          &lt;!-- JNDI Name Resover here? --&gt;
  &lt;/jms:connector&gt;
  &lt;flow name="mainTestFlow"&gt;
      &lt;jms:inbound-endpoint connector-ref="jmsConnector" 
          queue="jms/MessageQueue" /&gt;
      &lt;logger level="INFO" category="mule.message.logging" message="Message arrived." /&gt;
  &lt;/flow&gt;
  </code></pre>
  
  <p>jmsConnectionFactory refers to a JMS Connection Factory defined in Spring, from:</p>
  
  <pre><code>&lt;bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
      &lt;property name="jndiName" value="jms/QueueConnectionFactory" /&gt;
  &lt;/bean&gt;
  </code></pre>
  
  <p>The Queue Connection Factory was tested and is working.</p>
  
  <p>The <strong>jms/MessageQueue</strong> queue name refers to a <strong>resource-ref</strong> defined in the web application <strong>web.xml</strong> file. This JNDI reference is bound at the container level to a <strong>javax.jms.Queue</strong> managed by the application server and connected to a proper messaging server (ActiveMQ, in this case).</p>
  
  <p>However, Mule doesn't treat the <strong>queue=""</strong> attribute as a JNDI destination, but as the queue name itself. So, when the above code is initialized, it actually creates a new queue in ActiveMQ named "jms/MessageQueue". What I really wanted was that it correctly retrieved the queue from the JNDI reference in the Web Application descriptor.</p>
  
  <p>Ok, you could say, all I had to do was to configure a JNDI Name Resolver at the JMS Connector and also add the <strong>jndiDestinations="true"</strong> and <strong>forceJndiDestinations="true"</strong> attributes to it.</p>
  
  <p>This is acceptable:</p>
  
  <pre><code>&lt;jms:default-jndi-name-resolver 
      jndiProviderUrl="tcp://localhost:1099"
      jndiInitialFactory="???"/&gt;
  </code></pre>
  
  <p>The real problem is that I don't want to place the real Initial Context Factory class name in the <strong>jndiInitialFactory</strong>, because it would fall into a container-specific definition. However, my application is sometimes deployed into JBoss 4.2.3, and sometimes, into WebSphere 7. Having 2 configurations and 2 EAR packages is not an option, due to our development process.</p>
  
  <p>Anyway, is it anyhow possible to either tell Mule-ESB to assume the current container (as it is in embedded mode) as the default JNDI Initial Factory for lookups or provide a "generic" JNDI Initial Factory that would recognize the container's JNDI environment? That shouldn't be a problem, because a web application can refer to it's container JNDI environment without additional (or even visible) configuration.</p>
  
  <p>If not possible, can I have my <strong>jms:inbound-endpoint</strong> refer to a <strong>javax.jms.Queue</strong> defined in Spring, just as the <strong>jms:connector</strong> does with the JMS Connection Factory? That would actually be rather elegant and clean, as Mule is Spring-friendly.</p>
  
  <p>Thank you all in advance!</p>
  
  <hr>
  
  <p><em><strong>Solution</em></strong></p>
  
  <p>After much thought and consideration, I finally solved my problem by creating a custom JndiNameResolver wired up to spring JNDI facilities (JndiTemplate, for instance). This is far from the best solution, but I found that to be the one that would least interfere and tamper with Mule's and Spring's inner intricacies.</p>
  
  <p>That said, here is the class:
      package com.filcobra.mule;</p>
  
  <pre><code>import javax.naming.NamingException;
  
  import org.mule.transport.jms.jndi.AbstractJndiNameResolver;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.beans.factory.InitializingBean;
  import org.springframework.jndi.JndiObjectLocator;
  import org.springframework.jndi.JndiTemplate;
  
  public class SpringJndiNameResolver extends AbstractJndiNameResolver implements InitializingBean {
      private static Logger logger = LoggerFactory.getLogger(SpringJndiNameResolver.class);
      private JndiTemplate jndiTemplate;
  
      @Override
      public void afterPropertiesSet() throws Exception {
          if (jndiTemplate == null) {
              jndiTemplate = new JndiTemplate();
          }
      }
  
      @Override
      public Object lookup(String name) throws NamingException {
          Object object = null;
          if (name != null) {
              logger.debug("Looking up name "+name);
              object = jndiTemplate.lookup(name);
              logger.debug("Object "+object+" found for name "+name);
          }
          return object;
      }
  
      public JndiTemplate getJndiTemplate() {
          return jndiTemplate;
      }
  
      public void setJndiTemplate(JndiTemplate jndiTemplate) {
          this.jndiTemplate = jndiTemplate;
      }
  }
  </code></pre>
  
  <p>With that, the configuration falls back into the usual:</p>
  
  <pre><code>&lt;spring:bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate" /&gt;
  
  &lt;jms:connector
          name="jmsConnector"
          connectionFactoryJndiName="java:comp/env/jms/MyConnectionFactory" &lt;!-- from Resource-Ref --&gt;
          jndiDestinations="true"
          forceJndiDestinations="true"
          specification="1.1" &gt;
  
      &lt;jms:custom-jndi-name-resolver class="com.filcobra.mule.SpringJndiNameResolver"&gt;
          &lt;spring:property name="jndiTemplate" ref="jndiTemplate"/&gt;
      &lt;/jms:custom-jndi-name-resolver&gt;    
  &lt;/jms:connector&gt;
  </code></pre>
  
  <p>With that, I was finally able to not have my Mule ESB installation tied up to a specific JMS vendor/implementation. In fact, the JMS (queues and factories) configuration is all left under the application server responsibility.</p>
  
  <p>Nevertheless, one thing remained odd. I expected that the JMS endpoints also used my Jndi Name Resolver in order to lookup the queue from a resource-reference, or its JNDI Name, the same way it did with the Connection Factory. That wouldn't work whatsoever. I finally worked around that by placing the queue name itself, as created in the JMS server:</p>
  
  <pre><code>&lt;flow name="mainTestFlow"&gt;
      &lt;jms:inbound-endpoint connector-ref="jmsConnector" queue="queue/myQueue"/&gt; &lt;!-- Queue Name, not JNDI Name --&gt;
  </code></pre>
  
  <p>That worked. So, I'm assuming the JMS Connector doesn't try and look up the queue, but simply uses the connection factory (looked up or not) to directly access the JMS Server.</p>
  
  <p>Regards!</p>