【发布时间】:2015-12-11 21:47:55
【问题描述】:
我现在承认,在我尝试使用 JNDI 数据源创建一个带有嵌入式 Tomcat(并且可部署到实际 Tomcat)的 Spring Boot 应用程序时,我已经断断续续地阅读了许多问题、答案和网站。多次失败后,我开始认为这根本不可能,这只是一个大阴谋!
在我永远放弃之前的最后一次尝试中,我现在要问:你到底是怎么做到的?
这是我目前所拥有的: 我的主要课程:
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class FinanceApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(FinanceApplication.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();
resource.setName("jdbc/finance");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "com.mysql.jdbc.Driver");
resource.setProperty("url", "jdbc:mysql://localhost:3306/finance");
resource.setProperty("username", "xxxx");
resource.setProperty("password", "yyyy");
context.getNamingResources().addResource(resource);
}
};
}
@Bean(destroyMethod="")
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("java:comp/env/jdbc/finance");
bean.setProxyInterface(DataSource.class);
bean.setLookupOnStartup(false);
bean.afterPropertiesSet();
return (DataSource)bean.getObject();
}
}
我的 Servlet 配置(基于 java):
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(FinanceApplication.class);
}
}
我使用的是 Maven,我的 pom.xml 是基于 this one
问题:
当我在 Eclipse 中运行它时,我得到了这些异常(切入正题):
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean]: Factory method 'entityManagerFactory' threw exception; nested exception is org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.NameNotFoundException: Name [comp/env/jdbc/finance] is not bound in this Context. Unable to find [comp].
当我使用 Maven 部署到独立的 Tomcat 实例时,我得到了这个异常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean]: Factory method 'entityManagerFactory' threw exception; nested exception is org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1119)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1014)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:956)
...
【问题讨论】:
-
我之前没有在 Spring Boot 中使用过 JNDI,所以我真的帮不上忙(很抱歉 :( 但我确实有一个问题。既然您使用的是嵌入式 Tomcat,为什么要使用 JNDI?为什么不使用标准的 Spring Boot 约定来设置数据源?它会为你省去很多麻烦
-
它应该通过嵌入式和单独的 Tomcat 实例工作。仍然没有找到答案。我认为这是不可能的。
-
我建议您使用 Spring Profiles。当嵌入式配置文件处于活动状态时,将根据属性文件配置数据源。启用经典配置文件后,您可以使用 Spring Boot 的 JNDI 自动配置。看看here
标签: java maven tomcat spring-boot jndi