问题
I am looking for some assistance or guidance on the best way to handle collections of objects in Wicket that won't have a devastating impact on session size. Obviously wrapping an object with any of Wicket's IModel classes is ideal, but what is the best way to do that when working with a collection of objects (e.g. a collection of search results).
I have had success using LoadableDetachableModel when working with an individual object, but I appear to be getting a java.io.NotSerializableException intermittently when shutting down Tomcat. Initially, I thought I was safe but the exception being thrown suggests otherwise.
This is the code (edited for brevity):
public class CandidateSearch extends BasicPage {
private static final long serialVersionUID = 1L;
private CandidateService service = new CandidateService();
public CandidateSearch() {
ListView<Candidate> listView = new ListView<Candidate>("candidates", service.search()){
private static final long serialVersionUID = 1L;
@Override
protected void populateItem(ListItem<Candidate> item) {
Candidate candidate = (Candidate) item.getModelObject();
PageParameters pars = new PageParameters();
pars.add("id", candidate.getId());
Link<String> candidateLink = new BookmarkablePageLink<String>("candidateLink", CandidateDetails.class, pars);
candidateLink.add(new Label("candidateId", "ID-" + new Long(candidate.getId()).toString()));
item.add(candidateLink);
item.add(new Label("name", candidate.getFirstName() + " " + candidate.getLastName()));
item.add(new Label("location", candidate.getCity() + ", " + candidate.getState()));
}
};
add(listView);
}
}
NOTE: service.search returns an java.util.List typed as Candidate.
回答1:
When you construct the ListView
like that, your Candidate
objects will not be detachable...that's why you're getting the java.io.NotSerializableException
.
I'm not sure if this is best practices or not, but my strategy is to convert the list of objects into a LoadableDetachableModel
of a List. I have a utility method like this:
public static <T> IModel<? extends List<T>> convertToListViewModel(List<T> objects) {
final Class<? extends List> listClass = objects.getClass();
// NOTE: you will need to implement the toLoadableDetachableModels method
List<IModel<T>> asModels = toLoadableDetachableModels(objects);
return new LoadableDetachableModel<List<T>>() {
@Override
protected List<T> load() {
List<T> results = ClassUtils.newInstance(listClass);
for(IModel<T> model : asModels) {
results.add(model.getObject());
}
return results;
}
};
}
You could use this method to wrap the results of service.search()
, and then not only should you should be rid of that error, but your objects will require much less session storage space.
回答2:
The process suggested by stevevis of converting your list to a [LoadableDetachableModel][1]
is reasonable if you want to stick with something close to your current basic architecture.
A bigger change that would work as well and for some purposes maybe better would be to switch to using a DataView, so that the data shown comes from an implementation of IDataProvider as needed and is not held as you are doing in a List
at all.
Good example code for these and other repeaters can be found at the wicket examples site.
来源:https://stackoverflow.com/questions/14166942/what-is-the-correct-way-to-handle-collections-of-model-objects-in-wicket