How wicket LoadableDetachable model works

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

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

This topic is a wide one. LoadableDetachableModel is great for read-access to data since you get the advantage of traversing the load method only once per request. However, this may not be enough depending on what you want to achieve.

Since LoadableDetachableModel stores the once loaded value within a member variable for the duration of the request, it may not see updates to the underlying data that occur within the same request. Whether or not this is a problem depends of course on the timing of the calls to getObject on the model instances involved. It should be a rather rare problem actually.

I think first one needs to consider the component structure and the model instances that are involved. There may be several possible designs to achieve the same thing.

Depending on what the component structure looks like and how many model instances get created and assigned to components, there may be more than one instance of a specific model within a request. Also, if page serialization IS activated, components that somehow cling to their model instances may end up with further instances of models, which in case of LoadableDetachableModels may become an issue within later requests.

It is in my opinion a good practice to inject model instances into the constructors of components and make sure that there are only as many model instances as really needed. Components that get a model instance passed in the constructor, but do not need it themselves, should simply delegate it to constructors of one or more relevant child components. The API of the component get defined quite clearly in the constructor using IModel typed parameters. The only drawback may be that the user of the component needs to pass a lot of models depending on what is going on. Certainly models may be wrapped in decorators for any kind of purposes by the components even in this pattern.

For some purposes LoadableDetachableModel may not be enough, i.e. solutions with more features should be considered for implementation, for example a CachedModel that looks into a cache before performing an actual load.

In realy complex component interplay situations or request handling situations, one may consider to implement a reset mechanism for the LoadableDetachableModel in an own specialized LoadableDetachableModel class. A timestamped reset token could be published into the request scope to notify other addressed model instances that they have to discard their member variable value and traverse the load method again when their getObject method gets called. Each model instance should only honor each token once per request, while more than one token may be issued per request.

Or consider the case that there is no caching layer to access the data and therefore somehow you need sophisticated caching in the frontend layer. One may consider to implement a CachedModel as a specialization of LoadableDetachableModel - i.e. it has three places to look for the model value in getObject, the member variable, then the cache and then finally the load method - with the additional feature to publish a timestamped reset token into the request scope to notify addressed CachedModels that they have to discard their member variable value before returning anything. This additional reset feature can make sure that after an update to a value the relevant CachedModel instances would discard their possibly stored value of their member variable and take look into the central cache.

Of course there are other ways to achieve certain things with models. It depends what you want to do, on your design and how many components within a page need the data in question at which points in time.

转载于:https://my.oschina.net/qq86931065/blog/132781

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值