Good morning in my timezone
I already have follow this two Stack Overflow questions :
Spring Boot Using Embedded Tomcat with JNDI
and
Howto use JNDI database connection with Spring Boot and Spring Data using embedded Tomcat?
And none have worked. I am using Spring Boot 2. I want to configure embedded Tomcat Server to work with JNDI. I have try to approaches :
Snippet of code :
@SpringBootApplication
public class MyApplication {
public static void main ...
@Bean
public ServletWebServerFactory servletContainer() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
resource.setName("jdbc/CCC");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
resource.setProperty("url", "jdbc:oracle:thin:@a77k11111188.tt.ddd.test:3000:BHJR00TT00");
resource.setProperty("username", "user");
resource.setProperty("password", "pass");
context.getNamingResources().addResource(resource); }
@Override
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat){
tomcat.enableNaming();
TomcatWebServer container = super.getTomcatWebServer(tomcat);
for(Container child :container.getTomcat().getHost().findChildren()){
if (child instanceof Context) {
ClassLoader contextClassLoader = ((Context)child).getLoader().getClassLoader();
Thread.currentThread().setContextClassLoader(contextClassLoader);
break;
}
}
return container; }
}; return tomcat;
An then use the application.properties
spring.datasource.jndi-name=java:comp/env/jdbc/CCC
Error log:
Unable to start embedded Tomcat
Error creating bean with name 'servletEndpointRegistrar'
Error creating bean with name 'dataSource'
DataSourceLookupFailureException: Failed to look up JNDI DataSource with name 'java:comp/env/jdbc/CCC'
.NamingException: Could not create resource factory instance
ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory
Instead if i not use the application properties and i configure the datasource bean directly in the Spring Boot Application like this
@Bean(destroyMethod = "")
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("java:comp/env/jdbc/CCC");
bean.setProxyInterface(DataSource.class);
bean.setLookupOnStartup(false);
bean.afterPropertiesSet();
return (DataSource) bean.getObject();
}
The error log
UnsatisfiedDependencyException: Error creating bean with name 'entityManagerFactory'
BeanCreationException: Error creating bean with name 'jpaVendorAdapter'
JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object
NamingException: Could not create resource factory instance
In my pom i have the following dependecies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc7</artifactId>
<version>12.1.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
I am out of solutions Thanks in advance Best regards
I was also facing the same issue and most of the example on internet was using
TomcatEmbeddedServletContainerFactory
however after trying several things finally i was able to get jndi connection in my application.
I am still figuring out exact root cause of the problem but following is the code for your reference.
@SpringBootApplication
public class MybatisJNDISampleApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisJNDISampleApplication.class, args);
}
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected TomcatWebServer getTomcatWebServer(org.apache.catalina.startup.Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatWebServer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
//resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
resource.setName("jdbc/myDatasourceName");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "oracle.jdbc.OracleDriver");
resource.setProperty("url", "db_url");
resource.setProperty("username", "db_username");
resource.setProperty("password", "db_password");
context.getNamingResources().addResource(resource);
}
};
}
}
Following is my configuration class :
@Configuration
@MapperScan("com.sample.mybatis")
public class DataConfig {
public final String MAPPER_LOCATIONS_PATH = "classpath:mybatis-mappers/*.xml";
@Bean(destroyMethod="")
public DataSource dataSource() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("java:comp/env/jdbc/myDatasourceName");
//bean.setResourceRef(true); // this was previously uncommented
bean.setProxyInterface(DataSource.class);
//bean.setLookupOnStartup(false); // this was previously uncommented
bean.afterPropertiesSet();
return (DataSource)bean.getObject();
}
@Bean
public DataSourceTransactionManager transactionManager() throws NamingException {
return new DataSourceTransactionManager(dataSource());
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
configureSqlSessionFactory(sessionFactory, dataSource());
return sessionFactory.getObject();
}
public void configureSqlSessionFactory(SqlSessionFactoryBean sessionFactoryBean, DataSource dataSource) throws IOException {
PathMatchingResourcePatternResolver pathResolver = new PathMatchingResourcePatternResolver();
sessionFactoryBean.setDataSource(dataSource);
sessionFactoryBean.setMapperLocations(pathResolver.getResources(MAPPER_LOCATIONS_PATH));
}
}
Hope this helps you to resolve your issue.