Reputation: 705
I'm new to spring, so please bear with me.
I tried configuring my app using annotations and java. However, data source is not getting injected into my dao impl.
I have a properties file which maintains 3 different configs(dev,uat,prd) and these are accessed via CommonConfig.
I am getting below error-
Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanInitializationException: Property 'dataSource' is required for bean 'jdbcClientFundDao'
DAO-
package com.globeop.goreporting.gonavpack.persistence.dao;
import java.util.ArrayList;
import java.util.List;
public interface ClientFundDao {
public List<String> getClientsForUser(String user);
public ArrayList<String> getFundsForClient(String client);
}
DAO Implementer-
package com.globeop.goreporting.gonavpack.persistence.dao.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import com.globeop.goreporting.gonavpack.persistence.dao.ClientFundDao;
@Repository
public class JdbcClientFundDao implements ClientFundDao {
private JdbcTemplate jdbcTemplate;
@Required // tried @Autowired also
public void setDataSource(DataSource datasource) {
this.jdbcTemplate = new JdbcTemplate(datasource);
}
public List<String> getClientsForUser(String user) {
List<String> clients = jdbcTemplate.queryForList("select distinct ClientShortName from Client where IsActiveFlag = ?", String.class, 1);
return clients;
}
public ArrayList<String> getFundsForClient(String client) {
// TODO Auto-generated method stub
return null;
}
}
DataScource-
package com.globeop.goreporting.gonavpack.persistence.datasource;
import org.apache.tomcat.dbcp.dbcp.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.globeop.goreporting.gonavpack.model.CommonConfig;
@Configuration
public class DataSourceForClientFund {
private static final String driverClassName = CommonConfig.DB_PARAMETERMAP_DRIVER;
private static final String url = CommonConfig.DB_PARAMETERMAP_URL;
private static final String dbUsername = CommonConfig.DB_PARAMETERMAP_USER;
private static final String dbPassword = CommonConfig.DB_PARAMETERMAP_PWD;
@Bean
public static BasicDataSource getDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(dbUsername);
dataSource.setPassword(dbPassword);
return dataSource;
}
}
WebApplication Context (NavSummaryServlet-context.xml)-
<!-- Contains @Controller, @RequestMapping, view resolver, etc -->
<context:component-scan base-package="com.globeop.goreporting.gonavpack.webconfigs" />
<mvc:annotation-driven />
Application Context (NavSummaryApplication-context.xml)-
<!-- Contains DAO, DAO impl, and DataSource beans -->
<context:annotation-config/>
<context:component-scan base-package="com.globeop.goreporting.gonavpack.persistence" />
web.xml-
<servlet>
<servlet-name>NavSummaryServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/goNavPackServlet/NavSummaryServlet-context.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>NavSummaryServlet</servlet-name>
<url-pattern>/navSummary.jsp</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/goNavPackApp/NavSummaryApplication-context.xml</param-value>
</context-param>
Upvotes: 0
Views: 4363
Reputation: 280102
You don't need to initialize the JdbcTemplate
in your class. The whole point of an IoC container is to have it do that for you.
So add a @Bean
method to create it. (Also, don't make your methods static, it's not needed in this case)
@Configuration
@ComponentScan(basePackages = "the.name.of.your.package")
public class DataSourceForClientFund {
private static final String driverClassName = CommonConfig.DB_PARAMETERMAP_DRIVER;
private static final String url = CommonConfig.DB_PARAMETERMAP_URL;
private static final String dbUsername = CommonConfig.DB_PARAMETERMAP_USER;
private static final String dbPassword = CommonConfig.DB_PARAMETERMAP_PWD;
@Bean
public BasicDataSource getDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(dbUsername);
dataSource.setPassword(dbPassword);
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate() {
final JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(getDataSource()); // notice this is calling the other Bean method
jdbcTemplate.afterPropertiesSet();
return jdbcTemplate;
}
}
You can then @Autowired
or @Inject
the JdbcTemplate
directly.
In your @Repository
@Repository
public class JdbcClientFundDao implements ClientFundDao {
@Autowired
private JdbcTemplate jdbcTemplate;
...
}
In a @Controller
@Controller
public class YourController {
@Autowired
private ClientFundDao clientFundDao; // Spring will inject an `JdbcClientFundDao` instance
}
This Spring documentation should explain how these configurations are done.
Upvotes: 1