Posts Tagged ‘servlets

07
Apr
11

Extracting and Tokenizing HTTP Path Variables

This page describes how to extract and tokenizing HTTP path variable(s).

Background

URL Path is often used by RESTful applications to pass scoping information. Applications often parse this information and use it to retrieve data from the server-side.

Modern frameworks like Spring MVC 3 and The RESTlet frameworks have means of extracting tokens from HTTP Path. However if you aren’t using those frameworks then the information on this page will be helpful.

The utility class described on this page will allow you to extract tokens present in URL paths. For example “item/{itemId}/subcomponent/{subComponentId}”

Requirements

  • Maven 2
  • Spring 2.5.6 or above
  • Basic understanding of Struts MVC

Start a new project

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp

groupId: com.test
artifactId: pathVarTest

Answer the rest of the questions with defaults “Just hit the enter key”,

cd to the project base folder.

cd pathVarTest

Since this is a web project maven2 does not create the java source folder.

Create missing folders now.
mkdir -p src/main/java/com/test
mkdir -p src/main/webapp/WEB-INF/jsp

Modify the project Configuration

The pom.xml file should look something like this.

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test</groupId>
  <artifactId>pathVarTest</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>pathVarTest Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring</artifactId>
            <version>2.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>2.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-servlet_2.5_spec</artifactId>
            <version>1.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>    
  </dependencies>
  <build>
    <finalName>pathVarTest</finalName>    
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <configuration>
                    <scanIntervalSeconds>2</scanIntervalSeconds>
                    <stopKey>s</stopKey>
                </configuration>
            </plugin>
        </plugins>
  </build>
</project>

PathUtil

The following is where the URL path gets tokenized. It is a static utility class that could be used from a Spring MVC controller or a HTTPServlet Class.

src/main/java/com/test/PathUtil.java

package com.test;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Helper class to allow URL path's to be parsed into 
 * EL Expression type tokens.
 */
public class PathUtil {
	public static final Map<String, String> getPathVariables(String patternStr,
			String[] names, String path) {
		String regExPattern = patternStr.replace("*", "(.*)");
		Map<String, String> tokenMap = new HashMap<String, String>();
		Pattern p = Pattern.compile(regExPattern);
		Matcher matcher = p.matcher(path);

		if (matcher.find()) {
			// Get all groups for this match
			for (int i = 0; i <= matcher.groupCount(); i++) {
				String groupStr = matcher.group(i);
				if (i != 0) {
					tokenMap.put(names[i - 1], groupStr);
				}
			}
		}
		return tokenMap;
	}
}

Spring MVC Controller

The following controller class responds to the following URL’s

  • item/{itemId}
  • item/{itemId}/subcomponent/{subComponentId}

src/main/java/com/test/ItemController.java

package com.test;
 
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
public class ItemController {
 
    @RequestMapping(value="/item/*", method = RequestMethod.GET)
    public String itemInfo(HttpServletRequest request) {
    	final String pattern = "/item/*";
		final String[] names = {"itemId"};
		Map<String, String> pathMap = PathUtil.getPathVariables(pattern, names, request
				.getPathInfo());
   	
		request.setAttribute("pathMap", pathMap);
    	
        return "index";
    }
    @RequestMapping(value="/item/*/subcomponent/*", method = RequestMethod.GET)
    public String subComponentItemInfo(HttpServletRequest request) {
    	final String pattern = "/item/*/subcomponent/*";
		final String[] names = {"itemId", "subComponentId"};
		Map<String, String> pathMap = PathUtil.getPathVariables(pattern, names, request
				.getPathInfo());
   	
		request.setAttribute("pathMap", pathMap);
    	
        return "index";
    }
}

JSP

The following JSP is used to display the Hash Map that contains the results. I haven’t put any work in making it look pretty. Its just functional.

src/main/webapp/WEB-INF/jsp/index.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
<meta http-equiv="Content-Language" content="en-us" />
 
</head>
<body>
<h3>This are the tokens from the URL Path Info String</h3>
<h3><c:out  value="${pathMap}"/></h3>
</body>
</html>

Web App Configuration

src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
 
    <display-name>Archetype Created Web Application</display-name>
    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>
</web-app>

Spring MVC Configuration file

This is a pretty standard Spring MVC configuration file.

src/main/webapp/WEB-INF/spring-servlet.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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 
http://www.springframework.org/schema/context
 
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
    <context:annotation-config />
    <context:component-scan base-package="com.test" />
 
    <bean
        class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
    <bean
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
 
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean> 
</beans>

Test the application

Start the Jetty Servlet Engine to test the application with 1 scoping variable.

  1. Open a command line window and navigate to the project base directory.
  2. Type the following at the command line:
    mvn clean compile jetty:run
    
  3. Navigate to the following URL: http://localhost:8080/app/item/235
  4. You should see the next page which prints “{itemId=235}”.

Test the application with multiple scoping variables.

  1. Navigate to the following URL: http://localhost:8080/app/item/123/subcomponent/456
  2. You should see the next page which prints “{subComponentId=456, itemId=235}”.

Creating a WAR file

If you want to run the application in another environment you can create a war file and drop it into a server of your choice. This method will also package up any runtime dependencies and put them in the /WEB-INF/lib folder of the WAR file.

mvn clean compile package

The war file should appear in the project’s “target/” folder…

That’s all for now!

Advertisements



Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 77 other followers

November 2017
S M T W T F S
« Oct    
 1234
567891011
12131415161718
19202122232425
2627282930  

Blog Stats

  • 842,358 hits