Do i have to detach wicket models, if they are used in local variables?
I am using PropertyModel and Compoundpropertymodel in my wicket application. I use them as local variables and not as members of the page classes. Do i have to override the onDetach() Function to detach the models when they are local? Or are only member variables serialized into the session?
Example:
TextField<String> title = new TextField<String>("title", new PropertyModel<String>(position, "title"));
title.setR开发者_运维问答equired(true);
form.add(positionTitle);
It's not clear to me why you want to detach the model of your TextField, as a TextField needs a model object to write submitted form values to. If you detach position
from the PropertyModel, then the TextField won't have a place to write its "title" value to after the user submits the form. You might want to provide more details about what position
is, where it was loaded from, and why it needs to be detached between request cycles. Common practice is to have a safely serializable model object for form components to write their values to.
If you do need to detach the model object of a PropertyModel at the end of each request, chain the PropertyModel to a LoadableDetachableModel. LDM will load a fresh model object for each request cycle based on your provided load()
method, and will then automatically null out its reference to that model object on detach to prevent serializing the model object. If you use a LoadableDetachableModel<Position>
as the model object of your PropertyModel, then the PropertyModel will detach the LoadableDetachableModel automatically and that will be enough to avoid serializing the position
object.
Note that you do not need to explicitly call detach()
on models like the one in your example; Wicket detaches the default models of all Components in the Page hierarchy automatically. By "default model", I mean a model that gets passed up the super(...)
chain and eventually becomes the model
argument of one of the Component(...)
constructors.
At the end of request processing, the Page calls detach()
on its children (and those children call detach()
on their children and so on). This method (defined in Component) calls detachModels()
, which in turn detaches the default model of the Component.
Standard Wicket components that commonly use more than one model will detach additional models during detachModels
. For example, if you pass DropDownChoice both a model to get/set the selected value, and a model of the list of choices, you will notice that DropDownChoice automatically detaches both of these models at the end of each request. This is because AbstractChoice#detachModel()
looks for and detaches a choices
model, if one has been set.
Chaining models also detach their chained models, so for example if you had
Form<User> userForm = new Form<User>("userForm", new CompoundPropertyModel<User>(new DetachableUserModel(...));
then the CompoundPropertyModel would be detached automatically by detachModels
, and that would in turn detach the DetachableUserModel.
Where you DO need to worry about manually detaching models is any case where you use additional models in your code that are neither the default model
of some component, nor chained into another model that is. This might be a concern if you are creating a new type of Component that has more than one model object.
In this instance, and in most uses of such models in Wicket, the initial assignment is to a local variable, but the object is put into something that is not local.
Your form
is almost certainly a field or contained in something that is, and is serialized into the session. It contains the title
field, which in turn contains the model.
So it will be serialized, and yes you should probably implement onDetach()
.
Edit:
As noted in a comment, what really matters is whether it is part of the component hierarchy of a page, rather than whether it is a field. It does on some level amount to the same thing, as the child components of a page or any other component are held in a field children
in the superclass org.apache.wicket.MarkupContainer
.
In your case, I would do :
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);
The detach()
are called in chain at the end of the request. Using a LoadableDetachableModel ensure that the position object is not referenced.
A trick: keep you domain object or value object non serializable. In development configuration, if you have serialization errors, it means that you keep references on these objects.
精彩评论