Предотвращение сериализации дерева компонентов для определенных частей приложения

Можно ли явно запретить 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)

Бонусный вопрос: нормально ли делать резервную копию beans Serializable? Должно ли это предотвратить сериализацию/десериализацию этих?

Некоторая предыстория:

У нас есть группа сторонних классов, которые нам необходимо предоставить в JSF. Проблема в том, что мы не можем напрямую использовать эти классы на страницах JSF, потому что они не реализуют интерфейс Serializable и, следовательно, будут/должны потерпеть неудачу, если среда выполнения JSF решит сериализовать/десериализовать страницу и дерево компонентов. Классы "закрыты", и нам не разрешено изменять их.

Запуск Mojarra 2.0.2.

Ответ 1

Javabeans находится под spec, который должен реализовывать 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, так как именно они нарушают стандарты/спецификации).

Ответ 2

Я не знаю, чего вы ожидаете, если члены класса (например, nonSerializableClassInstance) не будут сериализованы. Конечно, вы можете пометить их как transient.

Цель управляемого bean состоит в том, чтобы удерживать состояние приложения - вы потеряете состояние, если некоторые члены не будут сериализованы (если серверу необходимо это делать).