title: How to create JNDI context in Spring Boot with Embedded Tomcat Container
body: <pre class="lang-java prettyprint-override"><code>import org.apache.catalina.Context;
  import org.apache.catalina.deploy.ContextResource;
  import org.apache.catalina.startup.Tomcat;
  import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
  import org.springframework.boot.builder.SpringApplicationBuilder;
  import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
  import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
  import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
  import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer;
  import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.ComponentScan;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.context.annotation.ImportResource;
  
  @Configuration
  @EnableAutoConfiguration
  @ComponentScan
  @ImportResource("classpath:applicationContext.xml")
  public class Application {
  
      public static void main(String[] args) throws Exception {
          new SpringApplicationBuilder()
                  .showBanner(false)
                  .sources(Application.class)
                  .run(args);
  }
  
  @Bean
  public TomcatEmbeddedServletContainerFactory tomcatFactory() {
      return new TomcatEmbeddedServletContainerFactory() {
          @Override
          protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
                  Tomcat tomcat) {
              tomcat.enableNaming();
              return super.getTomcatEmbeddedServletContainer(tomcat);
          }
      };
  }
  
  @Bean
  public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer() {
      return new EmbeddedServletContainerCustomizer() {
          @Override
          public void customize(ConfigurableEmbeddedServletContainer container) {
              if (container instanceof TomcatEmbeddedServletContainerFactory) {
                  TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory = (TomcatEmbeddedServletContainerFactory) container;
                  tomcatEmbeddedServletContainerFactory.addContextCustomizers(new TomcatContextCustomizer() {
                      @Override
                      public void customize(Context context) {
                          ContextResource mydatasource = new ContextResource();
                          mydatasource.setName("jdbc/mydatasource");
                          mydatasource.setAuth("Container");
                          mydatasource.setType("javax.sql.DataSource");
                          mydatasource.setScope("Sharable");
                          mydatasource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
                          mydatasource.setProperty("url", "jdbc:oracle:thin:@mydomain.com:1522:myid");
                          mydatasource.setProperty("username", "myusername");
                          mydatasource.setProperty("password", "mypassword");
  
                          context.getNamingResources().addResource(mydatasource);
  
                      }
                  });
              }
          }
      };
  }
  </code></pre>
  
  <p>}</p>
  
  <p>I'm using spring boot and trying to startup with an embedded tomcat that creates a JNDI context for my datasources:</p>
  
  <pre class="lang-java prettyprint-override"><code>    &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-actuator&lt;/artifactId&gt;
          &lt;version&gt;1.1.4.RELEASE&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;
          &lt;version&gt;1.1.4.RELEASE&lt;/version&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.data&lt;/groupId&gt;
          &lt;artifactId&gt;spring-data-oracle&lt;/artifactId&gt;
          &lt;version&gt;1.0.0.RELEASE&lt;/version&gt;
      &lt;/dependency&gt;
  </code></pre>
  
  <p>If I remove the @ImportResource my application starts up just fine.  I can connect to the tomcat instance.  I can check all of my actuator endpoints.  Using JConsole, I can connect to the application I can see my datasource in the MBeans (Catalina -> Resource -> Context -> "/" -> localhost -> javax.sql.DataSource -> jdbc/mydatasource)</p>
  
  <p>I also have MBeans showing up, via JConsole, here (Tomcat -> DataSource -> / -> localhost -> javax.sql.DataSource -> jdbc/mydatasource)</p>
  
  <p>However, when I @ImportResource what is actually looking for mydatasource via JNDI, it's not finding it.</p>
  
  <pre class="lang-java prettyprint-override"><code>&lt;bean id="myDS" class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
      &lt;property name="jndiName" value="java:comp/env/jdbc/mydatasource"/&gt;
  &lt;/bean&gt;
  </code></pre>
  
  <p><em>The relevant part of my imported xml file</em></p>
  
  <p>The ContextResource that I'm configuring above is with the exact same parameters that I was using in the context.xml that is getting deployed when the application is deployed to a tomcat container.  My imported beans and my application are working properly when deployed to a tomcat container.</p>
  
  <p>So it appears that I have a context now, but it doesn't appear that the naming is right.  I've tried to various combinations of the resource name, but can't seem to generate a "comp" bound in this context.</p>
  
  <pre class="lang-java prettyprint-override"><code>Caused by: javax.naming.NameNotFoundException: Name [comp/env/jdbc/mydatasource] is not bound in this Context. Unable to find [comp].
      at org.apache.naming.NamingContext.lookup(NamingContext.java:819)
      at org.apache.naming.NamingContext.lookup(NamingContext.java:167)
      at org.apache.naming.SelectorContext.lookup(SelectorContext.java:156)
      at javax.naming.InitialContext.lookup(InitialContext.java:392)
      at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:155)
      at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
      at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
      at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:179)
      at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95)
      at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:106)
      at org.springframework.jndi.JndiObjectFactoryBean.lookupWithFallback(JndiObjectFactoryBean.java:231)
      at org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(JndiObjectFactoryBean.java:217)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
      ... 30 more
  </code></pre>