[java] How to use JNDI DataSource provided by Tomcat in Spring?

It is said that in the Spring javadoc article about DriverManagerDataSource class, that this class is very simple and that it is recommended

to use a JNDI DataSource provided by the container. Such a DataSource can be exposed as a DataSource bean in a Spring ApplicationContext via JndiObjectFactoryBean

The question is: how do I accomplish this?

For example, if I wish to have DataSource bean to access my custom MySQL database, what would I require then? What should I write in the context configuration, etc?

This question is related to java spring tomcat datasource jndi

The answer is


With Spring's JavaConfig mechanism, you can do it like so:

@Configuration
public class MainConfig {

    ...

    @Bean
    DataSource dataSource() {
        DataSource dataSource = null;
        JndiTemplate jndi = new JndiTemplate();
        try {
            dataSource = jndi.lookup("java:comp/env/jdbc/yourname", DataSource.class);
        } catch (NamingException e) {
            logger.error("NamingException for java:comp/env/jdbc/yourname", e);
        }
        return dataSource;
    }

}

According to Apache Tomcat 7 JNDI Datasource HOW-TO page there must be a resource configuration in web.xml:

<resource-ref>
  <description>DB Connection</description>
  <res-ref-name>jdbc/TestDB</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>

That works for me


In your spring class, You can inject a bean annotated like as

@Autowired
@Qualifier("dbDataSource")
private DataSource dataSource;

and You add this in your context.xml

<beans:bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <beans:property name="jndiName" value="java:comp/env/jdbc/MyLocalDB"/>
</beans:bean>

You can declare the JNDI resource in tomcat's server.xml using

<Resource name="jdbc/TestDB" 
  global="jdbc/TestDB" 
  auth="Container" 
  type="javax.sql.DataSource" 
  driverClassName="com.mysql.jdbc.Driver" 
  url="jdbc:mysql://localhost:3306/TestDB" 
  username="pankaj" 
  password="pankaj123" 

  maxActive="100" 
  maxIdle="20" 
  minIdle="5" 
  maxWait="10000"/>

back to context.xml de spring add this

<ResourceLink name="jdbc/MyLocalDB"
                global="jdbc/TestDB"
                auth="Container"
                type="javax.sql.DataSource" />

if, like this exmple you are injecting connection to database, make sure that MySQL jar is present in the tomcat lib directory, otherwise tomcat will not be able to create the MySQL database connection pool.


I found this solution very helpful in a clean way to remove xml configuration entirely.

Please check this db configuration using JNDI and spring framework. http://www.unotions.com/design/how-to-create-oracleothersql-db-configuration-using-spring-and-maven/

By this article, it explain how easy to create a db confguration based on database jndi(db/test) configuration. once you are done with configuration then all the db repositories are loaded using this jndi. I did find useful. If @Pierre has issue with this then let me know. It's complete solution to write db configuration.


Another feature: instead of of server.xml, you can add "Resource" tag in
your_application/META-INF/Context.xml (according to tomcat docs) like this:

<Context>
<Resource name="jdbc/DatabaseName" auth="Container" type="javax.sql.DataSource"
  username="dbUsername" password="dbPasswd"
  url="jdbc:postgresql://localhost/dbname"
  driverClassName="org.postgresql.Driver"
  initialSize="5" maxWait="5000"
  maxActive="120" maxIdle="5"
  validationQuery="select 1"
  poolPreparedStatements="true"/>
</Context>

Documentation: C.2.3.1 <jee:jndi-lookup/> (simple)

Example:

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource"/>

You just need to find out what JNDI name your appserver has bound the datasource to. This is entirely server-specific, consult the docs on your server to find out how.

Remember to declare the jee namespace at the top of your beans file, as described in C.2.3 The jee schema.


Assuming you have a "sampleDS" datasource definition inside your tomcat configuration, you can add following lines to your applicationContext.xml to access the datasource using JNDI.

<jee:jndi-lookup expected-type="javax.sql.DataSource" id="springBeanIdForSampleDS" jndi-name="sampleDS"/>

You have to define the namespace and schema location for jee prefix using:

xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to spring

Are all Spring Framework Java Configuration injection examples buggy? Two Page Login with Spring Security 3.2.x Access blocked by CORS policy: Response to preflight request doesn't pass access control check Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified Spring Data JPA findOne() change to Optional how to use this? After Spring Boot 2.0 migration: jdbcUrl is required with driverClassName The type WebMvcConfigurerAdapter is deprecated No converter found capable of converting from type to type

Examples related to tomcat

Jersey stopped working with InjectionManagerFactory not found The origin server did not find a current representation for the target resource or is not willing to disclose that one exists. on deploying to tomcat Spring boot: Unable to start embedded Tomcat servlet container Tomcat 404 error: The origin server did not find a current representation for the target resource or is not willing to disclose that one exists Spring Boot application in eclipse, the Tomcat connector configured to listen on port XXXX failed to start Kill tomcat service running on any port, Windows Tomcat 8 is not able to handle get request with '|' in query parameters? 8080 port already taken issue when trying to redeploy project from Spring Tool Suite IDE 403 Access Denied on Tomcat 8 Manager App without prompting for user/password Difference between Xms and Xmx and XX:MaxPermSize

Examples related to datasource

Spring Boot Configure and Use Two DataSources Configure DataSource programmatically in Spring Boot Unable to find the requested .Net Framework Data Provider in Visual Studio 2010 Professional How to use JNDI DataSource provided by Tomcat in Spring? Using a list as a data source for DataGridView Binding Combobox Using Dictionary as the Datasource How to connect to a MySQL Data Source in Visual Studio VB.NET: Clear DataGridView c# dictionary one key many values How do I manually configure a DataSource in Java?

Examples related to jndi

How to create JNDI context in Spring Boot with Embedded Tomcat Container Name [jdbc/mydb] is not bound in this Context Cannot create JDBC driver of class ' ' for connect URL 'null' : I do not understand this exception How to use JNDI DataSource provided by Tomcat in Spring? How do I connect to a Websphere Datasource with a given JNDI name? How to lookup JNDI resources on WebLogic? What does "javax.naming.NoInitialContextException" mean? Configure hibernate to connect to database via JNDI Datasource What is JNDI? What is its basic use? When is it used? What does java:comp/env/ do?