Restlets and HTTP Sessions (Recipe 9)
Posted: 07/31/2008 by ValIf you are reading this posting chances are high that you are familiar with Servlet API and in particular with its javax.servlet.http.HttpSession interface. According to HttpSession Javadoc, this API "provides a way to identify a user across more than one page request or visit to a Web site and to store information about that user... The server can maintain a session in many ways such as using cookies or rewriting URLs." This interface allows servlets to view and manipulate information about a session, such as the session identifier, creation time, and last accessed time, and, most importantly, "to bind objects to sessions, allowing user information to persist across multiple user connections." To this end, servlet API specifies some additional constructs to accommodate various needs arising while dealing with HttpSession's.
HTTP sessions are very popular among Web developers because they allow for easy implementation of things like complex authentications (resulting in creating complex security contexts), shopping carts, etc. All we need to do is to use out-of-the-box implementation of Servlet API where vendors take care of all internal plumbing. On the other hand, if you peruse Restlet API, you will find that it does not contain anything even remotely similar to servlet sessions.
Is this a tribute to stateless philosophy which is behind the whole REST architecture? Or, is it an oversight? Or a simply a low priority thing? Whatever this is, I believe that this circumstance does not contribute to the adoption of Restlet API for the purposes of developing Web sites. But since our goal is very practical, let's see what we can do to make up for the lack of what could be "RestletSession."
Thank's God (and Restlet creators), there is a org.restlet.data.Cookie class (briefly explained in its documentation as "Cookie provided by a client"). Since cookies are the best underlying means to create HTTP sessions, we are going to try to use them to implement a prototype for a shopping cart. You will see that from practical perspective our shopping car will have everything we would expect from a session.
The conceptual implementation of session-like facility is actually very simple and straightforward. But as always the case, we need to create some environment where our coding will have more practical meaning. We will need (all details that are not relevant for the purposes of this article have been omitted):
- A data type that models Shopping Cart. See Listing 1 with its conceptual implementation. Note that quite logically it extends AbstractPage and implements Validatable. The former defines an entity that can be rendered as a Web page; the latter describes all necessary behavior to validate user supplied data. Also note that our ShoppingCart has an Order as its member.
- A way of adding shopping carts to our application. One of them is to create a ConcurrentHashMap shoppingCarts as a member of our main application class. Accordingly, if its name is Arredocenter you may say Arredocenter.addShoppingCart(shoppingCart); to store carts created by various users. If Map keys are shopping cart IDs, we can easily retrieve carts later.
- Since we want our e-commerce site to be very friendly, we should be able to create a shopping cart any place and any time. In fact, what we want to do is to create and empty shopping cart as soon as the user accesses the site (not only we anticipate coming orders but, by doing this, we will also effectively use shopping cart as a surrogate session to bind any user information and actions to it). To accomplish this goal we'll rely on public abstract class ArredocenterBaseHTMLResource that extends Restlet's Resource class that all our Resource's will extend. This approach is actually quite consistent with Recipe 1 where I discussed a possible architecture of a Restlet Web site. By sub-classing a basic Resource, we'll be able to implement a consistent behavior in dealing with sessions (oops, shopping carts)
Listing 1 - Conceptual implementation of ShoppingCart
public class ShoppingCart extends AbstractPage implements Validatable {
private String id;
/** HashMap of ShoppingCartItem's keyed by Product's SKUs and productOption */
private HashMap items;
/** Set of String's with Product SKUs for Products viewed */
private LinkedHashSet itemsViewed;
...
private Order order;
/** Used to handle cart's life cycle */
private boolean processed;
public ShoppingCart() {...}
public ShoppingCart(String id) {...}
public void cleanProductsFromCart() {...}
public int getOrderPhase() {...}
public double computeShippingAndHandling(double subTotal) {...}
public double computeTax(double taxableAmount) {... }
public void saveOrder(Database db) throws Exception {...}
public ShoppingCartItem buildFromtForm(Form productForm) {...}
public double getTotal() {...}
public void addItem(ShoppingCartItem shoppingCartItem) {...}
public void removeItem(String shoppingCartItemKey) {...}
public void addItemViewed(String shoppingCartItemKey) {...}
...
public String getValidationErrors() {...}
}
All important details of creating and "retrieving" shopping carts are shown in Listing 2. Note that the ShoppingCart is a member of the base Resource class. This is done to be able to access shopping cart information on each and every Web site page (for example, showing how many products have been viewed, how many products are in shopping cart, the total, etc.). The coding that deals with all shopping cart essentials takes only 11 lines. In addition, to show other options available with this approach in processing shopping carts, I show in Listing 2 the if (shoppingCart.isProcessed()) {...} block as a way to control carts upon user actions committed in previous requests.
Listing 2 - ShoppingCart plumbing in a base Resource class
public abstract class ArredocenterBaseHTMLResource extends Resource {
protected ShoppingCart shoppingCart;
public ArredocenterBaseHTMLResource(Context context, Request request,
Response response) {
super(context, request, response);
...
String sessionToken =
request.getCookies().getFirstValue(Constants.CAMERATA_ARREDOCENTER_SESSION_COOKI
E_NAME);
if (sessionToken == null) {
shoppingCart = new ShoppingCart();
sessionToken = shoppingCart.getId();
response.getCookieSettings().add(new
CookieSetting(Constants.CAMERATA_ARREDOCENTER_SESSION_COOKIE_NAME,
sessionToken));
Arredocenter.addShoppingCart(shoppingCart);
}
else {
shoppingCart = Arredocenter.getShoppingCart(sessionToken);
if (shoppingCart == null) {
shoppingCart = new ShoppingCart(sessionToken);
Arredocenter.addShoppingCart(shoppingCart);
}
}
...
if (shoppingCart.isProcessed()) {
shoppingCart.cleanProductsFromCart();
shoppingCart.setProcessed(false);
}
}
...
public ShoppingCart getShoppingCart() {
return shoppingCart; }
}
Recent Blogs
Convergence of Technologies II: Restlets, Highslide Viewer & SlideShowPro for Flash How to use Restlets, Highslide Viewer & Slide Show Pro Flash component to generate slide shows and show them in pop-up iframes 08/14/2009
Convergence of Technologies: Restlets, Highslide Viewer & Google Maps API How to use Restlets, Highslide Viewer & Google Maps API to generate Google maps using links on Web pages and show them in pop-up iframes. 08/13/2009
Ambimorphic, Mobile Configurations for Lamport Clocks After years of technical research into Smalltalk, with close cooperation with MIT Computer Science and Artificial Intelligence Laboratory (CSAIL) and its SCIgen, we have been able to show the construction of link-level acknowledgements. As a result, we propose an analysis of A* search, which we call Volt. 10/02/2008
Restlets and HTTP Sessions (Recipe 9) This recipe discusses some options in available to Web site developers using Restlet API to emulate traditional HttpSession's 07/31/2008
Restlet Cookbook - Delving into handleGet() and handlePost() (Recipe 8) This posting provides related examples that illustrate at least some simple things you may do with several handleX() methods where X may stand for various types of calls. 07/30/2008
Restlet Cookbook - How to enable SSL (Recipe 7) How to enable SSL on Restlet Web sites wihtout knowing too much keys, encryption, SSL and such. 07/29/2008
Restlet Cookbook - Using Filters in Restlet Applications (Recipe 6) This recipe contains code snippets illustrating the use of Filters in Restlet applications 03/09/2008
Restlet Cookbook - How to Create Virtual Hosts in Restlet Applications (Recipe 5) This recipe contains a code snippet for creating virtual hosts 02/24/2008
Popular HTML Escape Codes Here is a table of HTML escape codes for most frequently used symbols. If you use HTML, sooner or later you will find this table useful. 12/29/2007
Restlet Cookbook - Access Log (Recipe 4) This recipe describes access Logging using Restlet framework 11/09/2007
more...