titanium22
Photo credit: titanium22
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 (18)

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
i downloaded your zip file but i found there is an error. I can't fix it. Hope you can tell me why the problem occur. Thx
By fai on Sep 23, 2008 at 1:36 AM PDT
@fai: Help me out a bit here. :-) What was the error?
By Willie Wheeler on Sep 23, 2008 at 1:51 AM PDT
the view cart page doest not display the number of items added but is display the ${shoppingCart.numItems} in the viewcart.jsp page
By fai on Sep 23, 2008 at 2:31 AM PDT
Hi fai. You have a few different options:

1) If you are using Tomcat, upgrade to Tomcat 6.

2) If you don't want to upgrade, you can place the following line of code at the top of your JSP:

<%@ page isELIgnored="false" %>

This approach requires modifying each JSP that uses JSP EL.

3) If you want to handle this globally instead of on a page-by-page basic, try adding the following to web.xml:

<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>false</el-ignored>
</jsp-property-group>
</jsp-config>

Let me know if you continue to have trouble. Thanks!
By Willie Wheeler on Sep 23, 2008 at 8:09 AM PDT
The problem is solved after i paste the <%@ page isELIgnored="false" %> in the JSP page. But if use the globally method still the same problem. Thx a lot. =]
By fai on Sep 23, 2008 at 7:18 PM PDT
Hi Willie,

I am using Spring Web Flow and have spring session scoped bean (Shopping Cart)

How do I remove the scoped session variable(e.g shopping cart) after the customer finish the flow?

In MVC, we would do something like
request.getSession().removeAttribute("shoppingcart" );

Any hint?

Thanks,
By Gerald on Oct 16, 2008 at 8:49 AM PDT
I will be very curious if Spring 2.5 could remove a pre-configured session scoped bean on the fly from a given HTTP session, similar to the following in code:
request.getSession().removeAttribute("shoppingcart" );
By John on Oct 16, 2008 at 10:13 AM PDT

Very helpful article.

It took me some time to figure out that scoped beans need to be added to the model object to be visible on the JSP page tags through EL.

By en on Jan 15, 2009 at 12:01 AM PST

Is this thread safe? As you sad a bean serve more clients and I know that a bean is singleton...

By psw on Feb 22, 2009 at 4:22 PM PST

@psw: Session-scoping doesn't add any threadsafety guarantees. Usually you'll have only one request-processing thread working with your session at a time, and so for many practical purposes requests against the session-scoped bean will be isolated, but there are lots of situations in which this could fail to hold. So if you need actual threadsafety then it behooves you to use proper synchronization (for example on the bean itself).

By Willie Wheeler on Feb 22, 2009 at 4:33 PM PST

Another quick pair of comments:

  1. Session-scoped beans are not singletons in either the GoF design pattern sense or the Spring singleton bean sense.
  2. As a general rule, you have to be even more careful about threadsafety with singletons than you do with non-singletons, because singletons often involve data sharing across threads. I think this is what you were getting at with your post but just wanted to be sure.
By Willie Wheeler on Feb 22, 2009 at 4:39 PM PST

Thank you for the answer!

I know that session-scope is not singleton but I know that the service is. And for a shopping-bag, I think you need it thread safe.

By psw on Feb 24, 2009 at 9:09 AM PST

How do I access the session-scope bean from JSP, without putting into model explicitly from Controller?

By Ruban on May 15, 2009 at 9:48 AM PDT

This initially looked like a good idea, but the fact that you cant access them via the JSP pages without explicitly adding them to the model object prevents me from using this. If I could still use

<c:set value="${sessionScope['ShoppingCart']}" var="shoppingCart" />

then i would consider this.

By JaredTims on May 19, 2009 at 7:49 AM PDT

he myth of pandora is ancient, appears in several distinct Greek versions, pandora armbandand has been interpreted in many ways. In all literary versions, Neu Eingetroffen however, Pandora Armbänder the myth is a rosetta stone kind of theodicy, addressing the question pop information, web easy get, sports fashion, news-fashionof why there is evil in the world. In the seventh hot-winter century BC, Hesiod, both in his Theogony (briefly, without naming Pandora outright rosetta stone language, rosetta stone spanish, abercrombie and fitch, Abercrombie Fitch

By pandora schmuck on Aug 30, 2010 at 11:13 PM PDT

Post a comment

Your name:
Your e-mail address (won't be displayed):
Your web site (optional):
example: www.xyz.com
Your comment:
Preview:
By You
Please help us reduce comment spam:
Spring Annotations RefCard
Check out the new DZone Spring Annotations Refcard by Craig Walls!

What's New?

2009-08-30 - Check out my two-part series on DZone: Spring Integration: A Hands-On Tutorial.
2009-03-25 - My new article Getting Started with Spring Batch 2.0 is available on DZone.
Home | Consulting | Tech Articles | Mailing List | Contact | Spring Blog
Copyright © 2008 Wheeler Software, LLC.