aspose file tools*
The moose likes Struts and the fly likes [Struts Recipes] Dispatching actions Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Frameworks » Struts
Bookmark "[Struts Recipes] Dispatching actions" Watch "[Struts Recipes] Dispatching actions" New topic
Author

[Struts Recipes] Dispatching actions

Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4419
    
    5

One thing that has been kind of a niggling concern in my mind is the way requests are dispatched in Struts. The standard ways of dispatching, i.e. using a single property name for submit buttons and dispatching via a series of if-else statements that check the parameter value, or by using a DispatchAction always seem to have something that isn't quite right to me.

In the case of using a single property name for submit buttons and dispatching based on the value of that parameter, which is the button's label, the dependency on the button label doesn't feel right to me. Sure you can use bean:message and getResources() to kind of abstract away the value but it's still that dependency on the ApplicationResources key that bugs me.

In the case of DispatchAction, it's the linking of the Action class methods and the request parameter designated by the action mapping "parameter" attribute that bugs me. The need to use the struts-config mapping to create this link just isn't intuitive to me.

I actually wrote a Map-based POJO that allows me to write this:



This way, I'm not dependent on ApplicationResources for dispatching nor is there anything in the struts-config that I need to change in parallel if any of the commands or method names change. If a change is needed, I know I have to change the JSP and the Action, which seems more intuitive than the other methods. I haven't experienced any major difficulties with it so far. Any thoughts about this approach?

What is your preferred way of dispatching requests?


Junilu - [How to Ask Questions] [How to Answer Questions]
Karthik Guru
Ranch Hand

Joined: Mar 06, 2001
Posts: 1209
Hi Junilu,

I played with tapestry sometime back and your thoughts sound very similar to Tapestry. There is a Page java class for ever UI page/HTML. You directly embed the method/listener that needs to be invoked on click of a button in the HTML itself.

class Mypage{

public void addCustomer(IRequestCycle rc){

}

}

and in the HTML, the entry was somethign similar to this..

<input type="submit" jwcid="@Submit" listener="ognl:listeners.addCustomer"/>


There is no additional mapping bewteen UI and the action
Marc Peabody
pie sneak
Sheriff

Joined: Feb 05, 2003
Posts: 4727

Junilu,

I like where you are going with this. There are times that it is valuable to have multiple buttons that have the same "value" but do different things. Your method makes a very elegant solution.

What would put your idea over the top is if the property attribute for html:submit handled like the other inputs. That would allow your FormatCommand object to dictate what "value" to display by calling its getDo(String) method.


I like using constants, as it lessens the chances of typos causing difficult bugs:

<html:submit property="<%=Constants.COMMAND%>" value="<%=Constants.SAVE%>"/>
---------------------
String command = request.getAttribute(Constants.COMMAND);

if(Constants.SAVE.equals(command)){
...
}else...

You could combine our methods; each button would simply need its own constant.
[ January 28, 2005: Message edited by: Marc Peabody ]

A good workman is known by his tools.
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4419
    
    5

I tried using String constants but that didn't work out well because of violations of the equals() contract. And then when comparing

command.is("add")

vs.

Constants.ADD_COMMAND.equals(command.toString())

the first form is just simpler to me and I actually didn't see too much harm in hardcoding the values in this case. Writing about the DispatchAction made me start thinking though about extending FormCommand to make it do something similar.



Come to think of it though, the call would probably have to be:

cmd.dispatch(this, mapping, myForm, request, response);

Hmmm...
[ January 29, 2005: Message edited by: Junilu Lacar ]
Marc Peabody
pie sneak
Sheriff

Joined: Feb 05, 2003
Posts: 4727

Try this.

Have your Action extend DispatchAction but override the getMethodName() method.

We'll call the class DispatchSmartAction. To trigger using the new version, the user should set parameter="smart" in the ActionMapping.


And so all of your forms would extend a DispatchSmartForm which contains:


(I've thought this one through a little more thoroughly than my last post.)
Marc Peabody
pie sneak
Sheriff

Joined: Feb 05, 2003
Posts: 4727

I'm tempted to change "command" to "smart" just so the getter can be getSmart().

It would be wise to keep the naming consistent with everything else going on anyway.

I'm liking your mapping method more and more, Junilu. The bane of the DispatchAction IMO is the limitting factors when using buttons to set the method called. That's usually why I've avoided using it in the past. Mapping fixes all that.
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4419
    
    5

Marc,

I've been really bad at keeping my blog updated but I'll try to add something that discusses this in more detail and show the code for the FormCommand. Thanks for the feedback!
Jason Menard
Sheriff

Joined: Nov 09, 2000
Posts: 6450
I've been thinking about this topic myuself lately. Alot of the projects I work on use images as buttons as opposed to the traditional submit buttons. In the past I've done some JavaScript gymnastics to achieve my desired results, but I think I want to move towards using <html:img> along with ActionForms containing ImageButtonBean properties for the buttons.

You'll notice if you follow the link that Ted Husted demonstrates this by providing a getSelected() method in the ActionForm to determine which button was pressed. Well, this would still necessitate the whole if-else thing which isn't what we erally want.

What I've been thinking, and I need to go back and take a look at the source for DispatchAction to make sure I'm thinking along the proper lines, is to write a FormDispatchAction. If I remember correctly, dispatch action checks the request for the specified parameter value and dispatches accordingly. Again, I'm thinking aloud and haven't done all the necessary investigation to determine if this is all necessary, but I believe using <html:img> to submit, and without any javascript, does not leave a decent value in the request to dispatch off of. So this FormDispatchAction I'm thinking of would instead dispatch off of the value of a specified ActionForm property. This would allow you to write an ActionForm using ImageButtonBeans and a getSelected() method as shown by Ted Husted in the link I gave above.

This would probably also work for any other set of buttons with different names. Let's say we have the following jsp:



And given this ActionForm:



Then we would have our hypothetical implementation of FormDispatchAction dispatch on the "submitted" parameter.



And finally our implementation of FormDispatchAction:



Well, that's a sketch of what I've got rolling around in my head anyway. It seems something like this might be useful.
[ January 29, 2005: Message edited by: Jason Menard ]
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4419
    
    5

I used Husted's getSelected() method with image buttons in the past (I recall making some tweaks to it but unfortunately I didn't take that code with me when I left the project) Anyway, the one thing I remember not liking about it was that I had to change the ActionForm if a button was added or removed. If there were a way to use a Map-backed property in the form to capture which image button was selected, that would be better because the ActionForm would not need to be changed when an image button is added or removed.

The Map-backed property dispatcher was actually inspired by the method you describe. The FormCommand component simplifies the code in that it eliminates the need for getSubmitted() and having to add fields for each possible button. You would write:

Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4419
    
    5

Originally posted by Jason Menard:




I don't know, maybe it's just me but there's just something about using the parameter attribute of the action mapping that I don't like. Maybe it's because 3 or 4 months down the road, when I need to revisit the Action, I have to pause and stare at the code and ask myself "Now, how does the dispatching work for this action again?" Somehow, I never seem to remember right away that I need to look at the struts-config and check the parameter. Just not very intuitive to me. YMMV.
Marc Peabody
pie sneak
Sheriff

Joined: Feb 05, 2003
Posts: 4727

Julilu or Jason,

Would you mind giving feedback on my method?

Also, Junilu, I don't understand why you use that FormCommand object. Was it to make the functionality reusable? If so, why not extend ActionForm to handle it like my solution (DispatchSmartForm)?
 
 
subject: [Struts Recipes] Dispatching actions
 
Similar Threads
Disable button from code???
changing the value of html:submit
Dispatch VS LookupDispatch
LookupDispatchAction Query
difference between DispatchAction and LookupDispatchAction.