每次按钮从backing-bean调用操作时都会出错。 仅适用于具有视图范围的bean,我没有找到修复它的方法,而不会对代码中的其他模块进行回归。
DefaultFacele E Exiting serializeView - Could not serialize state: javax.faces.component.html.HtmlInputText
java.io.NotSerializableException: javax.faces.component.html.HtmlInputText
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
或者:
com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0014E: Uncaught service() exception
root cause Faces Servlet: ServletException: /jspFiles/jsf/Deployments/editQueue.faces No saved view state could be found for the view identifier /jspFiles/jsf/Deployments/editQueue.faces
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:205)
Caused by: javax.faces.application.ViewExpiredException: /jspFiles/jsf/Deployments/editQueue.faces No saved view state could be found for the view identifier: /jspFiles/jsf/Deployments/editQueue.faces
at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute (RestoreViewExecutor.java:128)
faces-config.xml中
<managed-bean>
<managed-bean-name>pc_EditQueue</managed-bean-name>
<managed-bean-class>pagecode.jspFiles.jsf.deployments.EditQueue</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
<managed-property>
<property-name>queueDeploymentBean</property-name>
<value>#{queueDeploymentBean}</value>
</managed-property>
</managed-bean>
的web.xml
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>true</param-value>
</context-param>
豆:
@ManagedBean
@ViewScoped
public class EditQueue extends PageCodeBase implements Serializable {
private static final long serialVersionUID = -1L;
public String doButtonAddAction() {
// calls manager (long)
FacesUtil.setViewMapValue("queueDeploymentBean", queueDeploymentBean);
return "";
}
我读了这个suggestion来将SERIALIZE_STATE_IN_SESSION设置为false,实际上这个解决方案适用于这个视图范围bean。然而,此修复成本很高:应用程序中的许多现有模块不再起作用,因此我无法在此处使用此修复程序。观察到的一些回归是:
// returns null must be changed with FacesUtil.getSessionMapValue("userId");
getSessionScope().get("userId");`
// returns null must be changed with FacesUtil.getViewMapValue("linkerBean");
linkerBean = (Linker) getManagedBean("linkerBean");`
// NPE so must be changed with FacesContext.getCurrentInstance().addMessage(...)
getFacesContext().addMessage(...)`
所以我的问题是:
是否有另一种解决方案让我的视图范围bean工作(不必将它们更改为请求范围或其他)?
WebSphere 8.0.0.3, Java 1.6.0, JSF 2.0, RichFaces 4.2.3.Final
答案 0 :(得分:4)
为什么NotSerializableException即使bean实现了Serializable?
不仅bean需要可序列化,而且它的所有属性(及其所有嵌套属性等)也必须是可序列化的。可以在异常消息中轻松找到违规的非序列化类的名称:
java.io.NotSerializableException: javax.faces.component.html.HtmlInputText
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
这表明您将<h:inputText>
组件绑定到bean上,如下所示:
<h:inputText binding="#{bean.fooInput}" ...>
private UIComponent fooInput;
当bean不在请求范围内时,这确实是非法的。 UIComponent
个实例是请求作用域,可能不会在多个请求之间共享。此外,UIComponent
个实例不可序列化。只有他们的状态,但JSF会自己担心这一切。
您必须删除fooInput
属性,并且您需要针对该问题寻找不同的解决方案,您错误地认为将该组件绑定到视图范围bean将是正确的解决方案。
如果您打算在视图中的其他位置访问它,例如#{bean.fooInput.value}
,然后将其绑定到Facelet范围,而不需要bean属性:
<h:inputText binding="#{fooInput}" ...>
它可以通过#{fooInput.xxx}
在同一视图中的其他位置使用。
<h:inputText ... required="#{empty fooInput.value}" />
如果您打算在bean中以编程方式设置一些组件属性,例如fooInput.setStyleClass("someClass")
或fooInput.setDisabled(true)
,那么您应该绑定视图中的特定属性而不是整个组件:
<h:inputText ... styleClass="#{bean.styleClass}" />
...
<h:inputText ... disabled="#{bean.disabled}" />
如果你绝对肯定你需要在bean中获取整个UIComponent
实例的手,无论出于何种原因,那么在方法局部范围内手动抓取它而不是绑定它:
public void someMethod() {
UIViewRoot view = FacesContext.getCurrentInstance().getViewRoot();
UIComponent fooInput = view.findComponent("formId:fooInputId");
// ...
}
但更好地提出问题或寻找答案如何以不同方式解决具体问题,而无需在辅助bean中获取整个组件。
关于ViewExpiredException
,这有不同的理由,在javax.faces.application.ViewExpiredException: View could not be restored中进一步阐述。