<meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/> <meta name='google-adsense-platform-domain' content='blogspot.com'/> <!-- data-ad-client=ca-pub-4320963827702032 --> <!-- --><style type="text/css">@import url(https://www.blogger.com/static/v1/v-css/navbar/3334278262-classic.css); div.b-mobile {display:none;} </style> </head><body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/platform.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d7256432\x26blogName\x3dThe+Frustrated+Programmer\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLACK\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttps://frustratedprogrammer.blogspot.com/search\x26blogLocale\x3den_US\x26v\x3d2\x26homepageUrl\x3dhttp://frustratedprogrammer.blogspot.com/\x26vt\x3d4213664491834773269', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>
| Friday, July 23, 2004

It not pretty, but in large web applications, you need to pass around data in the URL from time to time. Usually it has to do with passing something about the state of the application. Its either this or put it in the session. I don't like the session because:
  • Everything you put in the session can bog down performance if you need to replicate your session for failover.
  • Its too hard to keep track of whats in the session. Users can jump around your application and easily jumble things up.
Putting things in the URL solves both these problems. But as of today in Struts, your still stuck without an easy way to do this. Struts wants you to define static URLs in your forwards via struts-config.xml. But if you want to modify them dynamically in your Action, your left writing the same code everyone on the planet writes. Here's an example, it was written by Jan Sorensen, I found it on the struts mailing list.


/*
* ParameterizedActionForward.java
*
* Created on August 3, 2001, 11:45 AM
*/

package org.apache.struts.action;

import java.net.URLEncoder;

/**
*
* @author Jan Soresen
* @version
*/
public class ParameterizedActionForward extends ActionForward {

/** Create a new ParameterizedActionForward,
* populated from an ActionForward
* @param forward Populate the receiver from this ActionForward
*/
public ParameterizedActionForward(ActionForward forward) {
setPath(forward.getPath());
setRedirect(forward.getRedirect());
firstParameter = getPath().indexOf('?') == -1;
}

/** Create a new ParameterizedActionForward,
* based on an ActionForward found in an ActionMapping
* @param mapping The ActionMapping to get the base forward from
* @param forwardName The ActionMapping to get the base forward from
*/
public ParameterizedActionForward(ActionMapping mapping, String forwardName) {
this(mapping.findForward(forwardName));
}

/** Create a new ParameterizedActionForward
* @param forward The base ActionForward
* @param key The key of the parameter
* @param value The value of the parameter
*/
public ParameterizedActionForward(ActionForward forward, String key, String value)
{
this(forward);
addParameter(key, value);
}

/** Create a new ParameterizedActionForward
* @param mapping The ActionMapping to get the base forward from
* @param forwardName The ActionMapping to get the base forward from
* @param key The key of the parameter
* @param value The value of the parameter
*/
public ParameterizedActionForward(ActionMapping mapping, String forwardName,
String key, String value) {
this(mapping, forwardName);
addParameter(key, value);
}

/** Add a new parameter
* @param key The key of the parameter
* @param value The value of the parameter
*/
public void addParameter(String key, String value) {
StringBuffer buffer = new StringBuffer(getPath());
buffer.append(firstParameter ? '?' : '&apm;');
firstParameter = false;
buffer.append(URLEncoder.encode(key));
buffer.append('=');
buffer.append(URLEncoder.encode(value));
setPath(buffer.toString());
}

private boolean firstParameter;


}

With this class you can write code like this:

ParameterizedActionForward forward =
new ParameterizedActionForward( mapping.findForward("updateSuccess"), "foo", "bar" );
return forward;


Its a shame, because there has been a bug submitted for this for over 3 years. It even has a good patch similar to the file above, complete with testcases. Why hasn't it been added to CVS? I'm not sure, but I know how you can help. Exercise your right to vote on this bug!