Make Servlets With Spring

In this post we will see how to define a simple servlet with Spring framework. We will use as simple example of an application that calculate the distance betweed two cities and shows the results in a JSP page.

1. The POM file

First of all lets see the pom.xml.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.madbit.springservlet</groupId>
	<artifactId>Ex2-servlet</artifactId>
	<version>1.0.0-SNAPSHOT</version>
	<packaging>war</packaging>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>3.1.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.1.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>3.1.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>3.1.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.1.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
		</dependency>		
	</dependencies>
</project>

2. Create the service classes

Now we can start to define an interface CitiService.java

package org.madbit.springexample;

public interface CityService {
	public double findDistance(String srcCity, String destCity);
}

… and the class CitiServiceImpl.java that implements the service.

package org.madbit.springexample;

import java.util.Map;

public class CityServiceImpl implements CityService {

	private Map> distanceMap;

	public Map> getDistanceMap() {
		return distanceMap;
	}

	public void setDistanceMap(Map> distanceMap) {
		this.distanceMap = distanceMap;
	}

	public double findDistance(String srcCity, String destCity) {
		Map destinationMap = distanceMap.get(srcCity);
		if(destinationMap == null) {
			throw new IllegalArgumentException("Source city not found");
		}
		Double distance = destinationMap.get(destCity);
		if(distance == null) {
			throw new IllegalArgumentException("Destination city not found");
		}
		return distance;
	}
}

3. Create the Spring bean for the service

Now we are going to define the citiService bean in applicationContext.xml. NOTE: This file must be placed under src/main/resources.

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

    <bean id="cityService"
          class="org.madbit.springexample.CityServiceImpl">
        <property name="distanceMap">
            <map>
                <entry key="New York">
                    <map>
                        <entry key="London" value="5574"/>
                        <entry key="Beijing" value="10976"/>
                    </map>
                </entry>
            </map>
        </property>
    </bean>

    <bean id="distance" class="org.madbit.springexample.servlet.DistanceHttpRequestHandler">
        <property name="cityService" ref="cityService"/>
    </bean>
</beans>

Here we have create cityService bean just with a map for NewYork and two cities. Of course, we can find a more efficient way to initialize the bean with a complete map of cities, for example from the DB. Considering this just as an example. I order to …..we have to pass the bean definition to the Spring ContextLoaderListener. To do this we have to add the following lines of code in the web.xml.

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <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>
</webapp>

In this way we have passed the applicationContext.xml file to the Spring ContextLoaderListener through the param contextConfigLocation. NOTE: We can pass more than one *.xml file to contextConfigLocation just putting all of them in the param-value. For example:

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            a.xml
            b.xml
        </param-value>
    </context-param>

4. Define the servlet

Now we can create our servlet DistanceHttpRequestHandler.java

package org.madbit.springexample.servlet;

import org.madbit.springexample.CityService;
import org.springframework.web.HttpRequestHandler;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class DistanceHttpRequestHandler implements HttpRequestHandler {
    private CityService cityService;

    public void setCityService(final CityService cityService) {
        this.cityService = cityService;
    }

    public void handleRequest(final HttpServletRequest request, final HttpServletResponse response)
        throws ServletException, IOException {
        if (request.getMethod().toUpperCase().equals("POST")) {
            String srcCity = request.getParameter("srcCity");
            String destCity = request.getParameter("destCity");
            double distance = cityService.findDistance(srcCity, destCity);
            request.setAttribute("distance", distance);
        }
        forward(request, response);
    }

    private void forward(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/jsp/distance.jsp");
        dispatcher.forward(request, response);
    }
}

5. Create the JSP page

As you can see, the servlet puts the results in the request scope and does a redirect to a JSP page, distance.jsp. Below there is the code of this jsp page:

<html>
<head>
    <title>City Distance</title>
</head>

<body>
<form method="POST">
    <table>
        <tr>
            <td>Source City</td>
            <td><input type="text" name="srcCity" value="${param.srcCity}"/></td>
        </tr>
        <tr>
            <td>Destination City</td>
            <td><input type="text" name="destCity" value="${param.destCity}"/></td>
        </tr>
        <tr>
            <td>Distance</td>
            <td>${distance}</td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="Find"/></td>
        </tr>
    </table>
</form>
</body>
</html>

6. Declare the servlet in our application

Now we need to declare our servlet in the web.xml file:

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <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>
    <servlet>
        <servlet-name>distance</servlet-name>
        <servlet-class>
            org.springframework.web.context.support.HttpRequestHandlerServlet
        </servlet-class>
    </servlet>
    
     <servlet-mapping>
        <servlet-name>distance</servlet-name>
        <url-pattern>/distance</url-pattern>
    </servlet-mapping>
</web-app>

If you want to learn more retro games news, read our magazine and subscribe to our newsletter.