Spring Boot still requires resource-ref in web.xml

3.1k views Asked by At

Looking into Spring Boot right now and want to do it properly, as using Java config and ultimately without any web.xml. So, the tricky part is that the production environment requires a classic WAR file.

Hence, I'm specified WAR packaging within my Maven pom.xmlfile and the main Application class extends SpringBootServletInitializer.

Works just fine. Now, the tricky part is that in the production environment the Datasource is provisioned via JNDI. In a classic Spring app you would reference this dependency in the web.xml using a resource-ref as follows:

 <resource-ref>
    <res-ref-name>jdbc/DefaultDB</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
</resource-ref>

All the research I did seems to indicate that I would be able to get rid of the web.xml and replacing it with a respective context.xml file (in META-INF folder):

   <Resource name="jdbc/DefaultDB"
          auth="Container"
          type="javax.sql.DataSource"
          factory="com.sap.jpaas.service.persistence.core.JNDIDataSourceFactory"/>

Unfortunately that doesn't work :/

The interesting thing though is that a plain servlet3 web app works just fine that way, see [https://github.com/steinermatt/servlet3-sample].

So, I'm tempted to believe that the root cause it doesn't work for a Spring Boot app is related to the Spring Boot bootstrapping process... so, really looking for any hints, suggestions on what it could be!!!

Any help is appreciated!

1

There are 1 answers

0
Neha Prakash On

By default, JNDI is disabled in embedded Tomcat.

You could use following code to enable JNDI in tomcat. Following code will help you initialize DataSource spring bean.

    @Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
    return new TomcatEmbeddedServletContainerFactory() {

        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
                Tomcat tomcat) {
            tomcat.enableNaming();
            return super.getTomcatEmbeddedServletContainer(tomcat);
        }

        @Override
        protected void postProcessContext(Context context) {
            ContextResource resource = new ContextResource();
            resource.setName("jdbc/myDataSource");
            resource.setType(DataSource.class.getName());
            resource.setProperty("driverClassName", "your.db.Driver");
            resource.setProperty("url", "jdbc:yourDb");

            context.getNamingResources().addResource(resource);
        }
    };
}

You could use DataSource bean in your controller using auto-wiring.

@Autowired
private DataSource dataSource;