0

I've been given this old Apache Wicket 1.5 web application.

All the URLs seem to end in ?xxx, where xxx is a number. This seems to be a Wicket "feature" that allows you to version / cache previously shown webpages. As nice as it might sound, in practical terms this is nothing more than a headache for all users involved, as even if the underlying data shown on the page changes and the user forces a page refresh, the old, stale page is still reloaded.

I've browsed online and in Wicket's docs it seems to be referred as "versioning".

I've tried to disable it by calling setVersioned(false) but it was of no avail -- I see no observable difference. Does anyone know how to get this to work?

Thanks

devoured elysium
  • 101,373
  • 131
  • 340
  • 557
  • You actually do not want to disable this. The pageId is not related to caching. It is something very important for Wicket to deal with server side state. Please explain what is the actual problem you try to solve. – martin-g Apr 08 '19 at 14:28
  • @martin-g The problem is that I have a screen with data. Users hit refresh expecting to see the updated data and it still shows things as they were when they first got into the page 10 minutes ago. – devoured elysium Apr 08 '19 at 14:38
  • 2
    This means the application does not use Wicket Models in a proper way. Google "Wicket dynamic versus static models". There is a nice Wiki page about it. – martin-g Apr 08 '19 at 17:27
  • Ah, I see. Isn't there a way to just avoid having wicket put the ?xxx on the links it generates? Because it seems like taking them out always forces wicket to refresh the data from the page. The web-application I was given is large and in maintenance-mode, there's really not much sense in touching it other than to make a quick fix here and there. – devoured elysium Apr 08 '19 at 19:18
  • One way to get rid of the page versioning in wicket URLS is to use ONE_PASS_RENDER as a render strategy. However this has some pretty big disadventages and I wouldn't recommend it. You might end up breaking more than fixing. See also https://stackoverflow.com/q/14585858 – OH GOD SPIDERS Apr 10 '19 at 08:32

2 Answers2

2

The problem is that your application caches the data into the models. In Wicket terminology this is called a static model.

For example:

Person person123 = personService.get(123);

// a static model
page.add(new Label("personMood", new Model(person123.getMood())));

Here the Label will always show the mood of the person at the time of instantiation of the Label. The person may change his/her mood in the next second but the Label will still show the old/cached value.

// a dynamic model
page.add(new Label("personMood", new Model<String>() {
  @Override public String getObject() {
     return person123.getMood();
  }
}));

here the Label will render the current mood of the person at every render of this label/page.

The pageId in the url tells Wicket which stateful page to lookup and load from the page store. Only stateful pages have such id. If you want to get rid of it then you should use only stateless components and behaviors in your page. There is wicket-devutils module which provides StatelessChecker to help you identify the reason when a Page becomes stateful by accident.

In your case I am not sure which solution would be easier - to rework the Model(s) or to make the page stateless. Usually the first is easier.

martin-g
  • 17,243
  • 2
  • 23
  • 35
0

I had a slightly different but somewhat similar issue.

I have a page that had a component that could be rendered with one of two component structures that were both extremely different. One was a simple 'Create' panel and the other was displaying the complex structure of the thing that was created.

Unfortunately the second panel could not be constructed without a valid object (the complex structure) to display but it was not available if it had not yet been constructed and whether it was constructed was based on the user explicitly clicking 'Create' in the create panel.

Initially I thought a page refresh after the user hit Create would do the trick but nope ... it uses the cached version of the page and does not rebuild the component structure for the new complex structure.

I did finally manage to get a page refresh working, generated from within the onClick event handler of the Create button:

@Override
public void onClick(AjaxRequestTarget ajaxRequestTarget)
{
    Page page = getPage();
    setResponsePage(page.getPageClass(), page.getPageParameters());
}

At first I tried:

setResponsePage(getPage());

but this did not work - it kept rerendering from the cache and showed the page without the complex structure's Wicket components

That version of setResponsePage() takes an instance of your page.

The subtle difference to what I used above is to use the page class with parameters instead. This results in a re-rendering of the page and it renders the up to date state i.e. shows the complex structure instead of the 'Create' panel.

I am aware of partial updating available via Wicket models and use that extensively throughout our app but this was a complex case where updating a model was not going to work because I couldn't just make a component visible that was previously hidden because that component can't even be constructed without the creation of the complex object is represents.

Volksman
  • 1,969
  • 23
  • 18