2

I´m getting a lazy initialization exception. A have a controller method with the annotation @Transactional, it invokes a service method ( it not has the @Transactional annotation), and finally inside that method I invoke another spring component (it checks if the user has the proper role).

In the project I used the @Transactional and i have no problems. But in this case i have the lazy initialization exception.

Am I missing something?

Here is the code:

and here is the method that is first executed. It has the @Transactional annotation

@Transactional
    public CompanyForm edit(){
        CompanyForm form = new CompanyForm();
        Company company = companyService.findMainOne(getLoggedUser());
        if (company != null) {
            if (company != null)
                modelMapper.map(company, form);
        }
        return form;
    }

This is the method in a service where the code is called

@Autowired
    private UserVisitorHasBussinessRole hasBussinessRole;

@Override
    public Company findMainOne(User user) {
        if (user == null)
            throw new NullPointerException("the user can not be null");
        user.accept(hasBussinessRole);
        List<Company> companies = this.companyRepository.findOwnedBy(user
                .getId());
        if (companies != null && companies.size() > 0)
            return companies.get(0);
        return null;
    }

This component checks if the user has the proper role. This is where i got the exception

@Component
public class UserVisitorHasBussinessRole implements UserVisitor {

    @Autowired
    private Messages messages;

    @Override
    public void visit(SystemUser user) {
        if(user == null || user.getUserRoles() == null || user.getUserRoles().isEmpty())
        {
            String message = messages.get("hasBussinesRoleVisitor.noRole");
            throw new RuntimeException(message);
        }
        Boolean hasRole = false;
        for (UserRole role : user.getUserRoles()) {
            if(role instanceof UserRoleBusiness){
                hasRole = true;
                break;
            }
        }
        if(!hasRole)
        {
            String message = messages.get("hasBussinesRoleVisitor.noRole");
            throw new RuntimeException(message);
        }
    }

    @Override
    public void visit(SocialUser user) {
        String message = messages.get("hasBussinesRoleVisitor.noRole");
        throw new RuntimeException(message);
    }

}

This is where the exception is thrown

user.getUserRoles().isEmpty()

The entity:

@Entity
@DiscriminatorValue(value = "BU")
public class SystemUser extends User {

    /**
     * 
     */
    private static final long serialVersionUID = 3845147625976106863L;

    // for joing the tables (many-to-many)
    @ManyToMany(cascade = CascadeType.ALL, targetEntity = UserRole.class)
    @JoinTable(name = "systemUser_userRole", joinColumns = { @JoinColumn(name = "system_user_id") }, inverseJoinColumns = { @JoinColumn(name = "role_Id") })
    private List<UserRole> userRoles;

    /**
     * the list of user roles
     * @return the user roles
     */
    public List<UserRole> getUserRoles() {
        return userRoles;
    }

    /***
     * set the list of user roles
     * @param userRoles the user roles
     */
    public void setUserRoles(List<UserRole> userRoles) {
        this.userRoles = userRoles;
    }
}

I'm getting the following exception

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at ar.com.held.model.user.User.accept(Unknown Source)
    at ar.com.held.service.implementation.CompanyServiceImpl.findMainOne(Unknown Source)
    at ar.com.held.service.implementation.CompanyServiceImpl$$FastClassByCGLIB$$d0027e0c.invoke(<generated>)
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
    at ar.com.held.service.implementation.CompanyServiceImpl$$EnhancerByCGLIB$$b15b3940_2.findMainOne(<generated>)
    at ar.com.held.controller.CompanyFlowController.edit(CompanyFlowController.java:28)
    at ar.com.held.controller.CompanyFlowController$$FastClassByCGLIB$$c3823c4.invoke(<generated>)
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
    at ar.com.held.controller.CompanyFlowController$$EnhancerByCGLIB$$5b3921c7_2.edit(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:69)
    at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:109)
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57)
    at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102)
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:97)
    at org.springframework.binding.expression.spel.SpringELExpression.getValue(SpringELExpression.java:84)
    at org.springframework.webflow.action.EvaluateAction.doExecute(EvaluateAction.java:75)
    at org.springframework.webflow.action.AbstractAction.execute(AbstractAction.java:188)
    at org.springframework.webflow.execution.AnnotatedAction.execute(AnnotatedAction.java:145)
    at org.springframework.webflow.execution.ActionExecutor.execute(ActionExecutor.java:51)
    at org.springframework.webflow.engine.ActionList.execute(ActionList.java:155)
    at org.springframework.webflow.engine.Flow.start(Flow.java:534)
    at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:366)
    at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:225)
    at org.springframework.webflow.executor.FlowExecutorImpl.launchExecution(FlowExecutorImpl.java:140)
    at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:193)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129)
    at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:311)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:101)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:173)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ar.com.held.model.user.SystemUser.userRoles, no session or session was closed
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:393)
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:385)
    at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:125)
    at org.hibernate.collection.internal.PersistentBag.isEmpty(PersistentBag.java:249)
    at ar.com.held.service.implementation.visitor.UserVisitorHasBussinessRole.visit(Unknown Source)
    ... 100 more

3 Answers 3

4

I solved using @LazyCollection(LazyCollectionOption.FALSE)

here is the code:

@ManyToMany(cascade = CascadeType.ALL, targetEntity = UserRole.class)
@JoinTable(name = "systemUser_userRole", joinColumns = { @JoinColumn(name = "system_user_id") }, inverseJoinColumns = { @JoinColumn(name = "role_Id") })
@LazyCollection(LazyCollectionOption.FALSE)
private List<UserRole> userRoles;

It is not the best solution but it works. The problem is that LazyCollection annotation is a Hibernate annotation and not a jpa one.

Thanks to all

Sign up to request clarification or add additional context in comments.

Comments

2

This happens when a lazy initialized object is read when the original transaction is already completed. In other words, when you return something from a method with @Transactional annotation all objects must be initialized (no way to access lazy objects after returning from the method). So use lazy="false" in this case to resolve the issue (or force lazy initialization inside the method).

3 Comments

Thanks! But how can i force lazy initialization inside the method? calling user.getUserRoles().size()?
Iterate through all connected items and call any getter except getId() which is already loaded. I would suggest to change hibernate mapping though, to make it lazy="false"
Well, i solved it. I have to use @LazyCollection(LazyCollectionOption.FALSE)
0

Add @Transactional to findMainOne and visit(SystemUser) so they both participate in the same transaction, thus giving them access to the session/entity-manager for lazily-loading related components. Or you can load those components that might be needed before calling findMainOne.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.