First I'd like to point out that I like to keep an application as consistent as possible. That means that I like my links, my form submits, my buttons to all act similarly - this makes it very easy for a new developer to the project to figure out what is going on.
Concerning the first approach, it appears the type of command called has to match the button name. I don't like this approach at all. Sometimes you later need to change the button names or even a worse scenario, you sometimes need to have the same button name used on different forms go to the same Action class but call a different dispatch method (for example with the "ok" or "proceed" button).
The second approach runs into some of the same of problems as the LookupDispathAction.. maintenance problems. In that approach you have to maintain what action method gets called by editing an ActionForm class. This becomes sort of unintuitive. It works but to me it just does provide for a consistent approach.
What I like about the simple use of MappingDispatchAction, and using some extremely simple javascript for button situations, is that the approach is easy to follow. For a developer to figure what action dispatch method is going to be called he/she simply always can tell by the MappingDispatch mapping. This works for links, form submits and for button submits. (I'm thinking the later approach you mentioned would work with links and form submits but would then require you always pass in a request parameter that matches a button name similar to what you need to do when using a LookupDispatchAction).
Another feature I like of just always using a MappingDispatchAction is that maintenance seems easier. The only things you maintain are an action mapping in your struts config (which you always have to have anyway) and a dispatch method name (which you always need also). There is no need to worry about maintaining any button names and what they correspond to. You end up not caring about how they get to your Action dispatch method and you let the pure view(JSP) worry about calling the proper action mapping. Just my preference I guess for consistency's sake.
Michael McGrady wrote the following on 9/13/2004 2:48 AM:
*The following is from http://wiki.apache.org/struts/StrutsCatalogMultipleImageTagsSimplified . If you don't like this solution, I would be interested in your thinking, Rick. If you are interested, I have a comprehensive solution to everything to do with buttons and images. I am going to add to it, but it is pretty well developed.
*
*This is an efficient way to end forever that pesky and recurrent problem of how to use multiple image buttons in your forms. (N.B.: This solution also works for non-image (submit) buttons by using values like <input type="submit" name="add.x" value="add"> in the submit button. Or, just use <input type="submit" name="button" value="add"> for a different solution for <input type="submit"> versus <input type="image">)*
*Assume that you have code not unlike:*
<input type='image' name='update' src='change.gif'> <input type='image' name='delete' src='nuke.gif'>
*or, in Struts' image tag:*
<html:image property='submit' src='change.gif'/> <html:image property='delete' src='nuke.gif'/>
*Now, how do we know which image has been clicked? The answer has been complicated and costly in the past. Here is a simple way to achieve everything at a low cost and with great flexibility and freedom.*
String button = null; Enumeration enum = request.getParameterNames(); String parameterName = null; while(enum.hasMoreElements()) { parameterName = (String)enum.nextElement(); if(parameterName.endsWith(".x")) { button = parameterName.substring(0,parameterName.indexOf('.')); } }
*There you go. /If you clicked the image with name='submit', then the variable button will have the value "submit"./ I suggest that you toss out the LookupDispatchActions, the ButtonCommands, etc. This is a done deal. You can clearly seek other ways to ensure a bit more safety. For example, the code works equally as well with "submit.button" as it does with "submit". Elegant, no, eh? I use a class that encapsulates this functionality as follows:** *
*public class ImageTagUtil { public static String getName(HttpServletRequest request) { String command = null; String buttonValue = null; Enumeration enum = request.getParameterNames();
while(enum.hasMoreElements()) { buttonValue = (String)enum.nextElement(); if(buttonValue.endsWith(".x")) { command = buttonValue.substring(0,buttonValue.indexOf('.')); } } return command; } } *
*Surprisingly, some people still prefer the way I used to do this. I think they just like the plain fanciness of it all. For those people, here is code that is less extensible, more coupled, heavier, etc. This code is comparatively not as good, in my opinion. There is a further use of button objects which requires that you create a separate button object for each image button you use on an html page. That solution is very heavy and significantly affects the footprint of a struts page. /If/ you are going to use buttons, /which, again, is not recommended/, I would suggest the following more lightweight version, which creates and then nulls one button object per request. The use of an inner class allows the necessary communications between the action form and the button class. *
*public class AdminButtonForm extends ActionForm { protected CrackWillowButton button; protected String command;
public CrackWillowButton getButton() { if(button == null) { this.button = new CrackWillowButton(); } return button; }
public String getCommand() { String hold = command; command = null; return hold; }
public void setCommand(String command) { this.command = command; }
public void reset() { button = null; }
public class CrackWillowButton { private Integer x, y; public static final String CREATE = "create"; public static final String RETRIEVE = "retrieve"; public static final String UPDATE = "update"; public static final String DELETE = "delete"; public static final String SUBMIT = "submit";
public CrackWillowButton() { }
public CrackWillowButton getCreate() { setCommand(this.CREATE); return button; }
public CrackWillowButton getRetrieve() { setCommand(this.RETRIEVE); return button; }
public CrackWillowButton getUpdate() { setCommand(this.UPDATE); return button; }
public CrackWillowButton getDelete() { setCommand(this.DELETE); return button; }
public CrackWillowButton getSubmit() { setCommand(this.SUBMIT); return button; }
public void setX(Integer x) { if(y != null) { reset(); } else { this.x = x; } }
public void setY(Integer y) { if(x != null) { reset(); } else { this.y = y; } } } } *
*So, don't use buttons, but just mine the value of the [name].x request parameter. *
*Michael McGrady Cap't of the Eh Team*
Anyway, looking forward to you thinking on this.
Michael
Rick Reumann wrote:
Not sure which list this question/topic really belongs on so posting to both. (I'm bringing it up on the dev list because I'm thinking maybe the base MappingDispatchAction could/should be modified).
Some design background. I like to keep related tasks belonging in one Dispatch Action class (flavor to be discussed). This is a typical approach, yet one of the problems is desided on the type of DispatchAction ... keep it DispatchAction or use one of the subclasses LookupDispatch or MappingDispatch.
First off I really don't like the LookupDispatchAction. I've used it extensively in a large application and it becomes a real pain. It becomes really ugly to use when you start having some generic button names that you reuse for different things. For example a changing requirment was that we ended up having to use a button called "Ok" a lot (I know stupid). So sometimes "Ok" would submit to the same LookupDispatchAction but would need to access different methods. You end up then having to create 'fake' button names in your resources file just so the LookupDispatchAction can work correctly. Maintenance of the LookupDispatch can be a pain also. Anyway...
Until the MappingDispatchAction, I've been relatively content with using a standard DispathAction. What I like about the MappingDispatchAction is that it works really nicely for links - you don't have to append a dispatch parameter name to the URL. It's also nice for typical forms since you don't have to provide a hidden dispatch parameter on the page.
The only problem I'm running into it is when you have a form with more than one button and each button should call a different dispatch method. I haven't really figured out a good way to work this out with the MappingDispatchAction. I think trying to change the form's action attribute using JavaScript will be ugly (assuming it can even be done, I've never tried it). The only solution I can think of at the moment would be to override the getMethodName method of MappingDispatch and provide an extra mapping in your config where the parameter would change to something like parameter="dispatchMethod"
The overridden getMethodName might look like
protected String getMethodName( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String parameter) throws Exception { if( "dispatchMethod".equals( parameter ) { parameter = request.getParameter(parameter); } return parameter }
This would allow you to use the MappingDispatchAction like a DispatchActoin when needed. The only caveat is you would have to make sure the if statement in the above is what you wanted. (Probably better to pull the parameter name "dispatchMethod" from a properties file or constants class).
Maybe there is a much better way to accomplish what I'm concerned with?
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
-- Rick
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]