25

I want to write a simple servlet in JBoss which will call a method on a Spring bean. The purpose is to allow a user to kick off an internal job by hitting a URL.

What is the easiest way to get hold of a reference to my Spring bean in the servlet?

JBoss web services allow you to inject a WebServiceContext into your service class using an @Resource annotation. Is there anything comparable that works in plain servlets? A web service to solve this particular problem would be using a sledgehammer to crush a nut.

Oliver Drotbohm
  • 80,157
  • 18
  • 225
  • 211
Sophie Gage
  • 5,391
  • 5
  • 24
  • 25

3 Answers3

60

There is a much more sophisticated way to do that. There is SpringBeanAutowiringSupportinside org.springframework.web.context.support that allows you building something like this:

public class MyServlet extends HttpServlet {

  @Autowired
  private MyService myService;

  public void init(ServletConfig config) {
    super.init(config);
    SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,
      config.getServletContext());
  }
}

This will cause Spring to lookup the ApplicationContext tied to that ServletContext (e.g. created via ContextLoaderListener) and inject the Spring beans available in that ApplicationContext.

Oliver Drotbohm
  • 80,157
  • 18
  • 225
  • 211
  • 4
    In Spring 2.5.x it should be SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); which handles the rest automatically. Awesome tip btw. – Lajcik Nov 04 '10 at 15:57
  • 1
    If you need to access any of the ServletConfig, make sure that you call "super.init(config)" in the "init" method; e.g. public void init(ServletConfig config) { super.init(config); SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext()); } – tamsler Jun 21 '11 at 16:54
  • There's a known data access race condition risk in using instance variables in Servlets (if you don't follow the SingleThreadModel). I believe that risk still exists if the instance variable is autowired. OWASP link: https://www.owasp.org/index.php/Member_Field_Race_Condition – Paulo Merson Nov 26 '14 at 11:13
31

Your servlet can use WebApplicationContextUtils to get the application context, but then your servlet code will have a direct dependency on the Spring Framework.

Another solution is configure the application context to export the Spring bean to the servlet context as an attribute:

<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
  <property name="attributes">
    <map>
      <entry key="jobbie" value-ref="springifiedJobbie"/>
    </map>
  </property>
</bean>

Your servlet can retrieve the bean from the servlet context using

SpringifiedJobbie jobbie = (SpringifiedJobbie) getServletContext().getAttribute("jobbie");
Chin Huang
  • 12,912
  • 4
  • 46
  • 47
  • What is the advantage to doing it this way and not using WebApplicationContextUtils? Either way it's tied to Spring. – Elliot Dec 29 '09 at 19:51
  • 5
    The mechanism to populate the servlet context attribute does not have to be implemented using Spring. A filter or another servlet that runs at startup can populate the servlet context attribute. – Chin Huang Jan 09 '10 at 17:36
8

I've found one way to do it:

WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
SpringifiedJobbie jobbie = (SpringifiedJobbie)context.getBean("springifiedJobbie");
Sophie Gage
  • 5,391
  • 5
  • 24
  • 25