No, I was talking about something even more mundane...

public class AdminSystemControlAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
ClientFB clFB = new ClientFB();
form.setLogosList(clFB.getLogosList());
form.setSignaturesList(clFB.getSignaturesList());
form.setManagementReportsList(clFB.getReportList());
return mapping.findForward("defaultForward");
} // End execute()
} // End class


This is an Action I use, with a bunch of other stuff removed for brevity, when I initially show the System Control screen of one application I did. These are three ArrayLists, generated from a database, which are used to populate some dropdowns.

Now, this particular screen is a high-level admin screen, and you can perform probably 40 different functions from it. So, there's a bunch of Actions, generally speaking, one per function. But, after each, I need to populate those dropdowns again.

So, what you could of course do is have a helper class that does the above, and everything else required to set up the screen.

But, what has always bothered me about this, and it's a debatable point I'll say right up front, is that I tend to view the Control layer as a little closer to the View than the Model. Application flow control I consider more of a presentation consideration than a business logic consideration. Having business delegates encapsulating the actual business logic of a system makes perfect sense to me, but populating dropdowns is really a view task. So, most people would agree your not going to access a database from JSP code to populate dropdowns for instance, so your going to be doing it in the Control layer.

But, why add complexity to the code base by having "view delegates"? That's really what your doing by having helper classes called from an Action to populate a screen. I think there are some reasonable arguments to be made for this, but I've always felt it's just a little redundant.

So, getting to my point... instead of adding a helper class to do this screen population from the other 40 Actions, I would instead just do this at the end of those Actions:

  AdminSystemControlAction ascac = new AdminSystemControlAction();
  af = ascac.execute(mapping, form, request, response);
  return mapping.findForward("whatever");

See? It's nothing more than treating the first "setup" Action as a helper class! Like I said, pretty mundane. But what it does, in my mind at least, is reduces the number of classes I have.

You do have to be a little careful that the setup Action can function this way... It might be possible to write code in it that has some bad side-effects when called this way, but it's a pretty minor consideration generally speaking.

That's what I was talking about. Nothing grandiose by any stretch, but it's surprising that a lot of Struts developers don't even realize this is possible! I've told this to a number of people and they've reacted with surprise, they thought for some reason you couldn't just instantiate an Action and call execute() on it. I guess they forget it's just a class after all.

--
Frank W. Zammetti
Founder and Chief Software Architect
Omnytex Technologies
http://www.omnytex.com

Dakota Jack wrote:
Lo, Frank,

Very interesting and very helpful.  I think I am starting to see what
you guys are thinking.  I have dealt with the same problems, of
course.

I bet we do something similar, Frank.  Here is a class I use which
uses other classes like actions, but they are not actions.  Is this
what you do?


public final class AdminAction extends StateBaseAction {

  public AdminAction() {
  }

  public ActionForward execute(ActionMapping mapping,
                               ActionForm form,
                               HttpServletRequest request,
                               HttpServletResponse response)
      throws IOException,
             ServletException {
    HttpSession    session = request.getSession();
    StateContainer state   =
((StateContainer)request.getSession().getAttribute(SiteConstant.HOST_STATE_CONTAINER));

    if(state == null) {
      state  = StateContainerFactory.getWebmasterStateContainer();
      ServletContext cntxt = servlet.getServletContext();
      cntxt.setAttribute(SiteConstant.HOST_STATE_CONTAINER,state);
    }

    User user = ((User)((Map)state.getMap()).get(SiteConstant.USER));

    if(state == null) {
      state = StateContainerFactory.getStateContainer(user);
      session.setAttribute(SiteConstant.HOST_STATE_CONTAINER,state);
    }

    String layout = (String)state.get(SiteConstant.LAYOUT);

    ActionForward forward    = null;
    try {
      forward = method(this,mapping,form,request,response);
    } catch (Exception e) {
      StdOut.log(SiteConstant.ERROR_LOG,"\n\nAdminAction error = " +
e.getMessage() + " e = " + e);
      ActionMessages errors = new ActionMessages();
      errors.add(Globals.ERROR_KEY, new ActionMessage("webmaster.admin.token"));
      saveErrors(request, errors);

      StringBuffer sb = new
StringBuffer("").append(layout).append("_").append(mapping.getInput());
      forward = new ActionForward(sb.toString());
    }

    return forward;
  }

  public ActionForward exit                             (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionExit().execute(mapping,form,request,response); }
  public ActionForward guestOptions                     (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionGuestOptions().execute(mapping,form,request,response);
}
  public ActionForward hostGuestChange                  (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionHostGuestChange().execute(mapping,form,request,response);
}
  public ActionForward hostGuestCreate                  (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionHostGuestCreate().execute(mapping,form,request,response);
}
  public ActionForward hostGuestDelete                  (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionHostGuestDelete().execute(mapping,form,request,response);
}
  public ActionForward hostGuestOptions                 (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionHostGuestOptions().execute(mapping,form,request,response);
}
  public ActionForward hostGuestView                    (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionHostGuestView().execute(mapping,form,request,response);
}
  public ActionForward hostHostChange                   (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionHostHostChange().execute(mapping,form,request,response);
}
  public ActionForward hostHostOptions                  (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionHostHostOptions().execute(mapping,form,request,response);
}
  public ActionForward hostLookAndFeel                  (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionHostLookAndFeel().execute(mapping,form,request,response);
}
  public ActionForward hostLookAndFeelChange            (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionHostLookAndFeelChange().execute(mapping,form,request,response);
}
  public ActionForward webmasterChange                  (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionWebmasterChange().execute(mapping,form,request,response);
}
  public ActionForward webmasterHostApplication         (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterHostApplication().execute(mapping,form,request,response);
}
  public ActionForward webmasterHostApplications        (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterHostApplications().execute(mapping,form,request,response);
}
  public ActionForward webmasterHostApplicationAlbum    (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterHostApplicationAlbum().execute(mapping,form,request,response);
}
  public ActionForward webmasterHostApplicationChat     (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterHostApplicationChat().execute(mapping,form,request,response);
}
  public ActionForward webmasterHostApplicationDownload (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterHostApplicationDownload().execute(mapping,form,request,response);
}
  public ActionForward webmasterHostApplicationUpload   (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterHostApplicationUpload().execute(mapping,form,request,response);
}
  public ActionForward webmasterHostCreate              (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterHostCreate().execute(mapping,form,request,response);
}
  public ActionForward webmasterHostDelete              (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterHostDelete().execute(mapping,form,request,response);
}
  public ActionForward webmasterHostDeleteShow          (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterHostDeleteShow().execute(mapping,form,request,response);
}
  public ActionForward webmasterHostView                (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterHostView().execute(mapping,form,request,response);
}
  public ActionForward webmasterHostsOptions            (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterHostsOptions().execute(mapping,form,request,response);
}
  public ActionForward webmasterOptions                 (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionWebmasterOptions().execute(mapping,form,request,response);
}
  public ActionForward webmasterLayoutChange            (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterLayoutChange().execute(mapping,form,request,response);
}
  public ActionForward webmasterLookAndFeel             (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterLookAndFeel().execute(mapping,form,request,response);
}
  public ActionForward webmasterSchemeChange            (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterSchemeChange().execute(mapping,form,request,response);
}
  public ActionForward webmasterSetFileUploadExtensions (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterSetFileUploadExtensions().execute(mapping,form,request,response);
}
  public ActionForward webmasterTextChange              (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new 
AdminActionWebmasterTextChange().execute(mapping,form,request,response);
}
  public ActionForward webmasterView                    (ActionMapping
mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
return new AdminActionWebmasterView().execute(mapping,form,request,response);
}
} ///;-)

Thanks for your input.

Jack


On Wed, 05 Jan 2005 18:40:40 -0500, Frank W. Zammetti <[EMAIL PROTECTED]> wrote:

Hope no one minds an extra two cents here...

I've personally chained actions on a couple of ocassions, but what I
find myself doing more of in cases like this where there is a "setup
Action" and X number of "processing Actions" possible for a given screen
is I code the setup Action in such a way that the other Actions can
simply instantiate it and call execute().  It's relatively simple to
make it function as a normal Action, as well as basically a helper class
for another Action (and without any special branching logic or anything
like that).  This is very similar to chaining, but doesn't incur the
overhead (however much it really is) doing a forward, and doesn't get
into all the complexity you can sometimes run into with two request
contexts in essence when you chain (i.e., ActionForms reseting when you
don't want them to and dealing with tokens and all that jazz).

Having only taken a cursory glance at JSF at this point, and attended a
conference or two where it was discussed, I've had mixed feelings on it,
but I do like the relatively tight coupling you are referring to.  I too
am generally of the "DECOUPLE EVERYTHING!" mindset, but in this case I
think it makes sense.  Frankly, I think Microsoft got it mostly right
with ASP.Net, and JSF can in many ways be compared to that conceptually.

The flip-side (where my mixed feelings come in, partially) is that I've
never really bought into the whole "call the server to handle every
little UI event" model.  I suppose that's a separate debate though :)

--
Frank W. Zammetti
Founder and Chief Software Architect
Omnytex Technologies
http://www.omnytex.com

Dakota Jack wrote:

Hello, again, Jan,

Having read Ted's response, I can now understand what you were saying.
I just could not see why doing something like chaining an action made
any sense or believe that people actually do that.  What I would
naturally do is to provide a common helper class, Setup.java (or
Result.java), rather than a helper Action, ResultAction.java or even a
framework to hand the whole issue.  Am I missing something?  I have in
essence asked the same thing of Ted.

Maybe the difference is that I just have not even considered chaining
actions.  I thought that was just an example of something silly that
some people might do.  And, to my embarrassment, I guess that some
people think that is a good idea?

Jack


On Tue, 4 Jan 2005 15:28:05 -0000, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote:


Jack,

A use case is:

- Two struts actions (say CreateAction and EditAction call the same jsp
to view the result (say result.jsp).
- This result.jsp needs some setup (eg. a list of items for a selection
box).
- The natural way to populate such a list in struts, is in the action.
- To prevent having the logic to populate the list both in CreateAction
and in EditAction,
some users create a new ResultAction, where they do the view
preparation.
- Then they chain the action (this is controversal stuff):
. In CreateAction they do creation logic, and than forward to
ResultAction.
. In EditAction they do edit logic, and than forward to ResultAction.

As discussed in bug 16107:
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=16107

Regards, Jan

-----Original Message-----
From: Dakota Jack [mailto:[EMAIL PROTECTED]
Sent: dinsdag 4 januari 2005 15:34
To: Struts Developers List
Subject: Coupling, Struts and JSF

Craig,

I have been trying, again, to understand your position on Shale.  In
the wiki, you say "[y]et in Struts 1.x, for example, the setup logic
and processing logic end up in two different Actions, requiring
multiple action mappings".  Could you expand on this a bit,
remembering, if you would, that I am not a novice.  I have not run
into a problem here and wonder what you are talking about in concrete
terms.  I personally do not run into this problem and am
philosophically counter to the idea that coupling can be good.  I am
pretty "knee jerk" in favor of decoupling where possible.  This is one
of the main reasons I have difficulty with JSF.  I really am contrary
to the coupling.

Jack

--
------------------------------

"You can lead a horse to water but you cannot make it float on its
back."

~Dakota Jack~

"You can't wake a person who is pretending to be asleep."

~Native Proverb~

"Each man is good in His sight. It is not necessary for eagles to be
crows."

~Hunkesni (Sitting Bull), Hunkpapa Sioux~

-----------------------------------------------

"This message may contain confidential and/or privileged information.
If you are not the addressee or authorized to receive this for the
addressee, you must not use, copy, disclose, or take any action based
on this message or any information herein. If you have received this
message in error, please advise the sender immediately by reply e-mail
and delete this message. Thank you for your cooperation."

---------------------------------------------------------------------
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]






--------------------------------------------------------------------- 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