防止应用程序的某些部分的组件树序列化

时间:2011-01-04 12:41:29

标签: jsf serialization jsf-2

是否有可能明确拒绝JSF序列化某些组件树?目前我正在将一个不可序列化的对象传递给<h:inputText>

<h:inputText value="#{nonSerializableBean.nonSerializableClassInstance}" />

点击几下后会发生什么(在视图恢复期间):

javax.faces.FacesException: Unexpected error restoring state for component
with id configurationForm:j_idt292:j_idt302:field.  Cause:
java.lang.IllegalStateException: java.lang.InstantiationException:
my.namespace.NonSerializableClass

我认为这是因为JSF无法恢复nonSerializableClassInstance

Caused by: java.lang.IllegalStateException: java.lang.InstantiationException: com.foobar.utils.text.Period
at javax.faces.component.StateHolderSaver.restore(StateHolderSaver.java:110)
at javax.faces.component.ComponentStateHelper.restoreState(ComponentStateHelper.java:292)
at javax.faces.component.UIComponentBase.restoreState(UIComponentBase.java:1444)
at javax.faces.component.UIOutput.restoreState(UIOutput.java:255)
at javax.faces.component.UIInput.restoreState(UIInput.java:1359)

一个额外的问题:是否可以将支持bean序列化?那么这会阻止这些序列化/反序列化吗?

一些背景知识:

我们需要在JSF中提供一些第三方类来提供表单。问题是我们不能直接在JSF页面上使用这些类,因为它们不实现Serializable接口,因此如果JSF运行时决定序列化/反序列化页面和组件树,它将/应该失败。这些类是“封闭的”,我们不允许修改它们。

运行Mojarra 2.0.2。

2 个答案:

答案 0 :(得分:4)

spec的Javabeans应该实现Serializable。 JSF遵循/遵守此规范。

  

这些类已“关闭”,我们不允许修改它们。

最好的办法是将其包装为实现transient的类的Serializable属性,并相应地实现writeObject()readObject()

public class SerializableClass implements Serializable {

    private transient NonSerializableClass nonSerializableClass;

    public SerializableClass(NonSerializableClass nonSerializableClass) {
        this.nonSerializableClass = nonSerializableClass;
    }

    public NonSerializableClass getNonSerializableClass() {
        return nonSerializableClass;
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject();
        oos.writeObject(nonSerializableClass.getProperty1());
        oos.writeObject(nonSerializableClass.getProperty2());
        // ...
    }

    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
        ois.defaultReadObject();
        nonSerializableClass = new NonSerializableClass();
        nonSerializableClass.setProperty1((String) ois.readObject());
        nonSerializableClass.setProperty2((String) ois.readObject());
        // ...
    }

}

最后使用该类。你最终可以让它extends NonSerializableClass,然后通过一个不错的IDE自动生成委托方法。

无论哪种方式,它只会是很多不透明和样板代码,但是因为你不允许修改这些类...(我个人只是推动第三方的东西让他们所谓的所谓的Javabeans实施Serializable,因为他们违反了标准/规范。

答案 1 :(得分:1)

如果班级成员(例如nonSerializableClassInstance)未被序列化,我不知道您的期望。 当然,您可以将它们标记为transient

托管bean的目的是保持应用程序状态 - 如果某些成员没有被序列化(如果服务器需要这样做),您将失去状态。