我一直在寻找一段时间。我发现OpenSessionInViewFilter应该可以解决这个问题,但无论如何它似乎不适用于我的情况。
我也发现一些帖子说明手动初始化有帮助,但我不明白如何做到这一点,因为存储库是一个接口,它似乎是在我不知道的地方实现(我似乎无法找到从哪里开始寻找这一点。)
我正在使用Spring Roo-jsf-hibernate应用程序。在某些页面中,我在控制台中收到以下错误:
严重:javax.el.ELException:/pages/dossier.xhtml @ 76,72 value =“#{dossierDescription.documentTypesList}”:读取错误 'documentTypesList'en el tipo co.qcsc.spatha.domain.dossier.DossierDescription feb 01,2014 4:50:43 下午 com.sun.faces.context.PartialViewContextImpl $ PhaseAwareVisitCallback 访问SEVERE:javax.el.ELException:/pages/dossier.xhtml @ 76,72 value =“#{dossierDescription.documentTypesList}”:读取错误 'documentTypesList'en el tipo co.qcsc.spatha.domain.dossier.DossierDescription
搜索我到达此处的原因:
org.hibernate.LazyInitializationException:懒得初始化 角色集合: co.qcsc.spatha.domain.dossier.DossierDescription.documentTypes,可以 不初始化代理 - 没有会话
由于这是Roo,它已经在web.xml中使用了OpenSessionInViewFilter:
<?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>
班级:
@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;
}
}
由于我有存储库和服务层,我有,你可以想象:
public class DossierDescriptionServiceImpl implements DossierDescriptionService {
}
@RooJpaRepository(domainType = DossierDescription.class)
public interface DossierDescriptionRepository {
}
存储库的方面是(这个我根本不理解):
privileged aspect DossierDescriptionRepository_Roo_Jpa_Repository {
declare parents: DossierDescriptionRepository extends JpaRepository<DossierDescription, Long>;
declare parents: DossierDescriptionRepository extends JpaSpecificationExecutor<DossierDescription>;
declare @type: DossierDescriptionRepository: @Repository;
}
在xhtml的相关部分我有:
<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>
对应的ManagedBean是:
@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;
}
}
完成后,这是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>
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
感谢阅读,
答案 0 :(得分:0)
这意味着某人正在关闭OpenEntityManagerInView
创建的实体管理器,然后才能进入视图呈现阶段。
OpenEntityManagerInView
仅与某些交易管理器兼容,javadoc提到JpaTransactionManager
和JtaTransactionManager
,请查看详细信息。
这是正常的,因为将实体管理器绑定到线程是不够的,事务管理器需要知道它应该在创建新EM之前先在线程中查找。
事务管理器和过滤器之间需要有一定程度的协调和兼容性。
因此,一种解释是使用的事务管理器与OpenEntityManagerInView
不兼容。
另一种解释是,使用EntityManager.close()
直接在应用程序代码中关闭实体管理器。
在所有情况下,有一件事似乎是肯定的:问题的原因是某人正在关闭实体经理。
修改强>
问题也可能是由会话范围的bean引起的,该bean在一个请求中初始化,留在会话中并在新的HTTP请求中访问。第一个请求的初始会话在第一个请求完成时关闭,导致第二个请求的延迟初始化异常。
您可以通过以下方式进一步排查:
检查事务管理器是否与过滤器兼容
确保未在应用程序中手动调用em.close()
在EntityManagerImpl.close()
上放置一个断点,当它被击中时向下滚动堆栈跟踪,看看谁正在关闭它。
答案 1 :(得分:0)
问题是当您尝试访问documentTypes
时,没有来自DB的加载数据会话。所以,你有3个解决方案:
documentTypes
的加载模式更改为EAGER @PostLoad
加载列表(与以前的选项几乎相同)
@Transactional
public List getDocumentTypesList() {
DossierDescription connected = DossierDescription.findDossierDescription(getId);
List list = new ArrayList();
list.addAll(connected.getDocumentTypes());
return list;
}