I have inherited an older Grails 1.2 application, and I am trying to upgrade it to the latest Grails 2.1.2. Something has changed in Grails because this code from resources.groovy used to work:

searchIndexBuilder(SearchIndexBuilder) {bean ->
    bean.singleton = true
    indexManager = ref("indexManager")
    sessionFactory = ref("sessionFactory")
}

Combined with this code from SearchIndexBuilder.java:

private void injectHibernateEventListener() {
    try {
        HibernateEventListener hel = initHibernateEventListener();
        SessionFactoryImpl hibernateSessionFactory = (SessionFactoryImpl) sessionFactory; //fails here
        EventListeners hibernateEventListeners = hibernateSessionFactory.getEventListeners();
etc....

The code fails at the cast because I get an instance of SessionFactoryProxy which does not extend SessionFactoryImpl.

How do I fix this?

有帮助吗?

解决方案

This is new in Grails 2.0, it's to support domain class reloading. Before 2.0 changing a domain class during run-app would cause the application to restart, but with the new reloading agent this isn't necessary. But since the persistence configuration may have changed, Grails rebuilds the SessionFactory. But due to the way Hibernate is configured, other classes have a reference to the old one, so it cannot be replaced without knowing every class that has a reference. So the proxy is used to contain the replaceable real instance, and everyone calls methods on the proxy. When the SessionFactory is replaced it's entirely internal to the proxy and other users don't know that anything happened.

This means that the SessionFactory won't be a SessionFactoryImpl, but the point of interfaces is to abstract away the concrete implementation class, so it's a bad practice to cast to what you expect the real class to be. This should work in older and current versions of Grails:

SessionFactory hibernateSessionFactory = (SessionFactory)sessionFactory;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top