Photo by titanium22 - http://www.flickr.com/photos/nagarazoku/321106329/
del.icio.us Digg DZone Reddit StumbleUpon
1 | 2 | Next »
Software Development

Session-Scoped Beans in Spring

Learn how to create Spring beans scoped to HTTP sessions.

This short tutorial will show you how to define session-scoped beans in Spring. The idea here is that you have a web application, and you have various objects that exist on a per-session basis, such as maybe a user profile or a shopping cart. You'd like to make those available to some service bean, say, without having to manually pull them off the session and pass them as method arguments every time. First I'll show you how to do that. After that I'll talk a little bit about whether I think it's a good idea.

Here's the code for this article:

The code uses annotation-based autowiring. If you are unfamiliar with that and it's not reasonably clear what I'm doing with the code, you might want to see my articles Annotation-Based Autowiring in Spring 2.5 and Annotation-Based MVC in Spring 2.5.

Dependencies

I'm using Java 6 (though Java 5 should work too) and Spring 2.5.4 (though Spring 2.5.x should work generally). You will need the following JARs:

  • cglib-nodep-2.1_3.jar
  • commons-logging.jar
  • spring.jar
  • spring-webmvc.jar

Java Classes

We have four classes: a controller, a service interface, a service implementation, and a model class.

First, the controller:

Code listing: ssbexample.MyController
package ssbexample;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class MyController {
    private String SHOPPING_CART_KEY = "shoppingCart";
    
    private MyService service;

    public MyService getService() {
        return service;
    }

    public void setService(MyService service) {
        this.service = service;
    }
    
    @RequestMapping("/viewcart.do")
    public ModelMap viewCart() {
        return new ModelMap(SHOPPING_CART_KEY, service.getShoppingCart());
    }
    
    @RequestMapping("/additem.do")
    public ModelAndView addItem() {
        service.addItem();
        ShoppingCart cart = service.getShoppingCart();
        return new ModelAndView("/viewcart", SHOPPING_CART_KEY, cart);
    }
}

The thing to notice about the controller code is that I'm grabbing the shopping cart from the service bean itself, rather than pulling it off of the session directly. That means that the service bean is somehow able to return a session-specific shopping cart. (And we'll see how to do that shortly.) We're also able to tell the service to add an item (to the cart), and the service once again knows exactly which cart to add the item to.

Now here's the service interface:

Code listing: ssbexample.MyService
package ssbexample;

public interface MyService {
    
    ShoppingCart getShoppingCart();
    
    void addItem();
}

Here's the service implementation:

Code listing: ssbexample.MyServiceImpl
package ssbexample;

import org.springframework.stereotype.Service;

@Service("service")
public class MyServiceImpl implements MyService {
    private ShoppingCart shoppingCart;

    public ShoppingCart getShoppingCart() {
        return shoppingCart;
    }
    
    public void setShoppingCart(ShoppingCart shoppingCart) {
        this.shoppingCart = shoppingCart;
    }
    
    public void addItem() {
        shoppingCart.addItem();
    }
}

Notice that with the shopping cart getter and setter, we have a way to inject a shopping cart into the service bean. But we have only a single service bean instance, so it looks a little bit like magic right now.

And finally, here's the model class itself (a simple shopping cart):

Code listing: ssbexample.ShoppingCart
package ssbexample;

import java.io.Serializable;

public class ShoppingCart implements Serializable {
    private int numItems;
    
    public ShoppingCart() {
    }
    
    public int getNumItems() {
        return numItems;
    }
    
    public void addItem() {
        numItems++;
    }
}

As you may have guessed, the shopping cart is the object we want to save on the session. I've implemented Serializable so the servlet container can save the session when you shut it down. (Tomcat does that, anyway.)

The JSP

We have just one JSP.

Code listing: viewcart.jsp
<html>
    <head>
        <title>View Shopping Cart</title>
    </head>
    <body>
        <h1>View Shopping Cart</h1>
        <p>Your shopping cart currently contains ${shoppingCart.numItems} items.</p>
        <p><a href="additem.do">Add item to cart</a></p>
    </body>
</html>

web.xml Configuration File

Nothing special here:

Code listing: web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    
    <servlet>
        <servlet-name>front</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>front</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>

Now let's look at our Spring configuration file, which is where the aforementioned magic happens.

Social bookmarks: del.icio.us Digg DZone Reddit StumbleUpon
1 | 2 | Next »

Comments (2)

I'm curious as to what your take would be on using the @Scope annotation to define the session scoping.
By Adam Christensen on Jul 19, 2008 at 6:31 AM PDT
I haven't used that but I don't see why not.
By Willie Wheeler on Jul 21, 2008 at 5:24 PM PDT
Post a comment
Home | Consulting | Articles | Blog | About | Contact
Copyright © 2008 Wheeler Software, LLC.