jsf - 查看范围: java. io.NotSerializedException : javax. faces.component.html.HtmlInputText

标签 jsf serialization jsf-2 view-scope backing-beans

每次按钮从 backing-bean 调用操作时都会出现错误。 仅适用于具有 View 范围的 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>

bean :

@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,实际上此解决方案适用于此 View 范围 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(...)`

所以我的问题是:

  1. 即使 bean 实现了 Serialized,为什么还是会出现 NotSerializedException?

  2. 是否有办法仅将 SERIALIZE_STATE_IN_SESSION 参数应用于 Bean 的子集?

  3. 是否有另一种解决方案可以让我的 View 范围 bean 正常工作(无需将它们更改为请求范围或其他)?

    WebSphere 8.0.0.3, Java 1.6.0, JSF 2.0, RichFaces 4.2.3.Final

最佳答案

why the NotSerializableException even though the bean implements Serializable ?

不仅 bean 需要可序列化,而且它的所有属性(及其所有嵌套属性等)也必须可序列化。可以在异常消息中轻松找到有问题的不可序列化类的名称:

java.io.NotSerializableException: javax.faces.component.html.HtmlInputText
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)

这表明您正在绑定(bind) <h:inputText> bean 的组件如下所示:

<h:inputText binding="#{bean.fooInput}" ...>
private UIComponent fooInput;

当 bean 不在请求范围内时,这确实是非法的。 UIComponent实例是请求范围的,不能在多个请求之间共享。此外,UIComponent实例不可可序列化。只有他们的状态是,但 JSF 会自己担心这一切。

您必须删除 fooInput如果您错误地认为将组件绑定(bind)到 View 作用域 bean 是正确的解决方案,那么您需要寻找不同的解决方案来解决该问题。

  • 如果您打算在 View 中的其他位置访问它,例如#{bean.fooInput.value} ,然后只需将其绑定(bind)到 Facelet 范围,而不需要 bean 属性:

    <h:inputText binding="#{fooInput}" ...>
    

    它将在同一 View 的其他地方通过 #{fooInput.xxx} 提供。 .

    <h:inputText ... required="#{empty fooInput.value}" />
    

  • 如果您打算在 bean 内以编程方式设置某些组件属性,例如fooInput.setStyleClass("someClass") ,或fooInput.setDisabled(true) ,那么您应该绑定(bind) View 中的特定属性而不是整个组件:

    <h:inputText ... styleClass="#{bean.styleClass}" />
    ...
    <h:inputText ... disabled="#{bean.disabled}" />
    

  • 如果您绝对确定您需要整手UIComponent无论出于何种原因,bean 中的实例,然后在方法本地范围内手动获取它,而不是绑定(bind)它:

    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 中对此进行了进一步阐述。 .

关于jsf - 查看范围: java. io.NotSerializedException : javax. faces.component.html.HtmlInputText,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31485892/

相关文章:

java - 链接的奇怪行为 - 页面上显示的每个链接都附加了 URL

jsf - 带转换器的复合 JSF 组件

java - JSF2 ArrayList 的搜索方法

serialization - 为什么锁在Java中是可序列化的?

json - 如何从 DataContract 中排除类型信息?

sql-server-2008 - intellij 想法,生成具有关系的持久性映射

jsf - 我们可以直接在 JSF xhtml 文件中访问 session 范围变量吗

java.lang.IllegalStateException : CDI API is not available in this environment. 在 org.omnifaces.config.BeanManager

c - 试图将结构成员复制到 c 中的字节数组

jsf-2 - 为什么和号 (&) 需要在 JSF 中编码?有没有办法解决这个问题?