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>