Anthony N. Frasso wrote:
My head hurts. :)  Thanks for everyone's help.  I've
gotten a number of responses, it's just that I'm still
confused.  It's obvious I have something drastically
wrong with my understanding of the workflow of Struts,
so I'd like to clear that up now.

Let's take my list page, ListRoles.jsp:

[...]

When the form is submitted, the form bean is
populated.  Here is the form bean
(EditRolesForm.java):

[...]

Nice and simple. :)  Now, when the form is submitted,
and as I understand it, *after* the form bean is
populated, the execute method is called for the Action

Yes, that's right; the JSP submits to an action, and Struts looks up and populates the form bean for that action before calling it.

class.  Here is my the Action class I created for this
action (EditRolesAction.java):

public class EditRolesAction extends TransactionAction
{
    public ActionForward execute(ActionMapping
mapping,
                                 ActionForm form,
                                 HttpServletRequest
                                     request,
                                 HttpServletResponse
                                     response)
        throws Exception {

        EditRolesForm editRolesForm =
            (EditRolesForm) form;

        // at this point, I believe the form is
        // *already* populated.

Yes.


        // do some computation, place the correct
        // role in the request scope, and determine
        // the correct forward
        request.setAttribute("role", role);
        return mapping.findForward(...);
    }
}

So now, assuming the user has asked to do an edit, the
EditRole.jsp is generated:
>
> [...]

It sounds like the step you're missing there is that the forward should point to an action, not directly to a JSP -- say, PrepareEditRoleAction. It's *that* action that handles setting up the form bean that EditRole.jsp will use to render the form.

Here is the EditRoleForm form bean:

public class EditRoleForm {

    private int id;
    private String name;
    private String description;

    private boolean permissionA;
    private boolean permissionB;
    ...
    private boolean permissionN;
}

So the question is... I *don't* have access to the
EditRoleForm form bean in the EditRolesAction Action
class; there, it's the EditRolesForm form bean (sorry
about the confusing terminology; just node that
EditRoles refers to modifying the roles in some
aspect, and EditRole refers to editing a specific
role).

Right. You have two concerns here: 1) receive the the initial form and process it, determining what page to show next; and 2) setting up and displaying the next page. By adding a PrepareEditRoleAction and forwarding through that, rather than directly to EditRole.jsp, you have somewhere to manage item 2.

Albert Sapp Wrote:

"I am puzzled by your comment that you don't have a
form bean before you get to the jsp.  We do this all
the time.  Say I want to display a list of inventory
items for a user.  I retrieve a list of inventory
items matching the query data the user gave me and
create an array of inventory item forms to pass to the
jsp.  I convert information from the list inventory
item beans and place each one into the array.  Then
just set the array as a parameter in request scope and
then use that parameter to build my jsp.

I do the same if I am providing a means for a user to
update information on an item.  I initialize the form
in the prep action, display the jsp and read the form
in the processing action.  So I read/write to the same

inventory item form bean and read/write to my DAO
inventory item bean for the backend.  The only reason
I use 2 different beans is it was mandated to separate
the view from the model and I need to convert some
data say the unit of issue ID to a actual unit of
issue for the user."

I guess the question is... sure, I can provide the
request scope with the necessary information.  In this
case, the request scope has the Role object as an
attribute.  Are you saying that at the top of the
EditRole.jsp page I initialize the form bean myself,
using servlets?  Or is this "prep" action something
else?  I guess I'm not sure where to do this, as I am
confused.  If you can edit my code, or at least hint
at where I need to do this initialization, it would be
greatly appreciated.

The usual idiom is to do the form bean initialization in an action, as described above.

Laurie Harper Wrote:

"Yes you do, the form is passed in as one of the
parameters to execute()."

Isn't this the form bean that was populated *after* it
has been submitted?  I need the form bean that is
going to be used to create the next JSP page.

Hence the separation of concerns described above. You want an action whose concern is processing a form submission, but you also need one whose concern is preparing for the display of the form. By having this pair for each form, you can have the same form bean passed in to the prep action before the page is rendered, and the process action after the page's form is submitted.

"The typical pattern is for the action to be invoked
via an action mapping, populate the form bean and
forward to the JSP.  It's during this action
processing that you copy your business data into the
form bean, thus initializing it.

The form in the JSP is then bound to the form bean,
both reading from and writing to the same place. When
the form is submitted, another action is invoked and
in that action you copy the appropriate data from the
form to wherever you need it to complete the
operation."

So it sounds like I might be missing an action here...
I need two Actions per JSP?  One before the JSP is
generated, and one after?  How do I do this?

Exactly. Bascally, for each action you have that process the submission of form X, add an action mapping for 'prepare to display form X'. Anywhere you have a forward pointing at the JSP that renders form X, change it to point to the prepare action mapping. Here's a simple example:

  <action path="/PrepFormA class="package.PrepFormA"
    name="FormABean" validate="false" forward="FormA.jsp"/>

  <action path="/SubmitFormA" class="package.SubmitFormA"
    name="FormABean" validate="true">
      <forward name="editFoo" path="/PrepFoo.do"/>
      <forward name="editBar" path="/PrepBar.do"/>
  </action>

Repeat with /PrepFoo + /SubmitFoo, /PrepBar + /SubmitBar, ... mappings.

"To answer your earlier question, you *can* have a
form which takes its values from a bean other than the
form bean -- I think you've already had that working
for some input types. However, in the case of
checkboxes, that's going to be problematic, since the
input's value is doing double duty -- it's specifying
the value that should be submitted *if* the checkbox
is selected, and also specifying the value that the
checkbox property must have for it to be considered
selected already.

If you don't want to copy the permission data from
your model into the form bean before rendering the
form, "

I would like to do this... just don't know how....

"you can do as previously suggested and put the entire
business object into the form bean; that solution actually doesn't prevent the properties being
written/updated. There are problems with this approach
for certain types of inputs, but for boolean values rendered as checkboxes it should work fine."

To do this, in your PrepareEditRoleAction, you'd simply retrieve the model data (Role) object and set it as a property on your EditRoleForm form bean.

Thanks again for everybody's help.  I'm sorry I just
don't quite understand yet what it is I have to do
(thought this would originally be a simple question!).

I think small code snippets would be the most useful
in me understanding what I have to do, because right
now, I *think* I understand the concepts... just don't
know the syntax, and the web/my book aren't terribly
helpful.

You might want to take the time to explore some of the sample applications, examples and cookbooks -- the MailReader example might be a particularly good one to look at to see this pattern in action (note, I haven't looked at the Struts1 version of MailReader in a long time, so I don't know if it follows exactly the patterns described above, but it should give a concrete example of at least one strategy for this.)

HTH,

L.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to