Предотвращение сериализации дерева компонентов для определенных частей приложения
Можно ли явно запретить 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 состоит в том, чтобы удерживать состояние приложения - вы потеряете состояние, если некоторые члены не будут сериализованы (если серверу необходимо это делать).