oracle-databasespring-bootjndiconnection-pool

How to configure DataSource for a Spring-Boot Application in a Standalone (war) and in an embedded Tomcat?


I have a Spring-Boot-Aplication with the following dependencyManagement:

<dependencyManagement>
  <dependencies>
    <dependency>
      <!-- Import dependency management from Spring Boot -->
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.1.5.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

and the following dependencies:

spring-boot-starter-jersey
spring-boot-starter-jdbc(exclusion:tomcat-jdbc) 
HikariCP(version:3.3.1)
ojdbc7

On Tomcat I configured a JNDI-Datasource as:

<Resource name="jdbc/myDS" 
  type="javax.sql.DataSource" 
  driverClassName="oracle.jdbc.driver.OracleDriver" 
  username="Superuser" 
  password="secret"
  url="jdbc:oracle:thin:@xxxDbX"      
  ../>

In the .properties-file I added the following properties:

spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource    
spring.datasource.jndi-name=jdbc/myDS

As Spring-Boot is able to configure a DataSource from the properties, I let it do so and I do write no extra code for a DataSource. Deployed in a Standalone Tomcat it works perfectly.

Logically Spring Boot can not find the JNDI-Resource in an embedded Tomcat and starting the application as a Spring-Boot-Application I got:

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'spring.datasource.type' to java.lang.Class<javax.sql.DataSource>:

    Property: spring.datasource.type
    Value: org.apache.tomcat.jdbc.pool.DataSource
    Origin: class path resource [application.properties]:12:24
    Reason: No converter found capable of converting from type [java.lang.String] to type [java.lang.Class<javax.sql.DataSource>]

Action:

Update your application's configuration

I would like to be able to start the application as a Spring-Boot-Application and also build a war-file which can be deployed in any Standalone Tomcat.

Is this possible by adding properties for a second DataSource in case the application is started as a Spring-Boot-Application or I am obliged to have a second .properties file?


Solution

  • The solution that worked for me is to add a custom-properties to use for the DataSource in the embedded Tomcat Server like so:

    # for a dedicated Tomcat
    spring.datasource.jndi-name=jdbc/dirserver
    
    
    # for the embedded Tomcat
    
    embedded.datasource.driver-class-name=oracle.jdbc.OracleDriver
    embedded.datasource.url=jdbc:oracle:thin:@//myServer:1521/xxxxx
    embedded.datasource.username=superuser
    embedded.datasource.password=topsecret
    

    and to define @Bean DataSource in the class annotated with @SpringBootApplication:

    @SpringBootApplication
    public class MySbApplication extends SpringBootServletInitializer {
    
      private static final Logger lg = LoggerFactory.getLogger(MySbApplication.class);
    
      @Value("${embedded.datasource.username}")
      String username;
      @Value("${embedded.datasource.password}")
      String password;
      @Value("${embedded.datasource.driver-class-name}")
      String driverClassName;
      @Value("${embedded.datasource.url}")
      String url;
    
      @Bean(destroyMethod = "")
      public DataSource oracledataSoutŕce() throws SQLException {
        final OracleDataSource dataSource = new OracleDataSource();
        dataSource.setUser(username);
        dataSource.setPassword(password);
        dataSource.setURL(url);
        dataSource.setImplicitCachingEnabled(true);
        dataSource.setFastConnectionFailoverEnabled(true);
        return dataSource;
      }
    }
    

    I willl add a link to a sample project in Github.