Reputation: 383
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>
Upvotes: 10
Views: 19215
Reputation: 5919
For those just looking for a way to define a datasource via JNDI, I would go for:
@Bean
public JndiObjectFactoryBean dataSource(){
return new JndiDataSourceLookup().getDataSource("jdbc/SpittrDS");
}
Upvotes: 0
Reputation: 119
I landed here without realizing this was a problem I had faced in the past - Error Casting Spring's JndiObjectFactoryBean to ConnectionFactory for Solace-MQ JMS
So a workaround (not the preferred way) is to call afterPropertiesSet() on jndiObjectFactoryBean before attempting to getObject()
@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(); //NOT NULL
}
Upvotes: 1
Reputation: 5743
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
}
Upvotes: 12