Question

I have been searching for a while by now. I have found that OpenSessionInViewFilter should do the trick, but anyway it seems not be working in my case.

I also have found some posts that states that manual initialization helps, but I do not understand how to do this given that the repository is an interface and It seems to be implemented somewhere I don't know (I seem to be unable to find where to start to look for this point).

I'm working with a Spring Roo - jsf - hibernate application. In some page I am getting the following error in the console:

SEVERE: javax.el.ELException: /pages/dossier.xhtml @76,72 value="#{dossierDescription.documentTypesList}": Error reading 'documentTypesList' en el tipo co.qcsc.spatha.domain.dossier.DossierDescription feb 01, 2014 4:50:43 PM com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback visit SEVERE: javax.el.ELException: /pages/dossier.xhtml @76,72 value="#{dossierDescription.documentTypesList}": Error reading 'documentTypesList' en el tipo co.qcsc.spatha.domain.dossier.DossierDescription

Searching for the reason I arrived to this:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: co.qcsc.spatha.domain.dossier.DossierDescription.documentTypes, could not initialize proxy - no Session

Since this is Roo, it is already with an OpenSessionInViewFilter, in the web.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>spatha</display-name>
  <description>Roo generated spatha application</description>
  <context-param>
    <param-name>defaultHtmlEscape</param-name>
    <param-value>true</param-value>
  </context-param>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
  </context-param>
  <context-param>
    <param-name>primefaces.THEME</param-name>
    <param-value>cupertino</param-value>
  </context-param>
  <filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
  </filter-mapping>
  <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>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>ReportServlet</servlet-name>
    <servlet-class>co.qcsc.spatha.web.servlet.ReportServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>ReportServlet</servlet-name>
    <url-pattern>/clients.pdf</url-pattern>
  </servlet-mapping>

  <session-config>
    <session-timeout>10</session-timeout>
  </session-config>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
</web-app>

The class:

@RooJavaBean
@RooToString
@RooJpaEntity
public class DossierDescription {

    @NotNull
    @Size(min = 2)
    private String name;

    @ManyToOne
    private Client client;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "dossierDescription", fetch = FetchType.LAZY)
    private Set<DocumentType> documentTypes = new HashSet<DocumentType>();

    @NotNull
    private Boolean valid;

    public List<DocumentType> getDocumentTypesList() {
        List<DocumentType> list = new ArrayList<DocumentType>();
        list.addAll(getDocumentTypes());
        return list;
    }

}

Since I have Repository and Service Layers, I have, as you could imagine:

public class DossierDescriptionServiceImpl implements DossierDescriptionService {
}

@RooJpaRepository(domainType = DossierDescription.class)
public interface DossierDescriptionRepository {
}

The aspect for the Repository is (this one I do not understand at all):

privileged aspect DossierDescriptionRepository_Roo_Jpa_Repository {

    declare parents: DossierDescriptionRepository extends JpaRepository<DossierDescription, Long>;

    declare parents: DossierDescriptionRepository extends JpaSpecificationExecutor<DossierDescription>;

    declare @type: DossierDescriptionRepository: @Repository;

}

In the relevant part of the xhtml I have:

  <h:panelGrid id="createPanelGrid" columns="2" styleClass="dialog" columnClasses="col1,col2">
    <h:outputText value="#{app.label_specialty}" />
    <p:autoComplete id="specialtyInput"
            value="#{dossierMB.dossier.specialty.specialty}"
            completeMethod="#{dossierMB.completeSpecialty}"
            dropdown="true" var="specialty" required="false"
            itemLabel="#{specialty.name}" itemValue="#{specialty}"
            converter="co.qcsc.spatha.web.mb.converter.SpecialtyConverter"/>
    <p:tabView id="dossierDescriptionsTabView" var="dossierDescription"
            value="#{dossierMB.client.dossierDescriptionsList}">
        <p:tab id="dossierDescriptionTab" title="#{dossierDescription.name}">
            <p:dataTable id="dossierList" value="#{dossierDescription.documentTypesList}"
                    var="documentType" resizableColumns="false" paginator="true"
                    paginatorTemplate=" {CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
                    rowsPerPageTemplate="5,10,25,50" rows="10">
               <p:column>
                   <f:facet name="header">
                       <h:outputText value="#{app.label_documentType}" />
                   </f:facet>
                    <h:outputText value="#{documentType.name}"/>
               </p:column>
            </p:dataTable>
        </p:tab>
    </p:tabView>
  </h:panelGrid>

And the correspondant ManagedBean is:

@RooSerializable
@RooJsfManagedBean(entity = Dossier.class, beanName = "dossierMB")
public class DossierMB {

    @Autowired
    PurchaseOrderService poService;

    @Autowired
    ClientService clientService;

    @Autowired
    SpecialtyService specialtyService;

    private Client client;
    private List<PurchaseOrder> purchaseOrders;
    private PurchaseOrder purchaseOrder;
    private Dossier dossier;
    private OrderItem orderItem;

    public List<Client> getClients() {
        return clientService.findAllClients();
    }

    public String displayConsultPO() {
        return "consultPO";
    }

    public String findPurchaseOrders() {
        purchaseOrders = poService.findPurchaseOrderByClient(client);
        return "consultPO";
    }

    public String displayCreateDialog() {
        if (orderItem.getDossiers() == null){
            orderItem.setDossiers(new HashSet<Dossier>());
        }
        dossier = new Dossier();
        return "dossier";
    }

    public List<Specialty> completeSpecialty(String query) {
        List<Specialty> suggestions = new ArrayList<Specialty>();
        for (Specialty specialty : specialtyService.findAllSpecialtys()) {
            String specialtyStr = String.valueOf(specialty.getName());
            if (specialtyStr.toLowerCase().contains(query.toLowerCase())) {
                suggestions.add(specialty);
            }
        }
        return suggestions;
    }

    public Client getClient() {
        return client;
    }

    public void setClient(Client client) {
        this.client = client;
    }

    public List<PurchaseOrder> getPurchaseOrders() {
        return purchaseOrders;
    }

    public void setPurchaseOrders(List<PurchaseOrder> purchaseOrders) {
        this.purchaseOrders = purchaseOrders;
    }

    public PurchaseOrder getPurchaseOrder() {
        return purchaseOrder;
    }

    public void setPurchaseOrder(PurchaseOrder purchaseOrder) {
        this.purchaseOrder = purchaseOrder;
    }

    public OrderItem getOrderItem() {
        return orderItem;
    }

    public void setOrderItem(OrderItem orderItem) {
        this.orderItem = orderItem;
    }
}

For completion, this is the relevant part of applicationContext.xml:

<bean class="org.springframework.orm.jpa.JpaTransactionManager"
    id="transactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven mode="aspectj"
    transaction-manager="transactionManager" />
<bean
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    id="entityManagerFactory">
    <property name="persistenceUnitName" value="persistenceUnit" />
    <property name="dataSource" ref="dataSource" />
</bean>

The stacktrace:

WARNING: #{dossierMB.displayCreateDialog}: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: co.qcsc.spatha.domain.dossier.DossierDescription.documentTypes, could not initialize proxy - no Session
javax.faces.FacesException: #{dossierMB.displayCreateDialog}: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: co.qcsc.spatha.domain.dossier.DossierDescription.documentTypes, could not initialize proxy - no Session
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
    at javax.faces.component.UICommand.broadcast(UICommand.java:315)
    at javax.faces.component.UIData.broadcast(UIData.java:1093)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:180)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    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:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)
Caused by: javax.faces.el.EvaluationException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: co.qcsc.spatha.domain.dossier.DossierDescription.documentTypes, could not initialize proxy - no Session
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
    ... 31 more
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: co.qcsc.spatha.domain.dossier.DossierDescription.documentTypes, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:124)
    at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:180)
    at co.qcsc.spatha.web.mb.DossierMB.displayCreateDialog(DossierMB.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:278)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:274)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
    ... 32 more

Thanks for reading,

Was it helpful?

Solution

This means someone is closing the entity manager created by OpenEntityManagerInView before it reaches the view rendering phase.

OpenEntityManagerInView is only compatible with certain transaction managers, the javadoc mentions JpaTransactionManagerand JtaTransactionManager, have a look at it for further details.

This is normal because binding an entity manager to thread is not sufficient, the transaction manager needs to know that it should look first in the thread before creating a new EM.

There needs to be a level of coordination and compatibility between the transaction manager and the filter.

So one explanation is that the transaction manager being used in not compatible with OpenEntityManagerInView.

Another explanation is that the entity manager is being closed in the application code directly, using EntityManager.close().

In all cases one thing seems sure: the reason for the problem is that someone is closing the entity manager.

EDIT:

The problem can also be caused by a session scoped bean that is initialized in one request, left in the session and accessed in a new HTTP request. The initial session on the first request is closed when the first request completes, causing the lazy initialization exception on the second request.

You can troubleshoot it further by:

  • check if the transaction manager is compatible with the filter

  • make sure em.close() is not manually called in the application

  • put a breakpoint on EntityManagerImpl.close(), scroll down the stack trace when it's hit and see who is closing it.

OTHER TIPS

The problem is when you try to access documentTypes there is no session on load data from DB. So, you have 3 solutions:

  1. Change the loading-mode of documentTypes to EAGER
  2. Use a @PostLoad to load the list (which is almost the same than previous options)
  3. Force to create a connection before access the LAZY property:


    @Transactional
    public List getDocumentTypesList() {
        DossierDescription connected = DossierDescription.findDossierDescription(getId);
        List list = new ArrayList();
        list.addAll(connected.getDocumentTypes());
        return list;
    }


Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top