Search This Blog

Sunday 13 April 2014

Request and Session Scope

I have never used a request scoped bean. Always Singleton. And once I dabbled with Prototype but that too never went beyond the prototype stage.
I can't really think of a scenario where I might need request or session scoped beans (yet!). The job is generally achieved with stateless singleton beans and data in request and session attributes.
Anyway I decided to try out a request scoped bean.
The class is created is a simple class which holds a unique id and creation time stamp.
 public class RequestAudit {

   private static final SecureRandom random = new SecureRandom();

   private final Date date;
   private final String randomId;

   public RequestAudit() {
      this.date = new Date();
      this.randomId = new BigInteger(130, random).toString(32);
   }
   // ..setter getters
}
The configuration for the bean is as below:
<bean id="requestAudit" class="com.custom.request.RequestAudit" scope="request" />
The Spring container creates a new instance of the bean for each and every HTTP request. So to test the same we need a web application. Accordingly I created a simple Spring mvc application and added a Controller:
@Controller
public class SimpleController implements ApplicationContextAware {

   private ApplicationContext applicationContext;

   // other methods...
   @Override
   public void setApplicationContext(final ApplicationContext applicationContext)
         throws BeansException {
      this.applicationContext = applicationContext;
   }

}
The Controller has access to the ApplicationContext so that it can retrieve the request scoped bean. The first method here is :
   @RequestMapping(value = "/simple.do", method = RequestMethod.GET)
   public String display(final HttpServletRequest request) {
      final RequestAudit requestAudit =             
                (RequestAudit) this.applicationContext.getBean("requestAudit");
      System.out.println("RequestAudit in request { " + request + " } is " 
            + requestAudit.getRandomId() + ", created at " 
            + new SimpleDateFormat("yyyy-MM-dd, hh: mm :ss").format(requestAudit.getDate()));
      return "forward:/fwd.do";
   }

Any call for "<web context>/simple.do" will resolve at this method. The method retrieves the requestAudit bean from the ApplicationContext and display it. It then forwards to "<web context>/fwd.do":

   @RequestMapping(value = "/fwd.do", method = RequestMethod.GET)
   public String forwardedDisplay(HttpServletRequest request) {
      RequestAudit requestAudit 
              = (RequestAudit) applicationContext.getBean("requestAudit");
      System.out.println("RequestAudit in forwarded request { " + request + " } is " 
            + requestAudit.getRandomId() + ", created at " 
            + new SimpleDateFormat("yyyy-MM-dd, hh: mm :ss").format(requestAudit.getDate()));
      return "redirect:/redir.do";
   }
Here too we have only retrieved the bean from the request scope and displayed it. Then we have redirected to the url "<web context>/redir.do":
   @RequestMapping(value = "/redir.do", method = RequestMethod.GET)
   public void redirectedDisplay(HttpServletRequest request, HttpServletResponse response) 
         throws IOException {
      RequestAudit requestAudit = 
                 (RequestAudit) applicationContext.getBean("requestAudit");
      System.out.println("RequestAudit in redirected request { " + request + " } is " 
            + requestAudit.getRandomId() + ", created at "
            + new SimpleDateFormat("yyyy-MM-dd, hh: mm :ss").format(requestAudit.getDate()));
      PrintWriter writer = response.getWriter();
      writer.print("<html><body>Request Complete</body><html>");
      writer.flush();
   }
This method also fetches and displays the bean. It then displays a simple message on the screen. If we check the application logs for the call "http://localhost:8080/SpringWeb/simple.do":
2013-08-14 14:47:59 DEBUG RequestMappingHandlerMapping:226 - Looking up handler method 
for path /simple.do
...
2013-08-14 14:47:59 DEBUG DefaultListableBeanFactory:435 - Creating instance of bean 'requestAudit'
...
RequestAudit in request { org.apache.catalina.connector.RequestFacade@ce3b01 } 
is a3bd8sur358umhk086e3gu4kbk, created at 2013-08-14, 03: 06 :39
2013-08-14 14:47:59 TRACE HandlerMethod:135 - Method [display] returned [forward:/fwd.do]
...
2013-08-14 14:47:59 DEBUG InternalResourceView:236 - Forwarding to resource 
[/fwd.do] in InternalResourceView 'null'
...
RequestAudit in forwarded request { org.apache.catalina.core.ApplicationHttpRequest@108e44d } 
is a3bd8sur358umhk086e3gu4kbk, created at 2013-08-14, 03: 06 :39
2013-08-14 14:47:59 TRACE HandlerMethod:135 - Method [forwardedDisplay] returned [redirect:/redir.do]
...
2013-08-14 14:47:59 DEBUG DefaultListableBeanFactory:435 - Creating instance of bean 'requestAudit'
RequestAudit in redirected request { org.apache.catalina.connector.RequestFacade@c4a6d8 } 
is ls3g8e05fabbr94ngkhetvstkt, created at 2013-08-14, 03: 06 :42
As can be seen from the logs the called method and the forwarded method both had the same bean. The redirect method on the other hand had a new bean. This clearly indicates that the bean is created fresh for a request only once. Similar is the working for Session scope. One bean per session.
I changed the scope of the bean to session and executed the code again. The logs are :
2013-08-14 16:06:23 DEBUG DefaultListableBeanFactory:435 - Creating instance of bean 'requestAudit'
...
RequestAudit in request { org.apache.catalina.connector.RequestFacade@980a8d } 
is 51mhbud1nf2iil3odr4prcdnfp, created at 2013-08-14, 04: 06 :23
2013-08-14 16:06:23 TRACE HandlerMethod:135 - Method [display] returned [forward:/fwd.do]
...
RequestAudit in forwarded request { org.apache.catalina.core.ApplicationHttpRequest@1f4ec39 } 
is 51mhbud1nf2iil3odr4prcdnfp, created at 2013-08-14, 04: 06 :23
2013-08-14 16:06:23 TRACE HandlerMethod:135 - Method [forwardedDisplay] returned [redirect:/redir.do]
...
RequestAudit in redirected request { org.apache.catalina.connector.RequestFacade@980a8d } 
is 51mhbud1nf2iil3odr4prcdnfp, created at 2013-08-14, 04: 06 :23
As seen, the same bean was found in all the three methods, being created only once and added to session.

No comments:

Post a Comment