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>