Creating a Pretty URL With Struts Framework and URLRewrite

On this tutorial im trying to create a pretty URL using one of java’s most famous framework, Struts Framework. I want to change a usual struts URL from into a pretty URL such as news/newsID/newsTitle. The main benefits are your links get easily indexed by search engines and make them easy-to-read and easy-to-remember.

Im using urlrewrite library for url rewriting. As for this example, im using old version of struts 1.3.8 and iBatis ORM version 2.3.4.

First as always, a simple MySQL table

        id bigint NOT NULL AUTO_INCREMENT,
        title VARCHAR(100) NOT NULL,
        content text NOT NULL,
        createddate DATETIME NOT NULL,
        PRIMARY KEY (id)
insert into news 
        (id, title, content, createddate) 
        values (1, 'A Tale of Two More Earths?', 'Example of Content', '2011-12-26 19:00:00');
insert into news 
        (id, title, content, createddate) 
        values (2, 'India: Boat Capsizes; 11 Missing', 'Example of Content number 2', '2011-12-27 19:00:00');

and a javabean and xml for database mapping. And please be aware, im injecting Slugify class to getUrl method so i could get a clean url property inside this bean.

package com.edw.bean;

import com.edw.util.Slugify;
import java.util.Date;

public class News {

    private Long id;
    private String title;
    private Date createddate;
    private String content;
    // added for pretty URL
    private String url;

    // other getter and setter

    // do title formatting for a clean url
    public String getUrl() {
        return Slugify.slugify(getTitle());

    public void setUrl(String url) {
        this.url = url;

And this is my xml queries

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-// SQL Map 2.0//EN" "" >
<sqlMap namespace="news" >
  <resultMap id="newsBean" class="com.edw.bean.News" >    
    <result column="id" property="id" jdbcType="BIGINT" />
    <result column="title" property="title" jdbcType="VARCHAR" />
    <result column="content" property="content" jdbcType="LONGVARCHAR" />
    <result column="createddate" property="createddate" jdbcType="TIMESTAMP" />
  <select id="select" resultMap="newsBean" >    
    select id, title, createddate, content
    from news    
  <select id="selectWithId" resultMap="newsBean" parameterClass="java.lang.Integer" >    
    select id, title, createddate, content
    from news    
    where id = #id#

This is my utility java class, its main purpose is to encode and clean news titles so they can fit into URLs.

package com.edw.util;

import java.text.Normalizer;
import org.apache.log4j.Logger;

public class Slugify {

    private static final Logger logger = Logger.getLogger(Slugify.class);
     * modified version of Jozef Ševcík's slugify
     * @link
     * @param input
     * @return formatted URL
    public static String slugify(String input) {
        if (input == null || input.length() == 0) {
            return "";
        try {
            String toReturn = normalize(input);            
            toReturn = toReturn.replaceAll("[^\\w\\s\\-]", "");
            toReturn = toReturn.replace(" ", "-");
            toReturn = toReturn.toLowerCase();
            toReturn = URLEncoder.encode(toReturn, "UTF-8");
            return toReturn;
        } catch (Exception e) {
            logger.error(e, e);
        return "";


    private static String normalize(String input) {
        if (input == null || input.length() == 0) {
            return "";
        return Normalizer.normalize(input, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "");

And an xml file to load all my xml queries

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig
PUBLIC "-// SQL Map Config 2.0//EN"


    <transactionManager type="JDBC" commitRequired="false">
        <dataSource type="SIMPLE">

            <property name="SetAutoCommitAllowed" value="false"/>
            <property name="DefaultAutoCommit" value="false"/>
            <property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/>
            <!-- my database name = pepe -->
            <property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost/pepe"/>
            <property name="JDBC.Username" value="root"/>
            <property name="JDBC.Password" value="xxx"/>

    <sqlMap resource="com/edw/sqlmap/news.xml"/>

A java class to load my xml configuration

package com.edw.sqlmap.config;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;

public class SqlMapConfig {

    protected static final SqlMapClient sqlMap;

    static {
        try {
            Reader reader = Resources.getResourceAsReader("com/edw/sqlmap/sqlmapconfig.xml");
            sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);       
        } catch (Exception e){
            throw new RuntimeException("Fatal Error.  Cause: " + e, e);

    public static SqlMapClient getSqlMap() {
        return sqlMap;

Next is im creating a Struts Action class

package com.edw.action;

import com.edw.bean.News;
import com.edw.sqlmap.config.SqlMapConfig;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class NewsAction extends org.apache.struts.action.Action {

    private static final String SUCCESS = "success";
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        List<News> newses = null;
        if(request.getParameter("id") != null)
            newses = SqlMapConfig.getSqlMap().queryForList("news.selectWithId", Integer.parseInt(request.getParameter("id")));       
            newses = SqlMapConfig.getSqlMap().queryForList("");       
        request.setAttribute("newses", newses);
        return mapping.findForward(SUCCESS);

dont forget to register NewsAction to strutsconfig.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"


        <forward name="welcome"  path="/"/>

        <action path="/news" type="com.edw.action.NewsAction">
            <forward name="success" path="/WEB-INF/pages/news.jsp" />
        <action path="/Welcome" forward="/welcomeStruts.jsp"/>

    <message-resources parameter="com/edw/res/ApplicationResource"/>    

Next is my presentation layer. Im using a plain JSP and Struts tags, and put my JSP file under WEB-INF folder, so it cant be accessed directly.

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>

<%@taglib uri="" prefix="bean"%>
<%@taglib uri="" prefix="logic"%>

        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>News Page</title>

        <logic:iterate name="newses" id="news">            
            <bean:write name="news" property="id"/> , 
            <bean:write name="news" property="title"/>, 
            <bean:write name="news" property="createddate"/>, 
            <bean:write name="news" property="content"/>            
            <br />
            <a href="${pageContext.request.contextPath}/news/<bean:write name="news" property="id"/>/<bean:write name="news" property="url"/>">link</a>
            <br />
            <br />
            <br />


Next is where the magic of urlrewrite starts, first i register urlrewrite filter to my web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="" xmlns:xsi="" xsi:schemaLocation="">

and create a urlrewrite xml under WEB-INF

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-// UrlRewrite 3.2//EN"

        <note>for news with parameters</note>
        <note>display all news</note>


The final result is my url path will be changed from




This are my netbeans project structure and libraries.

Have Fun (&)

No Comments

Leave a Comment

Please be polite. We appreciate that.
Your email address will not be published and required fields are marked