Results 1 to 10 of 10

Thread: LazyInitializationException in JPA-based UserDetailsService

  1. #1
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    667

    Question LazyInitializationException in JPA-based UserDetailsService

    I'm setting up a UserDetailsService that retrieves the user's details via JPA, as recommended by Ben. My service looks like this (where Person and Skill are my own Roo-managed entities):

    Code:
    public class JpaUserDetailsService implements UserDetailsService {
    
        @Override
        public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException
        {
            Person person = Person.find...; // find the person with this username (via JPA)
            Iterator<Skill> skills = person.getSkills().iterator(); // !!!
            ...
        }
    }
    The line marked "!!!" throws this error:

    Code:
    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: lazy.Person.skills, no session or session was closed
            at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
            at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
    
            at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:97)
            at org.hibernate.collection.PersistentSet.size(PersistentSet.java:139)
            at lazy.JpaUserDetailsService.loadUserByUsername(JpaUserDetailsService.java:22)
            at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:83)
            at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationPro
    vider.java:125)
            at org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:121)
            at org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:49)
            at org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:139)
            at org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:49)
            at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFi
    lter.java:98)
            at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java
    :200)
            at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356)
            at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
            at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356)
            at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
            at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356)
            at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:150)
            at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
            at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
            at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
            at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
            at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
            at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
            at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:726)
            at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
            at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:206)
            at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
            at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
            at org.mortbay.jetty.Server.handle(Server.java:324)
            at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
            at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
            at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:648)
            at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
            at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
            at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
            at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
    This surprised me, because Roo by default adds the following filter to web.xml:
    Code:
    <filter>
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    The LazyInitializationException is easily fixed by making my JpaUserDetailsService transactional (e.g. by adding the @Transactional annotation to it), but I'm unclear why that's necessary. Doesn't every thread already have an open Hibernate session (or EntityManager in JPA-speak) thanks to the OEMIV filter?
    Last edited by Andrew Swan; Feb 8th, 2010 at 10:11 PM. Reason: Clarified that the Person lookup is done using JPA
    Andrew Swan
    "Now is the EJB of our discontent made glorious Spring"

  2. #2
    Join Date
    Mar 2008
    Location
    Sydney, AU
    Posts
    974

    Default

    Have you enabled debug logging to see when and why the session is closed before you hit this lazy loaded boundary? How is the service layer registered in your application (@Service, @Repository)?
    Stefan Schmidt
    Software Engineer, Spring Roo
    SpringSource - a division of VMware
    twitter @schmidtstefan

  3. #3
    Join Date
    Mar 2008
    Location
    Sydney, AU
    Posts
    974

    Default

    Another thing you could try is to change the sequence of the spring security filter and the open entity manager in view filter in web.xml. Try placing the security filter after the jpa filter.

    -Stefan
    Stefan Schmidt
    Software Engineer, Spring Roo
    SpringSource - a division of VMware
    twitter @schmidtstefan

  4. #4

    Default

    I hit this problem today so swapped the filters round; this solves the problem. It seems that spring security calls the toString() method on the UserDetails instance and if you are using @RooToString then those lazy loaded associations are called in that method.

    Jon

  5. #5
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    667

    Question Swap these filters for new Roo apps?

    Thanks guys. I guess people have two ways to solve this now.

    Stefan, how about swapping the order of these filters by default for new Roo apps? A lot of people are going to want to use JPA in their UserDetailsService implementations in order to retrieve the logged-in user's roles, and are going to encounter this lazy-loading error (with the inevitable duplicate forum threads, etc.).
    Andrew Swan
    "Now is the EJB of our discontent made glorious Spring"

  6. #6
    Join Date
    Mar 2008
    Location
    Sydney, AU
    Posts
    974

    Default

    Yes, we should change the sequence of filters so it all works well together. Please open a Jira ticket for this.

    Thanks,
    Stefan
    Stefan Schmidt
    Software Engineer, Spring Roo
    SpringSource - a division of VMware
    twitter @schmidtstefan

  7. #7
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    667

    Thumbs up Logged.

    Logged as ROO-609.
    Andrew Swan
    "Now is the EJB of our discontent made glorious Spring"

  8. #8
    Join Date
    Mar 2008
    Location
    Sydney, AU
    Posts
    974

    Default

    Thanks Andrew! I'll review if we should do this in 1.1 or earlier.

    -Stefan
    Stefan Schmidt
    Software Engineer, Spring Roo
    SpringSource - a division of VMware
    twitter @schmidtstefan

  9. #9
    Join Date
    Mar 2008
    Location
    Sydney, AU
    Posts
    974

    Default

    Oh, I meant to write this reply in a different context. I'll certainly change this one for 1.0.2 release.

    -Stefan
    Stefan Schmidt
    Software Engineer, Spring Roo
    SpringSource - a division of VMware
    twitter @schmidtstefan

  10. #10
    Join Date
    Jan 2011
    Posts
    12

    Default

    Hi, all - I created my project with Roo 1.1.1 last month and my web.xml was created with the improper ordering so it doesn't look like it's made it into a release yet. Thanks for the post though - easily enough solved.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •