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.
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.jarcommons-logging.jarspring.jarspring-webmvc.jarWe have four classes: a controller, a service interface, a service implementation, and a model class.
First, the controller:
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:
ssbexample.MyService
package ssbexample;
public interface MyService {
ShoppingCart getShoppingCart();
void addItem();
}
Here's the service implementation:
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):
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.)
We have just one JSP.
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>
Nothing special here:
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.