3

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?

Meziane
  • 1,586
  • 1
  • 12
  • 22
  • I believe you'll want to create a TomcatEmbeddedServletContainerFactory bean that sets up the JNDI when running on the Embedded Tomcat. I believe JNDI is disabled in embedded Tomcat By default. You need to call Tomcat.enableNaming() to enable it. While not a direct answer this question should help https://stackoverflow.com/questions/24941829/how-to-create-jndi-context-in-spring-boot-with-embedded-tomcat-container – Daniel Tung Jun 27 '19 at 08:38
  • As I wrote: Deployed in a Standalone Tomcat it works perfectly. I use the JNDI-Resource in the `Standalone Tomcat` just because I have to. For the `embedded Tomcat` I don't want to use JNDI: I just be able to start the application as a `Spring-Boot-Application` **without** having to code a *Datasource*. – Meziane Jun 27 '19 at 08:40
  • 1
    I forgot to say Thank you. Thank you [daniel-tung](https://stackoverflow.com/users/4623820/daniel-tung) – Meziane Jun 27 '19 at 08:46
  • The data source configuration you've setup only exists in the standalone Tomcat, you've setup the project to connect to the JNDI and it will attempt to do so on both the standalone and embedded Tomcat. If you don't configure the datasource for the embedded Tomcat your application will not start as it has to get the datasource configuration from somewhere. If you don't want to put your datasource configuration into the embedded Tomcat as a JNDI then I can't see how you'll be able to get the datasource information to both servers. – Daniel Tung Jun 27 '19 at 08:47
  • Yes that's my problem: I am trying to find a smart solution and avoid to code a Datasource for the `embedded Tomcat`. May be is it possible to add somme properties in the `.properties`-file, so that **Spring-Boot** can autoconfigure a `DataSource` for the `embedded Tomcat` with these properties as it does it for the `standalone Tomcat` – Meziane Jun 27 '19 at 08:51
  • I don't believe you can use property files just to configure a JNDI datasource just for the embedded Tomcat. By creating the bean I suggested the process would not run for the embedded Tomcat. It would mean compiling and deploying the project if the datasource changed but normally you'd do the same if your changed your properties file, though technically you could modify this and restart the application without deploying it. – Daniel Tung Jun 27 '19 at 08:55
  • [@daniel-tung](https://stackoverflow.com/users/4623820/daniel-tung): Once again I don't want to use JNDI in the `embedded Tomcat`. – Meziane Jun 27 '19 at 09:14

1 Answers1

1

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.

Meziane
  • 1,586
  • 1
  • 12
  • 22