简体   繁体   中英

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 :

  • autowiring a DAO class that implements an interface but does not extends my abstract GenericDaoImpl class : OK
  • autowiring my AdvertisementDaoImpl that implements the AdvertisementDao interface and extends my abstract GenericDaoImpl class : leads to bean initialization exception.

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) :

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.

After a few more tests, it turns out that the problem was caused by my abstract GenericDaoImpl class implementing BeanPostProcessor interface : for some reason, the methods from this interface were executed not only at this bean instantiation but at every bean intantiation .

Given that, within my BeanPostProcessor hook methods, I was retrieving generics parameterized types, when these methods were executed against classes that are not in my DAO hierarchy, they would end up yielding runtime Exceptions (more specifically, ClassCastException).

So, to solve this issue, I had my GenericDaoImpl class not implement BeanPostProcessor interface anymore and I moved the body of the hook method in the empty contructor.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM