简体   繁体   English

使用 Springboot 通过 jndi 查找配置两个数据源

[英]Configuring two datasources by jndi lookup with Springboot

I have a small web app built with Spring Boot that has two datasources, (one for the application data, and one for retrieving user access information).我有一个使用 Spring Boot 构建的小型 Web 应用程序,它有两个数据源(一个用于应用程序数据,另一个用于检索用户访问信息)。 I have configured this successfully using a config class for each datasource and using datasource connection details in the application.properties file.我已经使用每个数据源的配置类并使用 application.properties 文件中的数据源连接详细信息成功地配置了它。

I am now trying to refactor this to use jndi lookup for the datasource details so that I can use the same approach locally as I'll use in dev/test and prod.我现在正在尝试重构它以使用 jndi 查找数据源详细信息,以便我可以在本地使用与在开发/测试和生产中使用的方法相同的方法。

I have amended my database config classes to use jndi lookup and am now running my app on the Pivotal tc Server provided in Spring Tool Suite.我已经修改了我的数据库配置类以使用 jndi 查找,现在我在 Spring Tool Suite 中提供的 Pivotal tc Server 上运行我的应用程序。

Currently I can see that one of the datasources is configured correctly (i return a record count from a table on application start up).目前我可以看到其中一个数据源配置正确(我在应用程序启动时从表中返回记录计数)。 However my second datasource does not appear to get configured correctly and I get an exception...但是,我的第二个数据源似乎没有正确配置,并且出现异常...

java.sql.SQLException: The url cannot be null
    at java.sql.DriverManager.getConnection(DriverManager.java:556) ~[na:1.7.0_40]
    at java.sql.DriverManager.getConnection(DriverManager.java:187) ~[na:1.7.0_40]
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:308) ~[tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203) ~[tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:716) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:648) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:468) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:143) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) [tomcat-jdbc-8.5.4.jar:na]
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) [spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) [spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:342) [spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection.isEmbedded(EmbeddedDatabaseConnection.java:139) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.getDefaultDdlAuto(JpaProperties.java:224) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.getOrDeduceDdlAuto(JpaProperties.java:212) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.getAdditionalProperties(JpaProperties.java:188) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.access$000(JpaProperties.java:129) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.getHibernateProperties(JpaProperties.java:126) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.isInitializingDatabase(DataSourceInitializedPublisher.java:80) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.postProcessAfterInitialization(DataSourceInitializedPublisher.java:68) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1723) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:113) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1600) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:254) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:634) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:448) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:299) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:129) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:207) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1214) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:207) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1214) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:776) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861) [spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) [spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:369) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:313) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.web.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:150) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.web.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:130) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.web.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:86) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5156) [catalina.jar:na]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:na]
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725) [catalina.jar:na]
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701) [catalina.jar:na]
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717) [catalina.jar:na]
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:586) [catalina.jar:8.0.26.B]
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1750) [catalina.jar:8.0.26.B]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [na:1.7.0_40]
    at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_40]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_40]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_40]
    at java.lang.Thread.run(Thread.java:724) [na:1.7.0_40]

My application.properties file has the following properties我的 application.properties 文件具有以下属性

spring.datasource.jndi-name=java:comp/env/jdbc/app_datasource
spring.datasource.expected-type=javax.sql.DataSource

security.datasource.jndi-name=java:comp/env/jdbc/security_datasource
security.datasource.expected-type=javax.sql.DataSource

My Database configuration classes look like this..我的数据库配置类看起来像这样..

@Configuration
@EnableConfigurationProperties
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
public class AppDBConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public JndiPropertyHolder primary() {
        return new JndiPropertyHolder();
    }

    @Bean(name = "app")
    @Primary
    public DataSource appDataSource() {
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        DataSource dataSource = dataSourceLookup.getDataSource(primary().getJndiName());
        return dataSource;
    }
}

@Configuration
@EnableConfigurationProperties
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
public class SecurityDBConfig {

    @Bean
    @ConfigurationProperties(prefix = "security.datasource")
    public JndiPropertyHolder security() {
        return new JndiPropertyHolder();
    }

    @Bean(name = "security")
    public DataSource securityDataSource() {
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        DataSource dataSource = dataSourceLookup.getDataSource(security().getJndiName());
        return dataSource;
    }
}

and the server.xml looks like this server.xml 看起来像这样

<?xml version="1.0" encoding="UTF-8"?>
<Server port="${base.shutdown.port}" shutdown="SHUTDOWN">
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
    <Listener className="com.springsource.tcserver.serviceability.deploy.TcContainerDeployer"/>
    <Listener accessFile="${catalina.base}/conf/jmxremote.access" address="127.0.0.1" authenticate="true" className="com.springsource.tcserver.serviceability.rmi.JmxSocketListener" passwordFile="${catalina.base}/conf/jmxremote.password" port="${base.jmx.port}" useSSL="false"/>
    <GlobalNamingResources>
        <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
    </GlobalNamingResources>
    <Service name="Catalina">
        <Executor maxThreads="300" minSpareThreads="50" name="tomcatThreadPool" namePrefix="tomcat-http--"/>
        <Engine defaultHost="localhost" name="Catalina">
            <Realm className="org.apache.catalina.realm.LockOutRealm">
                <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
            </Realm>
            <Host appBase="webapps" autoDeploy="true" deployOnStartup="true" deployXML="true" name="localhost" unpackWARs="true">
                <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t &quot;%r&quot; %s %b" prefix="localhost_access_log." suffix=".txt"/>
                <Context docBase="bsc" path="/bsc" reloadable="true" source="org.eclipse.jst.jee.server:bsc">
                    <Resource auth="Container" defaultAutoCommit="true" driverClassName="com.sybase.jdbc3.jdbc.SybDriver" maxActive="20" maxIdle="30000" maxWait="100" name="jdbc/security_datasource" password="securityPassword" removeAbandoned="true" removeAbandonedTimeout="15" type="javax.sql.DataSource" url="jdbc:sybase:Tds:server.systems.uk.co:10010/security_database" username="securityUserName"/>
                    <Resource auth="Container" defaultAutoCommit="true" driverClassName="net.sourceforge.jtds.jdbc.Driver" maxActive="20" maxIdle="30000" maxWait="100" name="jdbc/app_datasource" password="appPassword" removeAbandoned="true" removeAbandonedTimeout="15" type="javax.sql.DataSource" url="jdbc:jtds:sybase://server.systems.uk.co:10010/app_database" username="appUserName"/>
                </Context>
            </Host>
        </Engine>
        <Connector maxHttpHeaderSize="1508192" acceptCount="100" connectionTimeout="20000" executor="tomcatThreadPool" maxKeepAliveRequests="15" port="${bio.http.port}" protocol="org.apache.coyote.http11.Http11Protocol" redirectPort="${bio.https.port}"/>
    </Service>
</Server>

Can anyone see why my second datasource does not get configured?谁能看到为什么我的第二个数据源没有被配置? Is this a lifecycle timing issue?.这是生命周期计时问题吗? As I say the primary datasource configures correctly but the security one fails正如我所说,主数据源配置正确,但安全性失败

Update更新

The JndiPropertyHolder is just a simple convenience class as below JndiPropertyHolder 只是一个简单的便利类,如下所示

import org.springframework.stereotype.Component;

@Component
public class JndiPropertyHolder {
    private String jndiName;

    public String getJndiName() {
        return this.jndiName;
    }

    public void setJndiName(final String jndiName) {
        this.jndiName = jndiName;
    }

}

I have achieved this successfully by configuring my spring boot project as mentioned below :我通过配置我的 spring 启动项目成功地实现了这一点,如下所述:

//1. Application.java
//package hello;
//
//import javax.sql.DataSource;
//
//import org.apache.commons.logging.Log;
//import org.apache.commons.logging.LogFactory;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.boot.SpringApplication;
//import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
//import org.springframework.boot.builder.SpringApplicationBuilder;
//import org.springframework.boot.web.support.SpringBootServletInitializer;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.ComponentScan;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.context.annotation.Primary;
//import org.springframework.jdbc.core.JdbcTemplate;
//import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
//
//import hello.utilspackage.Foo;
//import springfox.documentation.builders.PathSelectors;
//import springfox.documentation.builders.RequestHandlerSelectors;
//import springfox.documentation.spi.DocumentationType;
//import springfox.documentation.spring.web.plugins.Docket;
//import springfox.documentation.swagger2.annotations.EnableSwagger2;
//
//@Configuration
//@ComponentScan
//@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {

    private final Log logg = LogFactory.getLog(getClass());

    public static void main(String[] args) {
        SpringApplication.run(applicationClass, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        logg.info("Server startup data loading started");
        new Foo().bar();
        logg.info("Server startup data loading completed");
        return application.sources(applicationClass);
    }

    @Configuration
    public class Config {
        @Value("${foo.spring.datasource.jndi-name}")
        private String primaryJndiName;

        @Value("${bar.spring.datasource.jndi-name}")
        private String secondaryJndiName;

        @Primary
        @Bean(destroyMethod = "")

        public DataSource primaryDs() {
            JndiDataSourceLookup lookup = new JndiDataSourceLookup();
            return lookup.getDataSource(primaryJndiName);
        }

        @Bean(destroyMethod = "")

        public DataSource secondaryDs() {
            JndiDataSourceLookup lookup = new JndiDataSourceLookup();
            return lookup.getDataSource(secondaryJndiName);
        }
    }

    @Configuration
    public class ConfigJdbcTemplates {
        @Value("${foo.spring.datasource.jndi-name}")
        private String primaryJndiName;

        @Value("${bar.spring.datasource.jndi-name}")
        private String secondaryJndiName;

        @Primary
        @Bean(destroyMethod = "")

        public JdbcTemplate primaryJT() {
            JndiDataSourceLookup lookup = new JndiDataSourceLookup();
            return new JdbcTemplate(lookup.getDataSource(primaryJndiName));
        }

        @Bean(destroyMethod = "")

        public JdbcTemplate secondaryJT() {
            JndiDataSourceLookup lookup = new JndiDataSourceLookup();
            return new JdbcTemplate(lookup.getDataSource(secondaryJndiName));
        }
    }

    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
        @Bean
        public Docket api() {
            return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any())
                    .paths(PathSelectors.any()).build();
        }
    }

    private static Class<Application> applicationClass = Application.class;

}

Observe the class Config in above code snippet , it has been annotated with @Configuration and one of the datasources in it is declared as @Primary观察上面代码片段中的类Config ,它已经用@Configuration注解,其中一个数据源被声明为@Primary

//GreetingController.java
//package hello;
//
//import java.util.List;
//import java.util.Map;
//import java.util.Set;
//import java.util.concurrent.atomic.AtomicLong;
//
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.jdbc.core.JdbcTemplate;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RequestParam;
//import org.springframework.web.bind.annotation.RestController;
//
//import hello.Application.Config;
//
//@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @Autowired
    Config conf;

    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
        String ss = null;
        List<Map<String, Object>> a = new JdbcTemplate(conf.secondaryDs())
                .queryForList("SELECT * from secondaryDB");
        for (Map<String, Object> map : a) {
            Set<String> kkeys = map.keySet();
            for (String string : kkeys) {
                if (map.get(string) != null)
                    ss += string + "  --  " + map.get(string).toString() + "## ";
            }
        }
        return new Greeting(counter.incrementAndGet(), String.format(template, ss));
    }

    @RequestMapping("/")
    public Greeting greetingBlank() throws Exception {
        String ss = null;
        List<Map<String, Object>> a = new JdbcTemplate(conf.primaryDs()).queryForList(
                "SELECT * from primaryDB");
        for (Map<String, Object> map : a) {
            Set<String> kkeys = map.keySet();
            for (String string : kkeys) {
                if (map.get(string) != null)
                    ss += string + "  --  " + map.get(string).toString() + "## ";
            }
        }
        return new Greeting(counter.incrementAndGet(), String.format(template, ss));
    }
}

Now in one of my rest controllers ie in GreetingController class I can safely use the @Autowired Config config instance.So that we can use new JdbcTemplate(conf.secondaryDs()) for querying the database referred by the Secondary datasource.现在在我的休息控制器之一,即在 GreetingController 类中,我可以安全地使用 @Autowired Config 配置实例。这样我们就可以使用new JdbcTemplate(conf.secondaryDs())来查询辅助数据源引用的数据库。 OR new JdbcTemplate(conf.primaryDs()) for querying the database referred by the Primary datasource OR new JdbcTemplate(conf.primaryDs())用于查询主数据源引用的数据库

**Same can be achieved by configuring JdbcTemplates in Application.class , for this observe the class ConfigJdbcTemplates in Application.java. **同样可以通过在 Application.class 中配置 JdbcTemplates 来实现,为此请观察 Application.java 中的类ConfigJdbcTemplates Please have a look at below implementation in controller DatabasePrimaryQueryController请查看控制器DatabasePrimaryQueryController 中的以下实现

//DatabasePrimaryQueryController.java
//package hello;
//
//import java.util.List;
//import java.util.Map;
//import java.util.Set;
//import java.util.concurrent.atomic.AtomicLong;
//
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RestController;
//
//import hello.Application.ConfigJdbcTemplates;
//
//@RestController
public class DatabasePrimaryQueryController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @Autowired
    ConfigJdbcTemplates confJts;

    @RequestMapping("/queryforpas")
    public Greeting greeting() throws Exception {
        String ss = null;
        List<Map<String, Object>> a = confJts.secondaryJT()
                .queryForList("SELECT * from secondaryDB");
        for (Map<String, Object> map : a) {
            Set<String> kkeys = map.keySet();
            for (String string : kkeys) {
                if (map.get(string) != null)
                    ss += string + "  --  " + map.get(string).toString() + "## ";
            }
        }
        return new Greeting(counter.incrementAndGet(), String.format(template, ss));
    }

    @RequestMapping("/queryforods")
    public Greeting greetingBlank() throws Exception {
        String ss = null;
        List<Map<String, Object>> a = confJts.primaryJT().queryForList(
                "SELECT * from primaryDB");
        for (Map<String, Object> map : a) {
            Set<String> kkeys = map.keySet();
            for (String string : kkeys) {
                if (map.get(string) != null)
                    ss += string + "  --  " + map.get(string).toString() + "## ";
            }
        }
        return new Greeting(counter.incrementAndGet(), String.format(template, ss));
    }
}

Both of the above methods are working as per expectations the only difference is that in the first implementation I'm autowiring datasources and in second implementation Jdbctemplate is Autowired.上述两种方法都按预期工作,唯一的区别是在第一个实现中我自动装配数据源,而在第二个实现中 Jdbctemplate 是自动装配的。

My application.properties file is as below我的 application.properties 文件如下

server.servlet-path=/*
server.port=7877
foo.spring.datasource.jndi-name=java:/PrimaryDB
bar.spring.datasource.jndi-name=java:/SecondaryDB

This application is deployed on jboss eap 6.4 where the jndi-names are bound with DataSource details from jboss' standalone.xml此应用程序部署在 jboss eap 6.4 上,其中 jndi 名称与来自 jboss 的standalone.xml数据源详细信息绑定

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM