Search This Blog

Loading...

Tuesday, 29 January 2013

ServletContext and ServletConfig

With Spring MVC we have the Front Controller pattern at work. So there is the one Servlet - Spring's own DispatcherServlet which receives the requests and forwards them to the controllers in the code.
But what if you wanted to access the ServletContext ? Or (in some rare case) the Servlet Config ?
Could you get them in your controller?
For example you may want to access or add some attributes to the ServletContext . Or you may like to have some config parameters added and accessed in your code.
I decided to try to get access to these two objects.(For the example I used jars from Spring's 3.1 release.)
The code in my controller is as below:
@RequestMapping(value = "/action/")
public class SimpleController {

    @Autowired
    private ServletContext context;
    @Autowired
    private ServletConfig config;
// other stuff..
}
I debugged one of my methods and checked the properties of the controller:
As seen, the Spring container wired my controller instance with both the ServletConfig object and the ServletContext object.
The Startup logs also indicate the same:
17:33:03.566 D|DefaultListableBeanFactory              
|Creating shared instance of singleton bean 'simpleController'
17:33:03.566 D|DefaultListableBeanFactory              
|Creating instance of bean 'simpleController'
17:33:03.574 D|InjectionMetadata                       
|Found injected element on class [com.test.simpleController]: 
AutowiredFieldElement for private javax.servlet.ServletContext 
com.test.simpleController.context
17:33:03.574 D|InjectionMetadata                       
|Found injected element on class [com.test.simpleController]: 
AutowiredFieldElement for private javax.servlet.ServletConfig 
com.test.simpleController.config

17:33:03.574 D|InjectionMetadata                       
|Processing injected method of bean 'simpleController': 
AutowiredFieldElement for private javax.servlet.ServletContext 
com.test.simpleController.context
17:33:03.582 D|DefaultListableBeanFactory              
|Returning cached instance of singleton bean 'servletContext'
17:33:03.582 D|AutowiredAnnotationBeanPostProcessor    
|Autowiring by type from bean name 'simpleController' to bean named 
'servletContext'
17:33:03.582 D|InjectionMetadata                       
|Processing injected method of bean 'simpleController': 
AutowiredFieldElement for private javax.servlet.ServletConfig 
com.test.simpleController.config
17:33:03.582 D|DefaultListableBeanFactory              
|Returning cached instance of singleton bean 'servletConfig'
17:33:03.582 D|AutowiredAnnotationBeanPostProcessor    
|Autowiring by type from bean name 'simpleController' to bean named 
'servletConfig'
But what if you are not using annotation based wiring? How could you do it in that case?
@Controller
@RequestMapping(value = "/action/")
public class SimpleController implements ServletContextAware, ServletConfigAware {

    private ServletContext context;
    private ServletConfig config;

    @Override
    public void setServletConfig(final ServletConfig servletConfig) {
        this.config = servletConfig;

    }

    @Override
    public void setServletContext(final ServletContext servletContext) {
        this.context = servletContext;

    }
//other code
}
There are two interfaces of importance here: -
  • the ServletContextAware interface : It provides a method that gives the Controller access to the ServletContext. 
  • the  ServletConfigAware interface: It provides a method that gives the Controller access to the ServletConfig.
Both methods involved are called by the Controller as a part of the bean lifecycle.

2 comments:

  1. Hi, I tried it but I got the below error:::

    The method setServletConfig(ServletConfig) of type RedirectingController must override or implement a supertype method.

    ReplyDelete
  2. This should work. Did you include the implements part ?

    ReplyDelete