I had the need to do a 301 redirect in my Struts-based web application. I first tried using a redirect=”true” attribute in struts-config.xml like this:

<action path=”/oldPath” type=”com.myapp.controller.MyAction” name=”myForm” scope=”request” validate=”false” parameter=”Dispatch”>
<forward name=”Success” redirect=”true” path=”/do/newPath”>

This worked but it turns out it does a 302 redirect (a temporary redirect) as opposed to a permanent redirect, which is a 301. I could not find a way to make this work. What I ended up doing was the following:

Modified the old action element to use a new MyRedirAction class.

<action path=”/oldPath” type=”com.myapp.controller.MyRedirAction” name=”myForm” scope=”request” validate=”false” parameter=”Dispatch”>

The MyRedirAction class looks like this:

package com.calcxml.controller;

import java.util.HashMap;
import java.util.Map;

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;

import com.myStuff.base.ServiceException;

public class MyRedirAction extends MyBaseAction {

protected Map getKeyMethodMap() {
Map<string, string=””> map = new HashMap<string, string=””>();
return map;

public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws ServiceException {
String qs = request.getQueryString();
if (qs != null) {
response.setHeader(“Location”, “newPath” + “?” + qs);
} else {
response.setHeader(“Location”, “newPath”);
response.setHeader(“Connection”, “close” );
return null;

One gotcha that got me was that I assumed incorrectly that the query string (url parameters) would get passed along automatically in the redirect, but that was not the case. I had to add in the additional code to append the query string to the Location header variable.