Configuring two datasources by jndi lookup with Springboot

生来就可爱ヽ(ⅴ<●) 提交于 2021-01-28 11:11:01

问题


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). I have configured this successfully using a config class for each datasource and using datasource connection details in the application.properties file.

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.

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.

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

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

<?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

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;
    }

}

回答1:


I have achieved this successfully by configuring my spring boot project as mentioned below :

//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

//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 i.e. 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. OR new JdbcTemplate(conf.primaryDs()) for querying the database referred by the Primary datasource

**Same can be achieved by configuring JdbcTemplates in Application.class , for this observe the class ConfigJdbcTemplates in Application.java. Please have a look at below implementation in controller 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.

My application.properties file is as below

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



来源:https://stackoverflow.com/questions/41941147/configuring-two-datasources-by-jndi-lookup-with-springboot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!