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]

Reply via email to