Question

I have some Wicket pages which are laid out like this:

(HomePage.html)

<html>
  <head>
    <title>Front</title>
    <link wicket:id="applicationCss" rel="stylesheet" type="text/css"
          href="stylesheets/application.css"/>
  </head>
  <body>
    <!-- Content unnecessary -->
  </body>
</html>

(HomePage.java)

public class HomePage extends AbstractWebPage {
    public HomePage() {
        // Nothing necessary (real application initialises some other links here.)
    }
}

(AbstractWebPage.java)

public abstract class AbstractWebPage extends WebPage {
    protected AbstractWebPage() {
        setStatelessHint(true);

        // *** the trouble-maker:
        add(new ResourceLink<>(
            "applicationCss",
            new CssResourceReference(AbstractWebPage.class,
                                     "stylesheets/application.css")));
    }
}

When I visit my home page at /admin, the browser is immediately redirected to /admin?0, indicating that the page is not stateless. However, the only thing I have added is a link which as far as I can tell by reading the code, is not stateful.

Naturally, if I remove the <link> tag in the HTML and the add() statement in AbstractWebPage, the page returns to being stateless.

What am I doing wrong? Ideally I would like any URL the user ever sees to be stateless, but just by including a stylesheet on all pages, suddenly all my stateless pages are stateful for no obvious reason.

Was it helpful?

Solution

Instead of adding a ResourceLink, override the method that is meant for such (header) links:

@Override
public void renderHead(IHeaderResponse response) {
    super.renderHead(response);
    response.renderCSSReference(new ResourceReference(AbstractWebPage.class, "stylesheets/application.css"));
}

This should not make your page stateful. And then there's the additional benefit of not having to add anything to the markup as well.

This works for components and behaviors as well, enabling you to encapsulate dependencies at the lower level. Wicket will filter duplicates (provided you add a unique key to the resource reference).

Unfortunately it does add extra links to your head section, so be careful with adding 64 behaviors and components with their own JavaScript and CSS resources. That will slow your application down considerably (and you'll run into limits of browsers—looking at you, IE!)

OTHER TIPS

I will put another option out there which I have found. I'm not sure if it's better...

public class BookmarkableResourceLink<T> extends ResourceLink<T> {
    public BookmarkableResourceLink(String id, ResourceReference reference) {
        super(id, reference);
    }

    @Override
    protected boolean getStatelessHint() {
        return true;
    }
}

Then use this in place of ResourceLink itself, and everything works sanely. I'm not sure exactly why ResourceLink doesn't do this itself... but as a workaround, this is pretty clean.

just another hint, not really a solution. I found it usefull to work with @StatelessComponent annotion from wicket devutils. It throws an exception and tells you which component of the site breaks your page to be statefull. in wicket 1.5 you can this.getComponentPostOnBeforeRenderListeners().add(new StatelessChecker()); in the init of your Application to register the StatelessChecker.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top