My symptoms are similar to: How to create JNDI context in Spring Boot with Embedded Tomcat Container
I've created a github repo recreating my issue: https://github.com/Rkiouak/spring-boot-embedded-tomcat-hibernate-jndi (Note you may need to manually add the oracle dependency as oracle prevents the posting of its jars to public maven repos)
cloning the repo, cding into it and mvn clean && mvn package && java -jar target/spring-boot-sample-tomcat-jndi-0.1.0-SNAPSHOT.jar will reproduce the NameNotFound execption.
Can anyone help me understand what configuration needs to change in order to use tomcat 8 and the most recent spring-boot version with jndi (possibly hibernate complicating things)?
Longer description of issue:
The solutions from previous answers have not worked for me, i suspect a dependency issue in newer versions OR something to do with how/when hibernate performs jndi look ups.
However, I have cloned https://github.com/wilkinsona/spring-boot-sample-tomcat-jndi, updated its spring boot dependencies to LATEST, updated the tomcat package/imports that result from this new version and move from Tomcat 7 to Tomcat 8 and gotten it running.
I suspect my issues is slightly different, though the exception manifesting is the same.
The exception I receive is:
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:244)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:208)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:217)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:83)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:418)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:87)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:692)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 47 more
Caused by: org.hibernate.engine.jndi.JndiException: Unable to lookup JNDI name [java:comp/env/jdbc/MyDataSource]
at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:100)
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.configure(DatasourceConnectionProviderImpl.java:98)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:217)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.buildJdbcConnectionAccess(JdbcEnvironmentInitiator.java:145)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:66)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:234)
... 65 more
Caused by: javax.naming.NameNotFoundException: Name [comp/env/jdbc/MyDataSource] is not bound in this Context. Unable to find [comp].
at org.apache.naming.NamingContext.lookup(NamingContext.java:818)
at org.apache.naming.NamingContext.lookup(NamingContext.java:152)
at org.apache.naming.SelectorContext.lookup(SelectorContext.java:134)
at javax.naming.InitialContext.lookup(Unknown Source)
at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:97)
... 74 more
I'm working on migrating a legacy Struts app to Spring MVC, preferably spring boot using embedded tomcat. Eventually I would plan to change these jndi resource lookups to (at least what I know as)traditionally defined datasources, but want to avoid that step at this point.
I'm importing an applicationContext.xml resource:
@Configuration
@ComponentScan
@EnableAutoConfiguration
@ImportResource("classpath:context/applicationContext.xml")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
return new TomcatEmbeddedServletContainerFactory() {
@Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatEmbeddedServletContainer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
ContextResourceLink resourceLink = new ContextResourceLink();
resource.setName("jdbc/MyDataSource");
resource.setProperty("global", "jdbc/MyDataSource");
resource.setType("javax.sql.DataSource");
resource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
resource.setProperty("url", "jdbc:yourDb");
resource.setAuth("Container");
context.getNamingResources().addResource(resource);
resourceLink.setName("jdbc/MyDataSource");
resourceLink.setType("javax.sql.DataSource");
resourceLink.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
resourceLink.setProperty("url", "jdbc:connectionString");
context.getNamingResources().addResourceLink(resourceLink);
System.out.println("\n\n\ncontext naming resources\n"+context.getResourceOnlyServlets()+"\n\n\n");
}
};
}
@Bean(destroyMethod="")
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {
System.out.println("\n\n\nIn jndiDataSource\n\n\n");
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("java:comp/env/jdbc/MyDataSource");
bean.setProxyInterface(oracle.jdbc.driver.OracleDriver.class);
bean.setLookupOnStartup(false);
bean.afterPropertiesSet();
return (DataSource)bean.getObject();
}
}
The resource applicationContext.xml references a hibernateContext.xml that references a hibernate.cfg.xml file that looks like:
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:comp/env/jdbc/MyDataSource</property>
<property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
<property name="show_sql">false</property>
<property name="format_sql">true</property>
<property name="hibernate.max_fetch_depth">2</property>
.....
I DO NOT see the println from the
@Bean(destroyMethod="")
public DataSource jndiDataSource()...
bean. I do see:
Name = MyDataSource Ignoring unknown property: value of "jdbc/MyDataSource" for "global" property
and recognize that isn't a valid or helpful setting, but was one of the things I tried.
Any help on identifying the 1) cause and 2) solution to this would be greatly appreciated-- I've not used JNDI resources previously, and the background with this application has been with WAS.
I've looked at most of the stack overflow questions that vaguely matched some combination of spring-boot, hibernate, jndi, name not found, and read through the tomcat resource definition documentation, but haven't been able to piece it together...
Please let me know if I've left out any