I wanted to leverage on the solution provided by Sotirios Delimanolis but adding transparent autowiring to the mix. The idea is to turn plain servlets into autowire-aware objects.

So I created a parent abstract servlet class that retrieves the Spring context, gets and autowiring-capable factory and uses that factory to autowire the servlet instances (the subclasess, actually). I also store the factory as an instance variable in case the subclasses need it.

So the parent abstract servlet looks like this:

public abstract class AbstractServlet extends HttpServlet {

    protected AutowireCapableBeanFactory ctx;

    @Override
    public void init() throws ServletException {
        super.init();
        ctx = ((ApplicationContext) getServletContext().getAttribute(
                "applicationContext")).getAutowireCapableBeanFactory();
        //The following line does the magic
        ctx.autowireBean(this);
    }
}

And a sevlet subclass looks like this:

public class EchoServlet extends AbstractServlet {

    @Autowired
    private MyService service;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {
        response.getWriter().println("Hello! "+ service.getMyParam());
    }
}

Notice the only thing EchoServlet needs to do is to declare a bean just in common Spring practice. The magic is done in the init() method of the superclass.

I haven't tested it thoroughly. But it worked with a simple bean MyService that also gets a property autowired from a Spring-managed properties file.

Enjoy!


Note:

It's best to load the application context with Spring's own context listener like this:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Then retrieve it like this:

WebApplicationContext context = WebApplicationContextUtils
    .getWebApplicationContext(getServletContext());
ctx = context.getAutowireCapableBeanFactory();
ctx.autowireBean(this);

Only spring-web library needs to be imported, not spring-mvc.


What you are trying to do will make every Servlet have its own ApplicationContext instance. Maybe this is what you want, but I doubt it. An ApplicationContext should be unique to an application.

The appropriate way to do this is to setup your ApplicationContext in a ServletContextListener.

public class SpringApplicationContextListener implements ServletContextListener {
        @Override
    public void contextInitialized(ServletContextEvent sce) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

        sce.getServletContext().setAttribute("applicationContext", ac);            
    }
    ... // contextDestroyed
}

Now all your servlets have access to the same ApplicationContext through the ServletContext attributes.

@Override
public void init(ServletConfig config) throws ServletException {
   super.init(config);

   ApplicationContext ac = (ApplicationContext) config.getServletContext().getAttribute("applicationContext");

   this.apiData = (ApiData)ac.getBean("apiData");
   this.apiLogger = (ApiLogger)ac.getBean("apiLogger");
}