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]
