views:

183

answers:

2

I've been working with Wicket for month or two now, making simple web applications with it and getting used to models and so forth. Now I'd like to move forward and see if I can put what I've learned so far to use and create a medium/large web application. However, I haven't spent much time thinking about how to make pages stateless.

If I understand correctly, making a stateless page is achieved by making the page bookmarkable and making sure that no stateful components are added to the page.

For the website I am making I want to avoid "Page expired" messages, let users be logged in via cookies, make a whole lot of the content available without needing to login/create a session, and I want functionality such as pagination to be stateless and bookmarkable.

This is no problem with e.g. PHP, but it seems to me that a whole lot of the useful Wicket components are stateful. Am I in for a whole lot of work, such as creating my own set of components that are stateless, or is it no big deal?

I hope someone can help me out by pointing me in the right direction.

EDIT: Lets say I wanted to make a blog. Browsing posts, categories and so on should be possible without having to worry that the page will have become expired if a user decides to read an article for 2 hours and then tries to navigate further via e.g. pagination. I want to allow users to stay logged in for a month at a time, but I do not exactly want to store their session for a month either.

I'd greatly appreciate any help on how I can accomplish what I just described, with Wicket.

+4  A: 

When building stateless pages with Wicket, you do lose most 'smart' built-in components, for example paginated tables and trees.

I think this is less an issue for sites, blogs and the like, which usually have a fairly simpler navigation model and don't use this kind of 'rich' component, and use stateless-server-friendly, Javascript-based components/effects, like jQuery-UI or YUI instead.

Some things you'll do differently, like pagination. For example, instead of using built-in pagination components, you'll have to make your own mechanism, using page parameters and stateless links:

HomePage.html

<html xmlns:wicket="http://wicket.apache.org"&gt;
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div class="container">

    <div wicket:id="posts">
      <h2 wicket:id="title"></h2>
      <p wicket:id="content"></p>
      Posted on <span wicket:id="date"></span>
    </div>

    <div>
      <a wicket:id="recentPosts">&lt;&lt; Recent posts</a>
      <a wicket:id="previousPosts">Previous posts &gt;&gt;</a>
    </div>

  </div>
</body>
</html>

HomePage.java

package wishminimal.ui.home;

import java.util.Iterator;

import org.apache.wicket.PageParameters;
import org.apache.wicket.devutils.stateless.StatelessComponent;
import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.spring.injection.annot.SpringBean;

import wishminimal.dao.PostDAO;
import wishminimal.entity.Post;

@StatelessComponent
public class HomePage extends WebPage {

    @SpringBean
    PostDAO postDAO;

    ISortableDataProvider<Post> dataProvider = new SortableDataProvider<Post>() {
    public Iterator<? extends Post> iterator(int first, int count) {
        return postDAO.findAll(first, count).iterator();
    }
    public int size() {
        return postDAO.countAll();
    }
    public IModel<Post> model(Post object) {
        return new CompoundPropertyModel<Post>(object);
    }
    };

    public HomePage(PageParameters params) {
    final int currentPage = params.getAsInteger("p", 0);

    final DataView<Post> dataView = new DataView<Post>("posts", dataProvider, 10) {
        @Override
        protected void populateItem(Item<Post> item) {
        item.add(new Label("title"));
        item.add(new Label("content"));
        item.add(new Label("date"));
        }
    };
    dataView.setCurrentPage(currentPage);
    add(dataView);

    add(new BookmarkablePageLink<Void>("recentPosts", getClass(), new PageParameters("p=" + (currentPage - 1))) {
        @Override
        public boolean isVisible() {
        return currentPage > 0;
        }
    });
    add(new BookmarkablePageLink<Void>("previousPosts", getClass(), new PageParameters("p=" + (currentPage + 1))) {
        @Override
        public boolean isVisible() {
        return currentPage < dataView.getPageCount();
        }
    });
    }
}

While this is much less convenient than stateful Wicket, I still find much better than say, stateless JSF or Struts :)

tetsuo
Thank you for taking the time to write that incredibly useful example! :-)
John
+1  A: 

To make pages stateless, i do the following:

  1. Use bookmarkable pages
  2. Use stateless forms in all cases
  3. To pass data across pages, i use page parameters as the only constructor in the pages
  4. Use bookmarkable links

Regards.

joshua