Is it difficult to make a mainly stateless web application with Wicket?
Asked Answered
C

2

13

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.

Citizenry answered 7/8, 2010 at 17:14 Comment(1)
There is a whole dating site created with all the public pages stateless. It was done a few years ago so the entries are older but they might still be useful. especially the "anti-patterns". letsgetdugg.com/tag/wicketTarry
G
14

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">
<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 :)

Gerardogeratology answered 9/8, 2010 at 15:29 Comment(1)
Thank you for taking the time to write that incredibly useful example! :-)Citizenry
S
7

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 arguments in the pages
  4. Use bookmarkable links
Slippy answered 11/8, 2010 at 6:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.