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
JPA Configuration – Model, DAO and Service. With this, you have everything you need in order to use your JNDI datasource in your Spring application.
To configure your own DataSource , define a @Bean of that type in your configuration. Spring Boot reuses your DataSource anywhere one is required, including database initialization. If you need to externalize some settings, you can bind your DataSource to the environment (see “Section 25.8.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With