I like the idea of making the parameters/arguments passed between actions declarative verses programmatic. This makes it very easy to define "interfaces" between pages. The following code shows our solution using the extendibility of struts metadata but it would be slick if it was a feature of the baseline.
In the event that the forward is not a redirect, we just stage the data in request scope for the target page in a Map collection. This allows data to be staged in the formbean that was not in the request parameters. The target action just uses the populate method of beanutils to move corresponding from the map cached in the request to the target formbean. A redirect is easy because the request processor does the dirty work. It would be fun if this kind processing could be moved up in the framework. Maybe both options of encoding arguments (declarative, programmatic) could complement each other and both redirect and forward could have similar behavior? Gary <action path="/viewResultsetI" type="com.rustts.action.RusttsDispatchAction" className="com.rustts.action.RusttsActionMapping" input=".dynaPage" name="ResultsetDynaForm" scope="session" parameter="cmd"> <set-property property="pageId" value="viewResultsetIPage" /> <forward name="quit" path="/viewPage.do" redirect="true" className="com.rustts.action.RusttsForwardAction" <!-- values pulled from the from bean that interface with the target page --> <set-property property="arg0" value="year" /> <set-property property="arg1" value="month" /> </forward> </action> // action execute method stages the form and request. You might have // parameters in the form bean not in the request. if (mapping instanceof IRusttsActionMapping) { ((IRusttsActionMapping) mapping).setState(form, request); } package com.rustts.action; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; /** * @author Gary VanMatre * * Extended the base action mapping to add custom properties * use the set-property element in the XML mapping to associate * a page with an action. */ public class RusttsActionMapping extends ActionMapping implements IRusttsActionMapping { private String pageId = null; // make sure that these values will not be persisted in a // distributed deployment. I believe that struts caches it's // metadata in application scope which is not replicated (only session) private transient ActionForm form = null; private transient HttpServletRequest request = null; /** * Returns the pageId. * @return String */ public String getPageId() { return pageId; } /** * Sets the pageId. * @param pageId The pageId to set */ public void setPageId(String pageId) { this.pageId = pageId; } /** * This method's purpose is to stage date for the custom action forward class <code>RusttsForwardAction</code>. * The reference should be effective only for the dialog duration of a method call. * The method is invoked by @see com.rustts.action.RusttsDispatchAction#execute(ActionMapping, ActonForm, HttpServletRequest, HttpServletResponse). */ public void setState(ActionForm form, HttpServletRequest request) { this.form = form; this.request = request; } /** * This method has been overridden to initiate the propagation * of arguments on an action forward. * If the mapping class realizes interface * <code>IRusttsForwardAction</action>, the specified properties * in the struts configuration file will be pulled from the form bean and * staged for the next page. * The method of staging depends on if the action forward is a redirect. */ public ActionForward findForward(String name) { ActionForward forward = super.findForward(name); if ((forward != null) && (forward instanceof IRusttsForwardAction) && (request != null) && (form != null)) { forward = ((IRusttsForwardAction) forward).stageForward(form, request); } return forward; } protected void finalize() { pageId = null; form = null; request = null; } } package com.rustts.action; import java.net.URLEncoder; import java.util.Iterator; import java.util.Map; import java.util.TreeMap; import java.util.TreeSet; import javax.servlet.http.HttpServletRequest; import org.apache.commons.beanutils.BeanUtils; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; /** * @author Gary VanMatre * */ public class RusttsForwardAction extends ActionForward implements IRusttsForwardAction { private String[] args = new String[10]; /** * Returns the arg0. * @return String */ public String getArg0() { return args[0]; } /** * Returns the arg1. * @return String */ public String getArg1() { return args[1]; } /** * Returns the arg10. * @return String */ public String getArg10() { return args[10]; } /** * Returns the arg2. * @return String */ public String getArg2() { return args[2]; } /** * Returns the arg3. * @return String */ public String getArg3() { return args[3]; } /** * Returns the arg4. * @return String */ public String getArg4() { return args[4]; } /** * Returns the arg5. * @return String */ public String getArg5() { return args[5]; } /** * Returns the arg6. * @return String */ public String getArg6() { return args[6]; } /** * Returns the arg7. * @return String */ public String getArg7() { return args[7]; } /** * Returns the arg8. * @return String */ public String getArg8() { return args[8]; } /** * Returns the arg9. * @return String */ public String getArg9() { return args[9]; } /** * Sets the arg0. * @param arg0 The arg0 to set */ public void setArg0(String arg0) { args[0] = arg0; } /** * Sets the arg1. * @param arg1 The arg1 to set */ public void setArg1(String arg1) { args[1] = arg1; } /** * Sets the arg10. * @param arg10 The arg10 to set */ public void setArg10(String arg10) { args[10] = arg10; } /** * Sets the arg2. * @param arg2 The arg2 to set */ public void setArg2(String arg2) { args[2] = arg2; } /** * Sets the arg3. * @param arg3 The arg3 to set */ public void setArg3(String arg3) { args[3] = arg3; } /** * Sets the arg4. * @param arg4 The arg4 to set */ public void setArg4(String arg4) { args[4] = arg4; } /** * Sets the arg5. * @param arg5 The arg5 to set */ public void setArg5(String arg5) { args[5] = arg5; } /** * Sets the arg6. * @param arg6 The arg6 to set */ public void setArg6(String arg6) { args[6] = arg6; } /** * Sets the arg7. * @param arg7 The arg7 to set */ public void setArg7(String arg7) { args[7] = arg7; } /** * Sets the arg8. * @param arg8 The arg8 to set */ public void setArg8(String arg8) { args[8] = arg8; } /** * Sets the arg9. * @param arg9 The arg9 to set */ public void setArg9(String arg9) { args[9] = arg9; } /** * @return String[] list of formbean properties that * need to be propagated to the next page via request * scope (forward) or query string (redirect) */ public String[] getArgs() { TreeSet set = new TreeSet(); for (int i = 0; i < args.length; ++i) if (args[i] != null) set.add(args[i]); String[] noDup = new String[set.size()]; set.toArray(noDup); set = null; return noDup; } /** * This is a factory method to handle the prorogation * of key arguments to the target of the action forward. * if the action is a redirect, a query string of encoded * arguments will be added to the path. Otherwise the data * (Map) will be staged on the request. */ public ActionForward stageForward( ActionForm form, HttpServletRequest request) { ActionForward targetForward = null; try { Map sourceArgs = BeanUtils.describe(form); String[] targetNames = getArgs(); Map targetArgs = (Map) new TreeMap(); for (int i = 0; i < targetNames.length; ++i) { if (sourceArgs.containsKey(targetNames[i])) { Object arg = sourceArgs.get(targetNames[i]); if (arg != null) targetArgs.put(targetNames[i], arg); arg = null; } } if (redirect) { if (!targetArgs.isEmpty()) { StringBuffer buff = new StringBuffer(path); //look for an existing query string delimiter boolean firstArg = true; if (buff.toString().indexOf('?') > -1) { firstArg = false; } else buff.append("?"); Iterator vi = targetArgs.keySet().iterator(); while (vi.hasNext()) { String name = (String) vi.next(); Object arg = targetArgs.get(name); if (arg != null) { String value = URLEncoder.encode(arg.toString()); buff.append((firstArg) ? "" : "&").append( name).append( "=").append( value); firstArg = false; value = null; } arg = null; name = null; } //build an new ActionForward with the new query targetForward = new ActionForward(buff.toString(), true); buff = null; vi = null; } else targetForward = this; } else { //stage the data pickle in request scope for the next page request.setAttribute( com.rustts.Globals.RUSTTS_FORWARD_KEY, targetArgs); targetForward = this; } targetNames = null; sourceArgs = null; targetArgs = null; } catch (Exception e) { targetForward = this; } return targetForward; } } -----Original Message----- From: Hubert Rabago [mailto:[EMAIL PROTECTED] Sent: Wednesday, December 17, 2003 2:33 PM To: Struts Developers List Subject: Re: Context attributes (was: Struts 2.0 Discussion Forum) What about allowing Action objects to add the parameters themselves? It adds a great deal of flexibility, and doesn't limit the set of parameters that can be used, nor does it require using the request or session attributes. ActionForward forward = mapping.findForward("lookup"); forward.addParameter("param1","value1"); forward.addParameter("param2",2); forward.addParameter("param3",3.0); return forward; Or maybe support for both (merge and addParameter). This will also make bug 866 go away. --- Ted Husted <[EMAIL PROTECTED]> wrote: > Don Brown wrote: > > Is there one? I have several ideas I'd like to toss into the > discussion. > > > > Don > > There's a Whiteboard page in the Wiki. > > http://nagoya.apache.org/wiki/apachewiki.cgi?StrutsWhiteboard > > I'll be posting more about Jericho, but wanted to get what I had so far > (a starter DTD) under CVS. > > One other idea that I've been meaning to bring up in the wake of > wildcard Mappings, is the idea of merging context attributes into > ActionForward paths. For example, we could do something like > > <forward name="lookup" merge="true" path="/lookup.do?key={key}" /> > > and have it replace {key} with request.getAttribute("key") (or session > if not found). > > -Ted. > __________________________________ Do you Yahoo!? New Yahoo! Photos - easier uploading and sharing. http://photos.yahoo.com/ --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]