How wicket LoadableDetachable model works

java, wicket

Solution

`LoadableDetachableModel` caches the retrieved object for the duration it is attached. When you `load` the data from the database, all items are there. Then you execute a query to delete a record, but don't update the list. So either you have to change your `onClick` handler to also update the retrieved list, or just detach the model.

There is no magic in LoadableDetachableModel. Take a look at the code below:

List<Person> people = dao.getListOfPeopleAttendingParty();

// assume that the number of people attending the party is 4
assert people.size() == 4;

Person guest = people.get(0);
dao.delete(guest);

// what is the number of people attending the party now?
assert people.size() == ?;

What do you think that `people.size()` is now?

The execution of LoadableDetachableModel is not any different than the code snippet above:

List<Person> people = peopleModel.getObject(); // is called by ListView

// assume that the number of people attending the party is 4
assert people.size() == 4;

Person guest = people.get(0);
dao.delete(guest);

// what is the number of people attending the party now?
assert people.size() == ?;

So: no magic involved, just plain Java and ordinary logic.

PS. The answer to both questions is 4 even though the database no longer holds the guest

Problem

I am trying to understand how Wicket LoadableDetachable model is working. What i understand from the Wicket documentation is in a normal scenario , when the request completes the processing wicket will auto serialize the all components with associated model values. This one will consumes more memory . If we use the LoadableDetachable model at the time of serialization the model values will not get serialized. Is this right? . So it will detach the model object automatically . So For the next request the model value will be reload again automatically? See my below code. ``` public class ProductListPanel extends Column<Product> { @SpringBean private ProductService productService; private List productList; public ProductListPanel(String id) { super(id); class ProductModel extends LoadableDetachableModel { @Override public void detach() { // TODO Auto-generated method stub productList = null; System.out.print("Called Detach Object\n"); } @Override protected Object load() { // TODO Auto-generated method stub productList = productService.findAll(); System.out.print("Called Get Object\n"); return productList; } } System.out.print("Before creating also calling\n"); final ProductModel productModel = new ProductModel(); ListView view = new ListView("list", productModel) { protected void populateItem(ListItem item) { System.out.print("\nBefore start also calling\n"); System.out.print("Before this one is callling \n"); Product result = (Product) item.getModelObject(); item.add(new Label("code", result.getCode())); item.add(new Label("name", result.getName())); final Link deleteLink = new Link("remove", item.getModel()) { @Override public void onClick() { Product product = (Product) getModelObject(); productService.delete(product); } }; item.add(deleteLink); } }; add(view); Link addProductLink = new Link("addProduct") { @Override public void onClick() { // TODO Auto-generated method stub setResponsePage(new AddProduct()); } }; add(addProductLink); productModel.detach(); } } ``` In the above code i am listing all the products from the DB. and i am having Remove link for each product , when we are clicking that link i am removing the product from the DB. After clicking the Remove link the page is not getting refreshed means it still showing the deleted product . if i add this line productModel.detach(); then it is working properly . My question here is why i have to call productModel.detach(); manually? LoadableDetachableModel suppose do automatically right? Please help me

Original source