when I uss Java-base to config my JNDI. Spring 4.2.5.
But If I use JndiObjectFactoryBean to config.when I want to get the datasource
,the object will be null.
@Bean
public DataSource dataSource(){
JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS");
jndiObjectFactoryBean.setResourceRef(true);
jndiObjectFactoryBean.setProxyInterface(DataSource.class);
return (DataSource) jndiObjectFactoryBean.getObject(); //NULL!!!
}
But if change the method to this,it work well.
@Bean
public DataSource dataSource(){
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
DataSource dataSource = dsLookup.getDataSource("java:comp/env/jdbc/SpittrDS");
return dataSource;
}
I do not know where is the problem.
Tomcat 9.0 context.xml
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<Resource name="jdbc/SpittrDS"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/spittrds"
username="root"
password="1"
maxActive="100"
maxIdle="20"
minIdle="5"
maxWait="10000"/>
</Context>
The typical usage will be to register this as singleton factory (e.g. for a certain JNDI-bound DataSource) in an application context, and give bean references to application services that need it. The default behavior is to look up the JNDI object on startup and cache it.
We know that DataSource with JNDI is the preferred way to achieve connection pooling and get benefits of container implementations. Today we will look how we can configure a Spring Web Application to use JNDI connections provided by Tomcat.
The actual lookup in JndiObjectFactoryBean is done in the lifecycle callback method. Either call the method explictly in your @Bean method like this (workaround)
@Bean
public DataSource dataSource(){
JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS");
jndiObjectFactoryBean.setResourceRef(true);
jndiObjectFactoryBean.setProxyInterface(DataSource.class);
jndiObjectFactoryBean.afterPropertiesSet();
return (DataSource) jndiObjectFactoryBean.getObject(); //NULL!!!
}
Or the better approach. Let your @Bean method return the JndiObjectFactoryBean and manage its lifecyle. Then in your dependent beans that require a DataSource inject the datasource created from the factory
@Bean
public JndiObjectFactoryBean dataSource(){
JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS");
jndiObjectFactoryBean.setResourceRef(true);
jndiObjectFactoryBean.setProxyInterface(DataSource.class);
return jndiObjectFactoryBean;
}
//in your dependnecy
@Bean
public SomeBean someBean(DataSource dataSource){
//use the injected datasource shich comes from the factory
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With