当我配置两个数据源时,spring boot会抛出错误:
2015-04-10 10:01:50.750 INFO 8824 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat
2015-04-10 10:01:50.765 INFO 8824 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.0.20
2015-04-10 10:01:51.155 WARN 8824 --- [ost-startStop-1] o.a.catalina.core.NamingContextListener : Failed to register in JMX: javax.naming.NamingException: Could not create resource factory instance [Root exception is java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory]
pom.xml
包含以下条目:
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>qcom.cas.spring.reference.app</groupId>
<artifactId>spring-reference-app</artifactId>
<version>1.0-RELEASE</version>
</parent>
<artifactId>persistence</artifactId>
<name>persistence</name>
<packaging>jar</packaging>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
<gorm.version>1.1.0.RELEASE</gorm.version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.grails</groupId>
<artifactId>gorm-hibernate4-spring-boot</artifactId>
<version>${gorm.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
</dependencies>
</project>
应用程序属性文件包含:
myapp.db.jndi = java:comp/env/jdbc/myapp
pds.db.jndi = java:comp/env/jdbc/pds
// this is another team's DB. Will use select queries directly.
pds.jndi.factory = org.apache.commons.dbcp.BasicDataSourceFactory
pds.url = jdbc:mysql://pds.com:3306/test
pds.username = abc
pds.password = xyz
pds.driverClassName = com.mysql.jdbc.Driver
local.db.url = jdbc:mysql://localhost:3306/myapp
local.db.username = abc
local.db.password = xyz
local.db.driverClassName = com.mysql.jdbc.Driver
local.db.jndi.factory = org.apache.commons.dbcp.BasicDataSourceFactory
我已经定制了嵌入式tomcat,如下所示:
@Component
@Profile("local")
public class EmbeddedServerConfig implements EmbeddedServletContainerCustomizer {
@Value("${local.db.url}")
private String dbUrl;
@Value("${local.db.username}")
private String dbUserName;
@Value("${local.db.password}")
private String dbPassword;
@Value("${local.db.driverClassName}")
private String dbDriverClassName;
@Value("${local.db.jndi.factory}")
private String dbJNDIFactory;
@Value("${pds.jndi.factory}")
private String pdsJNDIFactory;
@Value("${pds.url}")
private String pdsUrl;
@Value("${pds.username}")
private String pdsUserName;
@Value("${pds.password}")
private String pdsPassword;
@Value("${pds.driverClassName}")
private String pdsDriverClassName;
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(9000);
}
@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
return new TomcatEmbeddedServletContainerFactory() {
@Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
tomcat.enableNaming();
TomcatEmbeddedServletContainer container = super.getTomcatEmbeddedServletContainer(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 super.getTomcatEmbeddedServletContainer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
ContextResource appDBResource = new ContextResource();
appDBResource.setName("jdbc/myapp");
appDBResource.setType(DataSource.class.getName());
appDBResource.setProperty("factory", dbJNDIFactory);
appDBResource.setProperty("driverClassName", dbDriverClassName);
appDBResource.setProperty("url", dbUrl);
appDBResource.setProperty("username", dbUserName);
appDBResource.setProperty("password", dbPassword);
context.getNamingResources().addResource(appDBResource);
ContextResource pdsDBResource = new ContextResource();
pdsDBResource.setName("jdbc/pds");
pdsDBResource.setType(DataSource.class.getName());
appDBResource.setProperty("factory", pdsJNDIFactory);
pdsDBResource.setProperty("driverClassName", pdsDriverClassName);
pdsDBResource.setProperty("url", pdsUrl);
pdsDBResource.setProperty("username", pdsUserName);
pdsDBResource.setProperty("password", pdsPassword);
context.getNamingResources().addResource(pdsDBResource);
}
};
}
@Configuration
@EnableJpaRepositories(basePackages = {"qcom.cas.myapp.repo" })
public class PersistenceConfig {
private final String entityPackages = "qcom.cas.myapp";
@Value("${hibernate.mysql.dialect}")
private String dialect;
@Value("${hibernate.hbm2ddl.auto}")
private String ddl;
@Value("${hibernate.ejb.naming_strategy}")
private String naming;
@Value("${hibernate.show_sql}")
private String showSql;
@Value("${hibernate.format_sql}")
private String formatSql;
@Value("${myapp.db.jndi}")
private String appDB;
private static final Logger log = Logger.getLogger(PersistenceConfig.class);
@Bean
@Primary
public DataSource dataSource() throws IllegalArgumentException, NamingException {
log.info("Setting up application data source");
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName(appDB);
bean.setLookupOnStartup(false);
bean.setProxyInterface(DataSource.class);
bean.setResourceRef(true);
bean.afterPropertiesSet();
return (DataSource) bean.getObject();
}
@Bean(name = "entityManagerFactory")
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory( ) throws IllegalArgumentException, NamingException {
log.info("Setting up entity manager factory");
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPackagesToScan(entityPackages);
entityManagerFactoryBean.setPersistenceUnitName("myapp");
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setJpaProperties(getJpaProperties());
return entityManagerFactoryBean;
}
private Properties getJpaProperties() {
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.dialect", dialect);
jpaProperties.put("hibernate.hbm2ddl.auto", ddl);
jpaProperties.put("hibernate.ejb.naming_strategy", naming);
jpaProperties.put("hibernate.show_sql", showSql);
jpaProperties.put("hibernate.format_sql", formatSql);
return jpaProperties;
}
}
@Configuration
public class PdsConfig {
private static final Logger log = Logger.getLogger(PdsConfig.class);
@Value("${pds.db.jndi}")
private String pdsDB;
@Bean(name="pdsDataSource")
public DataSource pdsDataSource() throws IllegalArgumentException, NamingException {
log.info("Setting up PDS data source.");
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName(pdsDB);
bean.setLookupOnStartup(false);
bean.setProxyInterface(DataSource.class);
bean.setResourceRef(true);
bean.afterPropertiesSet();
return (DataSource) bean.getObject();
}
}
如果我只使用1个数据源,那么app运行正常。
当我尝试访问第二个数据源时,下面是完整的堆栈跟踪:
2015-04-10 15:56:37.886 ERROR 7588 --- [nio-9000-exec-1] o.a.c.c.C.[.[.[/].[jerseyServlet] : Servlet.service() for servlet [jerseyServlet] in context with path [] threw exception [org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.NamingException: Could not create resource factory instance [Root exception is java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory]] with root cause
java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:191)
at org.apache.naming.factory.ResourceFactory.getDefaultFactory(ResourceFactory.java:47)
at org.apache.naming.factory.FactoryBase.getObjectInstance(FactoryBase.java:90)
at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:321)
at org.apache.naming.NamingContext.lookup(NamingContext.java:841)
at org.apache.naming.NamingContext.lookup(NamingContext.java:152)
at org.apache.naming.NamingContext.lookup(NamingContext.java:829)
at org.apache.naming.NamingContext.lookup(NamingContext.java:152)
at org.apache.naming.NamingContext.lookup(NamingContext.java:829)
at org.apache.naming.NamingContext.lookup(NamingContext.java:152)
at org.apache.naming.NamingContext.lookup(NamingContext.java:829)
at org.apache.naming.NamingContext.lookup(NamingContext.java:166)
at org.apache.naming.SelectorContext.lookup(SelectorContext.java:157)
at javax.naming.InitialContext.lookup(InitialContext.java:411)
at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:155)
at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:179)
at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95)
at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:106)
at org.springframework.jndi.JndiObjectTargetSource.getTarget(JndiObjectTargetSource.java:135)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:187)
at com.sun.proxy.$Proxy62.getConnection(Unknown Source)
at groovy.sql.Sql$36.run(Sql.java:4165)
at groovy.sql.Sql$36.run(Sql.java:4163)
at java.security.AccessController.doPrivileged(Native Method)
at groovy.sql.Sql.createConnection(Sql.java:4163)
at groovy.sql.Sql$AbstractQueryCommand.execute(Sql.java:4548)
at groovy.sql.Sql.rows(Sql.java:1954)
at groovy.sql.Sql.firstRow(Sql.java:2192)
at groovy.sql.Sql.firstRow(Sql.java:2230)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:189)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
at qcom.cas.myapp.service.pds.PdsService.getUserDetails(PdsService.groovy:27)
at qcom.cas.myapp.api.PdsResource.user(PdsResource.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:151)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:172)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:195)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:384)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:342)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:101)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:254)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1030)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:377)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:291)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:102)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration$MetricsFilter.doFilterInternal(MetricFilterAutoConfiguration.java:90)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
答案 0 :(得分:0)
我可以看到你正在使用jpa,如果你使用的是spring-boot,那么你可以使用spring-boot-starter-jpa
来自动配置你的数据源。您将需要额外的配置(请参阅此link)
添加此依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
答案 1 :(得分:0)
可以通过在类路径中添加以下jar来解决此问题: