View scope: java.io.NotSerializableException: javax.faces.component.html.HtmlInputText

心已入冬 提交于 2019-12-02 01:51:55
BalusC

why the NotSerializableException even though the bean implements Serializable ?

Not only the bean needs to be serializable, but all of its properties (and all their nested properties etc) must also be serializable. The name of the offending non-serializable class can easily be found in the exception message:

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

This suggests that you're binding a <h:inputText> component to the bean like below:

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

This is indeed illegal when the bean is not in request scope. UIComponent instances are request scoped and may not be shared across multiple requests. Moreover, UIComponent instances are not serializable. Only their state is, but JSF will worry about that all by itself.

You must remove the fooInput property and you need to look for a different solution for the problem for which you incorrectly thought that binding the component to a view scoped bean would be the right solution.

  • If you intend to access it elsewhere in the view, e.g. #{bean.fooInput.value}, then just bind it to the Facelet scope without the need for a bean property:

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

    It'll be available elsewhere in the same view via #{fooInput.xxx}.

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

  • If you intend to set some component attribute programmatically inside the bean, e.g. fooInput.setStyleClass("someClass"), or fooInput.setDisabled(true), then you should be binding the specific attribute in the view instead of the whole component:

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

  • If you are absolutely positive that you need to get a hand of whole UIComponent instance in the bean for whatever reason, then manually grab it in method local scope instead of binding it:

    public void someMethod() {
        UIViewRoot view = FacesContext.getCurrentInstance().getViewRoot();
        UIComponent fooInput = view.findComponent("formId:fooInputId");
        // ...
    }
    

    But better ask a question or search for an answer how to solve the concrete problem differently without the need to grab a whole component in the backing bean.

See also:


As to the ViewExpiredException, this has different grounds which is further elaborated in javax.faces.application.ViewExpiredException: View could not be restored.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!