I've just updated from Spring 3.1.1 to 3.2.6
With 3.1 the following code worked well:
@Bean(name = DEMO_DS)
public JndiObjectFactoryBean demoDataSource()
{
JndiObjectFactoryBean factory = new JndiObjectFactoryBean();
factory.setJndiName(JDBC_DEMO_DS);
factory.setProxyInterface(DataSource.class);
return factory;
}
@Bean(name = DEMO_SESSION_FACTORY)
public SqlSessionFactoryBean demoSqlSessionFactory(@Qualifier(DEMO_DS) DataSource dataSource)
{
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setConfigLocation(new ClassPathResource("demo/config.xml"));
return sessionFactory;
}
However with the uprgraded version I get the following exception:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=DemoDataSource)}
I have multiple DataSources hence the @Qualifier is a need.
Thanks.
Edit:
It seems that this solves the problem:
public DataSource dataSourceFactory() {
try
{
return (DataSource) demoDataSource().getObject();
}
catch (Exception ex)
{
throw new RuntimeException(ex);
}
}
...
sessionFactory.setDataSource(dataSourceFactory());
However I don't think it's a nice solution.
Depending on your need rewrite your configuration a little. If you don't really need the datasource injected you can do something like this.
@Bean(name = DEMO_DS)
public JndiObjectFactoryBean demoDataSource() {
JndiObjectFactoryBean factory = new JndiObjectFactoryBean();
factory.setJndiName(JDBC_DEMO_DS);
factory.setProxyInterface(DataSource.class);
return factory;
}
@Bean(name = DEMO_SESSION_FACTORY)
public SqlSessionFactoryBean demoSqlSessionFactory() {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(demoDataSource().getObject());
sessionFactory.setConfigLocation(new ClassPathResource("demo/config.xml"));
return sessionFactory;
}
If you need to have a datasource injected you might want to switch to using a JndiLocatorDelegate
to do the lookup instead of a JndiObjectFactoryBean
.
@Bean(name = DEMO_DS)
public DataSource demoDataSource() throws NamingException {
return JndiLocatorDelegate.createDefaultResourceRefLocator().lookup(JDBC_DEMO_DS, DataSource.class);
}
This gives you a DataSource
directly instead of a FactoryBean<Object>
(which is what the JndiObjctFactoryBean
is) what probably is the source of the problem.
Or (in theory) you should also be able to use a @Value
annotation on a property in your config class. Instead of a @Value
a normal @Resource
should also do the trick (that can also delegate a call to JNDI for a lookup).
public class MyConfig {
@Value("${" + JDBC_DEMO_DS + "}")
private DataSource demoDs;
}
With @Resource
public class MyConfig {
@Resource(mappedName=JDBC_DEMO_DS)
private DataSource demoDs;
}
And you can then simply reference it in your configuration method.
@Bean(name = DEMO_SESSION_FACTORY)
public SqlSessionFactoryBean demoSqlSessionFactory() {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(demoDs);
sessionFactory.setConfigLocation(new ClassPathResource("demo/config.xml"));
return sessionFactory;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.