I've been stuck for a week with this problem and there is no way to find a solution in my project using Spring tool suite.
My dispatcher scan packages and creates beans for the controller and service layer but it seems it can't reach the model layer.
This is my servlet-context.xml:
<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- <beans:property name="dataSource" ref="dataSource"/> -->
<beans:property name="configLocation" value="classpath:hibernate-annotation.cfg.xml" />
</beans:bean>
<tx:annotation-driven/>
<!-- <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory" />
</beans:bean> -->
I have commented the transactionManager bean because it throws an expection.
The problem comes up when in my UserServiceImpl set UserDaoI as #Autowired
#Service
public class UserServiceImpl implements UserServiceI{
private static final Logger logger =
Logger.getLogger(UserServiceImpl.class);
#Autowired
UserDaoI userDao;
public boolean isRegisteredUser(User user){
logger.debug("Entrando en isRegisteredUser" + logger.getClass());
boolean isRegistered = false;
UserDao uDao = userDao.getUserByDni(user.getDni());
if(!(uDao.getEmail().equals(user.getEmail()))){
isRegistered = true;
}
return isRegistered;
}
I am clueless and desperate.
EDIT:
This is my UserDaoI class, but I think is not relevant.
public interface UserDaoI {
void addUser(UserDao userDao);
UserDao getUser(int id);
boolean updateUser(UserDao userDao);
boolean deleteUser(int id);
List<UserDao> getAllUsers();
UserDao getUserByDni(String dni);
}
This is my UserDaoImpl.java, the source of the problems.
#Repository
public class UserDaoImpl implements UserDaoI{
private static final Logger logger = LoggerFactory.getLogger(UserDaoImpl.class);
#Autowired
SessionFactory sessionFactory;
Session session;
#Override
public void addUser(UserDao userDao) {
session = sessionFactory.openSession();
session.beginTransaction();
session.save(userDao);
session.getTransaction().commit();
session.close();
}
#Override
public UserDao getUser(int id) {
//sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.openSession();
session.beginTransaction();
UserDao userDao = (UserDao) session.get(UserDao.class, id);
session.getTransaction().commit();
session.close();
return userDao;
}
#Override
public boolean updateUser(UserDao userDao) {
assert(userDao!=null);
//sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.openSession();
session.beginTransaction();
session.update(userDao);
session.getTransaction().commit();
session.close();
return false;
}
#Override
public boolean deleteUser(int id) {
//sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
UserDao userDao = new UserDao();
userDao.setId(id);
if(getUser(id)!=null){
try{
session.beginTransaction();
session.delete(userDao);
session.getTransaction().commit();
return true;
}catch(Exception ex){
logger.error("No se ha podido borrar el usuario");
}finally{
session.close();
}
}
return false;
}
#Override
public List<UserDao> getAllUsers() {
//sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.openSession();
session.beginTransaction();
#SuppressWarnings("unchecked")ArrayList<UserDao> userDaoList = (ArrayList<UserDao>) session.createQuery("from user").list();
session.getTransaction().commit();
session.close();
return userDaoList;
}
#Override
public UserDao getUserByDni(String dni) {
session = sessionFactory.getCurrentSession();
session.beginTransaction();
UserDao userDao = (UserDao) session.createQuery("from user where dni = " + dni).uniqueResult();
session.getTransaction().commit();
session.close();
return userDao;
}
}
Why I do not need to autowire my Session?
This is my hibernate config
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/gen</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">fiw48asi</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<mapping class="com.library.app.dao.user.UserDao"/>
</session-factory>
Now the exception I get is
org.hibernate.hql.internal.ast.QuerySyntaxException: user is not mapped
But it is declared in hibernate-annotation.cfg.xml
Thanks a ton!
The problem is:
'userDaoImpl': Injection of autowired dependencies failed...: Could not autowire field:
because
No qualifying bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate
In your model, you will need to define a userDaoImpl bean with an #Bean annotation and a Hibernate SessionFactory to allow Spring to create and inject it, e.g.,: add a method to your UserServiceImpl class like this:
UserServiceImpl.java
#Bean
public UserDaoI userDao() {
return new UserDaoImpl();
}
But I notice some mixing of types and models, however, which I think is at the root of your issues, so I'll explain how the service with DAO model works generally with a simpler model.
In a "service and data access object" model, you create a persistence mediator for each entity, conventionally with a DAO suffix and the entity is typically a simple plain ordinary Java object (POJO).
For example, to represent an in-memory user, you might model the entity as follows:
User.java
public class User {
private String name;
// more POJO properties as need..
public void setName(String name) {
this.name = name;
}
public String getName(String name) {
return this.name;
}
// more POJO setters and getters...
}
Now we need a mediator which can create, read, update, and delete these entities from our database. In a DAO pattern, that's the role of the entity's DAO:
UserDao.java
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
public class UserDao {
#Autowired
private SessionFactory sessionFactory;
public User getUser(long id) {
sessionFactory.getCurrentSession().get(User.class, id);
}
public void addUser(User user) {
sessionFactory.getCurrentSession().saveOrUpdate(user);
}
//...
}
We add a service layer on top of the DAO layer when services either span entities or add some (likely to change) business logic to the entity. For example, supposed we have a registration table which captures registration records in various states for each user:
UserService.java
public class UserService {
#Autowired
private UserDao userDao
#Autowired
private RegistrationDao registrationDao
public boolean isRegistered(long userId) {
// DAOs mediate access to tables
User user = userDao.getUser(userId);
Registration reg = registrationDao.getRegistration();
//
// business logic
//
return isUserRegistered(user, registration);
}
}
With Spring 4, though, I don't hand-code my DAO layers anymore; instead I use Spring Data JPA with the Hibernate JPA provider. Here's a very simple example of how to make this work. You're already using the Hibernate ORM, so you don't "lose" much (quite the opposite, really) by using Spring Data JPA with the Hibernate JPA provider.
Related
I'm new to Spring and I did a login/register applicaton following a youtube tutorial but I want to add a new functionality that allows to delete a student. I used #Transactional on my delete method and modified accordingly the xml file but I get this error:
Message Request processing failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'platformTransactionManager' is expected to be of type 'org.springframework.transaction.PlatformTransactionManager' but was actually of type 'com.infotech.service.impl.StudentServiceImpl'
my Service class
#Service("studentService")
public class StudentServiceImpl implements StudentService {
#Autowired
private StudentDAO studentDAO;
public void setStudentDAO(StudentDAO studentDAO) {
this.studentDAO = studentDAO;
}
public StudentDAO getStudentDAO() {
return studentDAO;
}
//other methods
#Override
public void delete(String email) {
getStudentDAO().delete(email);
}
}
my DAO class
#EnableTransactionManagement
#Repository("studentDAO")
public class StudentDAOImpl implements StudentDAO {
#Autowired
private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
public HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
#Autowired
private SessionFactory sessionFactory;
protected Session getSession() {
return (Session) sessionFactory.getCurrentSession();
}
//other methods
#Transactional("platformTransactionManager")
public void delete(String email) {
Student student = (Student) ((HibernateTemplate) getSession()).get(Student.class, email);
((HibernateTemplate) getSession()).delete(student);
}
}
In the dispatcher servlet I have defined InternalResourceViewResolver, dataSource, hibernateTemplate, sessionFactory beans and then I added another bean
<tx:annotation-driven transaction-manager="platformTransactionManager"/>
<bean id= "platformTransactionManager"class="com.infotech.service.impl.StudentServiceImpl">
</bean>
Finally, this is the controller
#Controller
public class MyController {
#Autowired
private StudentService studentService;
public void setStudentService(StudentService studentService) {
this.studentService = studentService;
}
public StudentService getStudentService() {
return studentService;
}
//...RequestMappings...
#RequestMapping(value = "/delete/{email}", method = RequestMethod.GET)
public ModelAndView delete(#PathVariable("email") String email) {
studentService.delete(email);
return new ModelAndView("redirect:/view/home");
}
...
}
Now, how can I make my bean of PlatformTransactionManager type?
But most of all I think there's a simpler way to delete a field from my table, maybe without using #Transaction at all so can anyone help me understand why I get the error and explain me what is #Transactional and if I really should use it in this case?
Remember that I'm NEW to Spring, I still don't have many notions so sorry if I wrote something totally stupid :-)
Spring is looking for transaction manager - it requires a concrete implementation of the PlatformTransactionManager interface. It's being given your service implementation, which isn't a PlatformTransactionManager and not what it needs. If you're using JDBC, org.springframework.jdbc.datasource.DataSourceTransactionManager should work.
Try changing:
<bean id= "platformTransactionManager" class="com.infotech.service.impl.StudentServiceImpl">
To:
<bean id= "platformTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
I'm using Spring AOP with AspectJ and Spring Data MongoDb and am having a world of trouble persisting objects.
In this case, I have an AclEntryDaoImpl that exposes AclEntryImpl. When AclEntryImpl is provided a Principal that is a standard Java object (a "non-Spring" bean), mongoTemplate.save() works as expected. However when Principal is a Spring bean, Mongo is unable to convert the object and results in a MappingException org.springframework.data.mapping.model.MappingException: No id property found on class class com.sun.proxy.$Proxy33. All my objects need to be Spring beans so that (a) I keep my objects decoupled and (b) my AOP (LoggingAspect) is invoked.
Lastly, I cannot take advantage of Spring converters because Mongo sees the target object AclEntryImpl as a proxy com.sun.proxy.$Proxy33 and so Converter<Principal, DBObject> is never invoked.
Any and all help would be greatly appreciated!
Snippets:
Here's my Spring XML configuration:
<beans>
<context:component-scan base-package="a.b" />
<context:property-placeholder location="config.properties" />
<aop:aspectj-autoproxy />
<bean id="loggingAspect" class="a.b.LoggingAspect" />
<mongo:db-factory host="${database.host}" port="${database.port}" dbname="${database.dbname}" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
<bean id="aclEntryDao" class="a.b.AclEntryDaoImpl">
<lookup-method name="createAclEntry" bean="aclEntry" />
</bean>
</beans>
AclEntryImpl:
#Document
#Component
#Scope("prototype")
public class AclEntryImpl implements AclEntry {
#Id
private String id;
private String service;
#DBRef #Expose
private Principal principal;
#Expose
private boolean accessGranted;
#Expose
private List<Permission> permissions;
#Override #Loggable #MongoSaveReturned
public AclEntry save() {
return this;
}
...getters and setters...
}
AclEntryDaoImpl:
#Repository
public abstract class AclEntryDaoImpl implements AclEntryDao {
#Override #Loggable
public AclEntry addEntry(String serviceName, Principal principal, Permission[] permissions, boolean accessGranted) throws Exception {
AclEntry entry = createAclEntry(); //<-- Spring lookup-method
entry.setService(serviceName);
entry.setPrincipal(principal); //<-- com.sun.proxy.$Proxy33
entry.setAccessGranted(accessGranted);
for (Permission permission : permissions) {
if (!entry.addPermission(permission)) {
return null;
}
}
return entry.save();
}
... other DAO methods ...
}
LoggingAspect:
#Aspect
public class LoggingAspect {
#Autowired
private MongoTemplate mongoTemplate;
#Pointcut("execution(!void a.b..*.*(..))")
public void returningMethods() {}
#AfterReturning(pointcut="returningMethods() && #annotation(MongoSaveReturned)", returning="retVal")
public Object mongoSaveReturnedAdvice(Object retVal) {
Logger logger = null;
try {
logger = getLogger(retVal);
mongoTemplate.save(retVal); //<-- throws MappingException
log(logger, "save: " + retVal.toString());
} catch (Exception e) {
log(logger, "throw: " + e.toString());
}
return retVal;
}
... other logging methods ...
}
I will be working with a database and with a JMS queue so I decided to use JTATransactionManager (multiple resources).
I am using Spring Framework 3.2.3.RELEASE
Hibernate 4.2.1.Final
Glassfish 3.1.2.2
With JTATransactionManager nothing is committed to db.I tried JPATransactionManager it works fine.I don't get any exceptions with JTATransactionManager.Any idea what I am doing wrong?Thanks.
This is a piece of jpa config file
<jee:jndi-lookup id="dataSource" jndi-name="Test" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:packagesToScan="com.pinkshield.jpaTest.domain"
p:dataSource-ref="dataSource"
p:jpaPropertyMap-ref="jpaPropertyMap"
p:jpaVendorAdapter-ref="hibernateVendor" />
<util:map id="jpaPropertyMap">
<entry key="hibernate.hbm2ddl.auto" value="validate" />
<entry key="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect" />
<entry key="transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory" />
<entry key="transaction.manager_lookup_class"
value="org.hibernate.transaction.SunONETransactionManagerLookup" />
</util:map>
<bean id="hibernateVendor"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:showSql="true" />
<tx:jta-transaction-manager />
<context:component-scan base-package="com.pinkshield.jpaTest" />
This is my Generic Dao for JPA
package com.pinkshield.jpaTest;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
public class GenericDaoJpa<T> implements GenericDao<T>
{
private Class<T> queryClass;
protected EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager entityManager)
{
this.entityManager = entityManager;
}
public GenericDaoJpa(Class<T> queryClass)
{
super();
this.queryClass = queryClass;
}
public T getNewInstance()
{
try
{
return getQueryClass().newInstance();
}
catch (InstantiationException e)
{
throw new RuntimeException("Error creating new instance of : " + getQueryClass().getName(), e);
}
catch (IllegalAccessException e)
{
throw new RuntimeException("Error creating new instance of : " + getQueryClass().getName(), e);
}
}
public Class<T> getQueryClass()
{
return queryClass;
}
public T get(Long id)
{
if (id == null)
{
return null;
}
else
{
return entityManager.find(queryClass, id);
}
}
#SuppressWarnings("unchecked")
public List<T> getAll()
{
return entityManager.createQuery("select o from " + queryClass.getName() + " o").getResultList();
}
public void save(T object)
{
entityManager.persist(object);
}
public void update(T object)
{
entityManager.merge(object);
}
public void delete(T object)
{
entityManager.remove(entityManager.merge(object));
}
}
This is UserDao
#Repository
public class UserDao extends GenericDaoJpa<User>
{
public UserDao()
{
super(User.class);
}
}
And this is my service code
#Service
public class UserServiceImpl implements IUserService{
#Autowired UserDao userDao;
#Override
#Transactional
public void saveUser(String name, String lastName)
{
User user=new User();
user.setLastName(lastName);
user.setName(name);
userDao.save(user);
}
}
I think you need to add <tx:annotation-driven/> to the context xml. That will run a context post processor that will wrap methods with #Transactional with an AOP method interceptor that provides the transaction behavior you're looking for.
I know hibernate well, and fairly Spring core, I am able to use hibernate template and hibernate dao support class to integrate both but as from hibernate 3.1 we have contextual sessions i.e. we need not to use hibernate template and hibernate dao support but when i am trying to integrate with this concept and inject the sessionFactory in my dao class everything goes write but i am trying to insert data hibernate shows the insert query but the data is not saved to database please help me what can i do.
Here is my code
#Transactional
public class UserDAO {
SessionFactory sessionFactory;
public void save(User transientInstance) {
try {
sessionFactory.openSession().save(transientInstance);
} catch (RuntimeException re) {
throw re;
}
}
public static UserDAO getFromApplicationContext(ApplicationContext ctx) {
return (UserDAO) ctx.getBean("UserDAO");
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
This is my beans.xml
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
</bean>
<bean id="UserDAO" class="dao.UserDAO">
<property name="sessionFactory"><ref bean="sessionFactory" /></property>
</bean>
This is my main code
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
User user=new User("firstName", "lastName", "address", "phoneNo", "mobileNo", "email", "password", false, null);
SessionFactory factory=(SessionFactory)context.getBean("sessionFactory");
Session session=factory.openSession();
Transaction tx=session.beginTransaction();
UserDAO ud=(UserDAO)context.getBean("UserDAO");
ud.save(user);
tx.commit();
session.close();
There are several problems with your code,
The DAO is already transactional, managed by Spring. You are starting another transaction in main.
You are opening session twice. Once in main and another time in dao.
When you are using contextual session, it is best practice to call sessionFactory.getCurrentSession()
Now if you have configured transaction manager with Spring properly, the following code will work, I just added some comments, see if it's helpful to you :)
#Transactional
public class UserDAO {
SessionFactory sessionFactory;
public void save(User transientInstance) {
//Removed try-catch. It was just catching RuntimeException only to re throw it
sessionFactory.openSession().save(transientInstance);
}
//I would get rid of this method.
public static UserDAO getFromApplicationContext(ApplicationContext ctx) {
return (UserDAO) ctx.getBean("UserDAO");
}
//I would get rid of this method or make it private
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
Main code
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
//I would use builder instead of constructor here
User user=new User("firstName", "lastName", "address", "phoneNo", "mobileNo", "email", "password", false, null);
UserDAO ud=(UserDAO)context.getBean("UserDAO");
ud.save(user);
I'm having some trouble getting a data source bean, defined in an xml file, into a class in Spring using #Autowired annotation.
Would anyone have an idea what's happening here? It seems as though dataSource in the *Impl class is not being wired in.
dao-context.xml
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:8889/spring" />
<property name="username" value="user" />
<property name="password" value="1234" />
</bean>
PersonDaoImpl.java
public class PersonDaoImpl implements PersonDao {
#Autowired
private DataSource dataSource;
private JdbcTemplate jdbcTemplate = new JdbcTemplate();
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
System.out.println("SETTING DATA SOURCE");
this.dataSource = dataSource;
}
public List<Person> getPersonList() {
// TODO Auto-generated method stub
return null;
}
public void savePerson(Person person) {
// TODO Auto-generated method stub
}
public Person getPersonById(int id) {
System.out.println("Getting Person: " + id);
return null;
}
#Override
public int getPersonCount(){
String sql = "SELCECT COUNT(*) FROM PERSON";
jdbcTemplate.setDataSource(getDataSource());
int count = jdbcTemplate.queryForInt(sql);
System.out.println("Count of Person: " + count);
return count;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
...and finally, the exception.
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: No DataSource specified
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
java.lang.IllegalArgumentException: No DataSource specified
org.springframework.util.Assert.notNull(Assert.java:112)
org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:97)
org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:382)
org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:456)
org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:464)
org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:472)
org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:477)
org.springframework.jdbc.core.JdbcTemplate.queryForInt(JdbcTemplate.java:486)
com.myPackage.rest.dao.impl.PersonDaoImpl.getPersonCount(PersonDaoImpl.java:50)
com.myPackage.rest.HomeController.home(HomeController.java:36)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:212)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
Any help would be greatly appreciated, cheers.
Your data source needs to be set in the JdbcTemplate (I don't see you doing that). Also since you put the #Autowired annotation on the field, I don't think it uses the setter so that would be why your setDataSource method is not being called. Since your exception indicates that you called jdbcTemplate.execute and dataSource is null, this makes sense.
If you look here: http://static.springsource.org/spring/docs/current/spring-framework-reference/html/jdbc.html there is an example of autowiring a data source, but the idea is:
public class MyDao {
private JdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
}
Right, thanks to the two replies I've got this working.
dao-context (as above, with this added):
<bean id="personDao" class="com.mypackage.rest.dao.impl.PersonDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
Impl class
#Repository
public class PersonDaoImpl implements PersonDao {
private JdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public int getPersonCount(){
String sql = "select count(*) from person";
return jdbcTemplate.queryForInt(sql);
}
}
One more important piece I had missed was the Dependency Injected Impl instance in the Controller.
#Controller
public class HomeController {
#Autowired
private PersonDao personDao;
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
int personCount = personDao.getPersonCount();
model.addAttribute("personCount", personCount );
return "home";
}
}
The impl class needs to be marked for handling by spring:
#Repository
public class PersonDaoImpl implements PersonDao {
Now if spring package scanning is being used, it will find this class and process all the #Autowired annotations