On Fri, Jan 29, 2010 at 12:25 PM, Ben Short <[email protected]> wrote:
> I want to store data for anonymous users, such as the contents of a shopping
> cart.
>
> When the user comes to the site a script will look for a path contained in a
> cookie. If this cookie present then any 'add to basket' forms will post to
> it and any requests to show the basket will pull content from this path.
>
> If the cookie is not present then a new unique path will be created for this
> user and the cookie will be returned in the response.
>
> Another way I can see it working is the basket contents is
> stored entirely on the client side in a cookie.
>
> Can anyone give me any pointers on best practices of how to
> store anonymous user data?

You could probably set ACLs so that a node (e.g. /shoppingbaskets) are
writable by anonymous users, and then send a simple POST request to
create new baskets. But it's not trivial to limit the type of content
your users can posts to /shoppingbaskets, so you might risk that
someone uploads a file to it etc.

Instead, I'd write a couple of SlingPostOperations [1] to
create/update baskets. The SlingPostOperations could log in as admin
(via SlingRepository.loginAdministrative()) and make sure the baskets
are created properly.

Some un-tested pseudo-code:
@Component
@Service
@Properties({...@property(name = "sling.post.operation", value = 
"createBasket")}
public class CreateBasketPostOp implements SlingPostOperation {

  @Reference
  private SlingRepository repository;

  public void run(SlingHttpServletRequest req, HtmlResponse res,
SlingPostProcessors[] processors) {
      Session session = repository.loginAdministrative(null);
      Node basketsParent = session.getItem(req.getResource().getPath());
      Node basket = basketsParent.addNode(/* generate a unique name */);
      res.onCreated(basket.getPath());
      session.save();
  }
}

With this SlngPostOperation in place, you should be able to create a
shoppingbasket for a new, anonymous user by POSTing to
/shoppingbaskets, with the field ":operation" set to "createBasket".
You'll have to parse the resulting HTML to find the path of the
created basket node.

Then you need a PostOp to add products to a basket (I assume you're
getting the cookie from an ESP script or similar, and then include the
cookie value as part of the request URI):

@Component
@Service
@Properties({...@property(name = "sling.post.operation", value = "addToBasket")}
public class AddToBasketPostOp implements SlingPostOperation {

  @Reference
  private SlingRepository repository;

  public void run(SlingHttpServletRequest req, HtmlResponse res,
SlingPostProcessors[] processors) {
      Session session = repository.loginAdministrative(null);
      Node basket = session.getItem(req.getResource().getPath());
      Node product = basket.addNode(/* get ID of product added to
basket from query params */);
      res.onCreated(product.getPath());
      session.save();
  }
}

You would add products to a shopping basket by posting to the basket's
node (e.g. /shoppingbaskets/basket1) with the field ":operation" set
to "addToBasket", and some field to specify the product ID that is to
be added.

You will also need some maintenance service to remove outdated baskets.

The strategy of storing the basket on the client (in a cookie) should
also be possible, but that would probably imply that the entire
shopping basket is sent with every request to your site (including
requests for images, css, javascript etc). This might not be a big
problem, but if the shopping basket is big, and the user has limited
upstream bandwith (a mobile user, for example), this could make
requests slower.

[1] 
http://sling.apache.org/site/manipulating-content-the-slingpostservlet-servletspost.html
- see "Extending the SlingPostSerlvet" at the bottom

-- 
Vidar S. Ramdal <[email protected]> - http://www.idium.no
Sommerrogata 13-15, N-0255 Oslo, Norway
+ 47 22 00 84 00 / +47 21 531941, ext 2070

Reply via email to