Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Servlet dependency injection with Spring

This article will discuss about servlet dependency injection with spring.

Background

For a complex project, dependency injection is often the ideal way of managing the relationships between the various components of your application. Taking control of object creation outside of those components allows us to connect them in different ways for various purposes - most importantly, of course, for testing. And the Spring Framework is the most popular implementation of the pattern, providing not just the basic requirements of object instantiation and injection but a variety of extra conveniences: autowiring, automatic transaction management, and so on.

Configuring Servlets with dependency injection, however, can be a bit tricky. The Servlet API was designed before the pattern was commonplace, and attempts to simplify the job of the programmer by managing object creation itself. Unfortunately (at least prior to recent updates to the API, which I'll describe below) this gets in the way of dependency injection. But it doesn't entirely stop you from using it. There are in fact several ways of achieving the same result. I'll show you a few so you can choose your favorite.

Using Spring MVC

Spring MVC is a Model-View-Controller framework included with Spring. Spring provides a DispatcherServlet that can be configured in various ways to find controller methods that implement functions to expose to the web. It is a very useful framework, but not the primary focus of this article, which is geared towards simpler solutions for those who may not want to use an entire MVC framework in their application.

Using an HttpRequestHandler

The approach offered by the Spring framework itself is HttpRequestHandler, an interface which your beans can implement. Spring then provides an HttpServlet implementation that locates a bean from your application context (configured via the name of the servlet specified in web.xml) that forwards the request to your handler bean. Let’s look at some example code.

A simple implementation of HttpRequestHandler might look like this (with imports removed for clarity):

Listing 1: HttpRequestHandler

package com.example.myapp;

public class MyRequestHandler implements HttpRequestHandler
{
    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) 
                throws ServletException, IOException
    {
        response.getWriter().println ("hello, world");
    }
}

In web.xml, we need to declare a servlet of type HttpRequestHandlerServlet, a servlet implementation provided by Spring:

Listing 2: Web.xml

    <servlet>
        <servlet-name>myServlet</servlet-name>
        <servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>myServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

We also need to initialize the Spring context, which is usually done with a ContextLoaderListener in web.xml:

Listing 3: ContextLoaderListener in web.xml

    <listener> 
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 

Finally, in applicationContext.xml you need to declare a bean that has the same name as the servlet and is of the class we just defined:

Listing 4: applicationContext.xml

    <bean id="myServlet" class="com.example.myapp.MyRequestHandler" />

Fire it all up and request '/hello' within your application and you'll get the traditional greeting. This approach works, and it has the benefit of being the officially supported way of doing this with Spring, but it does have a few drawbacks. Firstly, it introduces a dependency in your processing code on Spring, which is to say the HttpRequestHandlerServlet interface. In an ideal world, we would write the majority of our code with no dependency on Spring, and keep the Spring-dependent aspects to parts of the code only used for configuration purposes, isolating the majority from changes (if, for example, we decided to switch from Spring to a different method of managing our dependencies). Secondly, it's an awful lot of work. Every servlet has to be configured in two places. Can't we get away with only one - or, ideally, none?

Using the Servlet 3.0 API for dynamic registration

It turns out that, at least if we are using the Servlet 3.0 API, we can do better. Servlet 3.0 (which is supported by many recent application servers, as well as Apache Tomcat 7) adds the ability to add servlets to the application context dynamically; we can use this to get servlets out of a Spring context and then register them ourselves. Our servlets can then extend HttpServlet directly, rather than having to implement a Spring-provided interface.

We'll need at least one class that depends on Spring - it'll need to be able to query the application context for its list of servlets - and we can cause it to run on startup by making it a web context event listener. I put it in a separate library so it can be reused in multiple projects.

Listing 5: applicationContext.xml

package com.example.springintegration;
public class SpringServletRegistrationListener implements ServletContextListener
{
    @Override
    public void contextDestroyed (ServletContextEvent arg0)
    {
    }

    @Override
    public void contextInitialized (ServletContextEvent contextEvent)
    {
        // we'll do our magic here
    }
}

And it will need to be registered in web.xml, where it should be placed after the registration of your Spring ContextLoaderListener, so the Spring context is initialised before it runs:

Listing 6: web.xml

    <listener>
        <listener-class>com.example.springintegration.SpringServletRegistrationListener</listener-class>
    </listener>

With the listener registered, we now need to make it do something useful. It'll get a map out of the Spring context, where the keys are the URL patterns and the values are the servlets that handle those patterns. There are other approaches that can be used, and we'll examine one of those when we come to look at ways of reducing the configuration still further, but for now this is probably the simplest approach. A map can be declared in the Spring applicationContext.xml file using Spring's 'util' namespace. Once we have the map, we step through its entries and register them in the servlet context:

Listing 7: Defining context

    @SuppressWarnings ("unchecked")
    @Override
    public void contextInitialized (ServletContextEvent contextEvent)
    {
        ServletContext servletContext = contextEvent.getServletContext ();
        WebApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext (servletContext);
        Map<String, Servlet> servlets = ((Map<String, Servlet>)appContext.getBean ("servlets", Map.class));
        for (Map.Entry<String, Servlet> bean : servlets.entrySet ())
        {
            Dynamic dynamic = servletContext.addServlet (bean.getKey (), bean.getValue ());

            // add multipart config if present
            if (bean.getValue ().getClass ().isAnnotationPresent (MultipartConfig.class))
                dynamic.setMultipartConfig (new MultipartConfigElement (
				    bean.getValue ().getClass ().getAnnotation (MultipartConfig.class)));
                
            dynamic.addMapping (bean.getKey ());
        }
    }

Because the container doesn't scan the annotations of servlets added to it dynamically like this, we have to replicate any behavior that annotations would otherwise be used for - here I check for the presence of the MultipartConfig annotation on each servlet's class, and if it is present I set the appropriate MultipartConfigElement on the servlet's registration. You may find you want to handle additional configuration options, and they can easily be added to this logic at this point.

Now all that's left is to add some servlets. Create a HelloWorldServlet in the usual way, and then register it with your Spring applicationContext.xml:

Listing 8: applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"
    default-autowire="byName">

    <util:map id="servlets">
        <entry key="/hello"><bean class="com.example.web.HelloWorldServlet" /></entry>
    </util:map>
</beans>

Obviously, it is now trivial to add dependencies and configuration properties to your servlets, as they are processed by Spring as though they were any other bean. You can also use Spring's Aspect-Oriented Programming facilities to define wrappers around your servlets' functions (e.g. to provide logging, user authentication, transactions, or any other behavior you want applied to your entire site). And we now only have to configure each servlet in one place - and as an added bonus, the configuration is simpler than is required for web.xml.

That’s all for this article. See you next time.



My main area of specialization is Java and J2EE. I have worked on many international projects like Recorders,Websites,Crawlers etc.Also i am an Oracle Certified java professional as well as DB2 certified

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login