springhibernatespring-mvchibernate-generic-dao

Spring MVC + Hibernate DAOs : unable to wire beans


I'm currently working on a Spring MVC project in which I integrated Hibernate. The pure Spring MVC part (DispatcherServlet + request mapping) works fine. Now, the problem I have to cope with is quite strange : I've read "Java Persistence with Hibernate" and I am trying to design my persistence layer in a similar way than explained in the book. That is, I've designed it in two parallel hierarchies : one for implementation classes and a second for the interfaces.

So, I have an abstract class named GenericDaoImpl, that implements the GenericDao interface. Then I have a concrete class named AdvertisementDaoImpl, that extends GenericDaoImpl and that implements the AdvertisementDao interface (which extends GenericDao).

Then, in a service bean (class marked with @Service), I'll have my dao class autowired.

Here's my problem :

The abstract class I have at the top of my DAO hierarchy handles all the boilerplate code for common CRUD methods. So, I definitely want to keep it.

Does anyone have an explanation about that?

Here's an excerpt of code :

public abstract class GenericDaoImpl <T, ID extends Serializable> implements BeanPostProcessor, GenericDao<T, ID>{
    @Autowired(required=true)
    private SessionFactory sessionFactory;
    private Session currentSession;
    private Class<T> persistentClass;

...
}


@Repository
public class AdvertisementDaoImpl extends GenericDaoImpl<Advertisement, Long> implements AdvertisementDao {

...


    public List<Advertisement> listAdvertisementByType(AdvertisementType advertisementType, Class<? extends Good> type) {
        return null;
    }

}

@Service
public class AdvertisementServiceImpl implements AdvertisementService{
    @Autowired(required=false)
    private AdvertisementDao advertisementDao;

    public List<Advertisement> listAllAdvertisements() {

        return null;
    }

}

Here's the most relevant part of the stacktrace (at least, I guess it is):

nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: be.glimmo.service.AdvertisementService be.glimmo.controller.HomeController.advertisementService; nested exception is java.lang.IllegalArgumentException: Can not set be.glimmo.service.AdvertisementService field be.glimmo.controller.HomeController.advertisementService to be.glimmo.dao.AdvertisementDaoImpl

And here's my Spring configuration (link to pastebin.com) :


Solution

  • I believe you should use proxy-target-class in your transaction management configuration:

    <tx:annotation-driven transaction-manager="transactionManagerForHibernate" 
         proxy-target-class="true" />
    

    The symptoms of the problem you describe match the ones mentioned in Spring Transaction Management (look for Table 10.2) and AOP proxying with Spring:

    If the target object to be proxied implements at least one interface then a JDK dynamic proxy will be used. All of the interfaces implemented by the target type will be proxied. If the target object does not implement any interfaces then a CGLIB proxy will be created.

    So, when CGLIB is not there by default, you have all the methods coming from implemented interfaces but you will miss proxying of the methods that come from super classes in the hierarchy and that's why you get an exception on this.