theFriedC
theFriedC

Reputation: 430

Spring JSF OpenSessionInViewFilter

i'm having big trouble with getting the OpenSessionInViewFilter working, using Spring 3.0.2, hibernate3 and jsf2.

the scenario:

there is a BusinessCaseEntity with holding some simple information properties (of string and int type) and a list of mapped EmployeeEntities. This list is mapped with

fetch=FetchType.LAZY

first of all, i load a list of all BusinessCases and show them in a table. for this purpose, i use a dao class. the businesscases with their simple properties are displayed. if i select a specific businesscase i want to show the connected employees for instance. therefore i just want to use the getter method of the businesscase object --> getEmployees()

with my simple understanding of spring and hibernate, i know that the BusinessCaseEntity at this time is detached from any spring and hibernate(session) at the backend and the famous LazyLoadingException appears.

this is where i think that the OpenSessionInViewFilter comes in place. i read a lot of instructions of how to use it, but i still could not manage to get it working in my app.

configured the filter in my web.xml and i made a little subclass of the OpenSessionInViewFilter of spring to do some output for debugging purpose.

nevertheless, when it comes to the point to fetch the required data, the filter opens a new session, then an LazyLoadException is thrown and then the filter closes the session. why is there a LazyLoadException when the session is currently open?

2011-06-14 19:19:49,734 DEBUG HibernateFilter:239 - Using SessionFactory 'sessionFactory' for OpenSessionInViewFilter
2011-06-14 19:19:49,734 DEBUG HibernateFilter:66 - Opening single Hibernate Session in OpenSessionInViewFilter
Jun 14, 2011 7:19:49 PM com.sun.facelets.FaceletViewHandler handleRenderException
SEVERE: Error Rendering View[/web/caseDetails.xhtml]
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.frivak.cat.db.entities.BusinessCaseEntity.caseClientList, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
LOTS OF STACKTRACE ...
2011-06-14 19:19:49,879 DEBUG HibernateFilter:92 - Closing single Hibernate Session in OpenSessionInViewFilter

do i somehow misunderstand the purpose of the OpenSessionInViewFilter?

i am quite lost now and would really appreciate some help.

thanks - chris

Upvotes: 3

Views: 1777

Answers (2)

Dalton
Dalton

Reputation: 420

I gave up trying to use Spring's OpenSessionInViewFilter. I have implemented JSF Phase Listeners to do the job, as oriented here: http://assenkolov.blogspot.com.br/2008/04/open-session-in-view-with-jsf-and.html. The solution worked for me.

The full post below (if the link is dead):

I expected that a quick google session would immediately deliver the standard solution for this situation, but it didn't go this way.

The problem: I want Open Session in View for an JSF/Spring application. Ok, I know there is something fishy about open session in view, but believe me, for this application this is just fine. There is a chance that the application will become a portlet eventually, so I didn't want to have to handle portlet and servlet filters issues too. Instead, I want to use the convenient hooks provided by JSF to open and close the hibernate session - phase listeners. Happily, the Spring-provided OpenSessionInViewFilter reveals the technicalities of how Spring deals with the hibernate session factory.

Here is the result:

public class HibernateRestoreViewPhaseListener implements PhaseListener {
    public void afterPhase(PhaseEvent event) {
}

protected SessionFactory lookupSessionFactory() {
    FacesContext context = FacesContext.getCurrentInstance();
    ServletContext servletContext = (ServletContext) context.getExternalContext().getContext();
    WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
    return (SessionFactory) wac.getBean("hibernate-session-factory", SessionFactory.class);
}

public void beforePhase(PhaseEvent event) {
    SessionFactory sessionFactory = lookupSessionFactory();
    if (!TransactionSynchronizationManager.hasResource(sessionFactory)) {
        Session session = getSession(sessionFactory);
        TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
    }
}

public PhaseId getPhaseId() {
    return PhaseId.RESTORE_VIEW;
}

protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
    Session session = SessionFactoryUtils.getSession(sessionFactory, true);
    session.setFlushMode(FlushMode.MANUAL);
    return session;
}

The session gets closed when Render Response phase is finished:

public class HibernateRenderResponsePhaseListener implements PhaseListener {

    public void afterPhase(PhaseEvent event) {
        SessionFactory sessionFactory = lookupSessionFactory();
        SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
        closeSession(sessionHolder.getSession(), sessionFactory);
    }

    ...

}

Don't forget to register the listeners in faces-config.xml

<lifecycle>
    <phase-listener>
        ...HibernateRestoreViewPhaseListener
    </phase-listener>
    <phase-listener>
        ...HibernateRenderResponsePhaseListener
    </phase-listener>
</lifecycle>

Upvotes: 1

Michael Pralow
Michael Pralow

Reputation: 6630

do you have configured a transaction ? see http://justsomejavaguy.blogspot.com/2010/04/lazy-loading-under-spring.html

Upvotes: 0

Related Questions