Нужно ли отсоединять модели калитки, если они используются в локальных переменных? - PullRequest
2 голосов
/ 31 июля 2011

Я использую PropertyModel и Compoundpropertymodel в своем приложении для калитки. Я использую их как локальные переменные, а не как члены классов страниц. Нужно ли переопределять функцию onDetach (), чтобы отсоединять модели, когда они локальные? Или только переменные-члены сериализуются в сеанс?

Пример:

TextField<String> title = new TextField<String>("title", new PropertyModel<String>(position, "title"));
title.setRequired(true);
form.add(positionTitle);

Ответы [ 3 ]

3 голосов
/ 02 августа 2011

Мне не понятно, почему вы хотите отсоединить модель вашего TextField, поскольку TextField нужен объект модели для записи отправленных значений формы.Если вы отсоедините position от PropertyModel, то TextField не будет иметь места для записи своего значения «title» после того, как пользователь отправит форму.Возможно, вы захотите предоставить более подробную информацию о том, что такое position, откуда он был загружен и почему его нужно отсоединять между циклами запросов.Обычная практика состоит в том, чтобы иметь надежно сериализуемый объект модели, чтобы компоненты формы могли записывать свои значения.

Если вам необходимо отсоединить объект модели PropertyModel в конце каждого запроса, добавьте PropertyModel в цепочку к LoadableDetachableModel,LDM загрузит новый объект модели для каждого цикла запроса на основе предоставленного вами метода load(), а затем автоматически отключит его ссылку на этот объект модели для предотвращения сериализации объекта модели.Если вы используете LoadableDetachableModel<Position> в качестве объекта модели вашей PropertyModel, то PropertyModel автоматически отключит LoadableDetachableModel, и этого будет достаточно, чтобы избежать сериализации объекта position.

Обратите внимание, что вам не нужноявно вызовите detach() на моделях, подобных той, что в вашем примере;Wicket автоматически отключает модели по умолчанию для всех компонентов в иерархии страниц.Под «моделью по умолчанию» я имею в виду модель, которая передается по цепочке super(...) и в конечном итоге становится аргументом model одного из конструкторов Component(...).

В конце обработки запросаСтраница звонит detach() своим детям (а эти дети звонят detach() своим детям и т. Д.).Этот метод (определенный в Компоненте) вызывает detachModels(), который, в свою очередь, отсоединяет модель компонента по умолчанию.

Стандартные компоненты Wicket, которые обычно используют более одной модели, будут отсоединять дополнительные модели в течение detachModels.Например, если вы передадите DropDownChoice как модель для получения / установки выбранного значения, так и модель списка вариантов выбора, вы заметите, что DropDownChoice автоматически отключает обе эти модели в конце каждого запроса.Это связано с тем, что AbstractChoice#detachModel() ищет и отсоединяет модель choices, если она была установлена.

Модели с цепочками также отсоединяют свои модели с цепочками, например, если у вас было

Form<User> userForm = new Form<User>("userForm", new CompoundPropertyModel<User>(new DetachableUserModel(...));

тогда CompoundPropertyModel будет автоматически отсоединен detachModels, и это, в свою очередь, отсоединит DetachableUserModel.

Если вам действительно нужно беспокоиться о ручном отсоединении моделей, в любом случае вы используете дополнительные модели в своем коде, которыене являются model по умолчанию для какого-либо компонента и не связаны какой-либо другой моделью.Это может быть проблемой, если вы создаете новый тип Компонента, который имеет более одного объекта модели.

2 голосов
/ 31 июля 2011

В этом случае, и в большинстве случаев использования таких моделей в Wicket, начальное присвоение выполняется локальной переменной, но объект помещается в нечто, что не локально.

Ваш form почти наверняка является полем или содержится в чем-то, что есть, и сериализуется в сеанс. Он содержит поле title, которое, в свою очередь, содержит модель.

Так что он будет сериализован, и да, вы, вероятно, должны реализовать onDetach().

Изменить:

Как отмечено в комментарии, действительно важно, является ли он частью иерархии компонентов страницы, а не является ли это полем. Это на некотором уровне равнозначно тому же, как дочерние компоненты страницы или любого другого компонента содержатся в поле children в суперклассе org.apache.wicket.MarkupContainer.

1 голос
/ 05 августа 2011

В вашем случае я бы сделал:

    IModel model = new CompoundPropertyModel(new LoadableDetachableModel(position){
        @Override protected Object load() { return null; }
    });
    Form form = new Form("form", model);
    form.add(
            new TextField("title")
                .setRequired(true));
    add(form);

detach() вызываются по цепочке в конце запроса. Используя LoadableDetachableModel, убедитесь, что на объект позиции не ссылаются.

Хитрость: не допускайте сериализации объекта домена или объекта значения. В конфигурации разработки, если у вас есть ошибки сериализации, это означает, что вы сохраняете ссылки на эти объекты.

...