Matt RaibleMatt Raible is a Web Developer and Java Champion. Connect with him on LinkedIn.

The Angular Mini-Book The Angular Mini-Book is a guide to getting started with Angular. You'll learn how to develop a bare-bones application, test it, and deploy it. Then you'll move on to adding Bootstrap, Angular Material, continuous integration, and authentication.

Spring Boot is a popular framework for building REST APIs. You'll learn how to integrate Angular with Spring Boot and use security best practices like HTTPS and a content security policy.

For book updates, follow @angular_book on Twitter.

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

Mapping buttons to methods

In AppFuse, I use Struts' LookupDispatchAction to map submit buttons to methods in my Actions. It's caused quite a headache for i18n, but Jaap provided a workaround and now everything works fine. However, as I did the Spring MVC implementation this weekend, I didn't have to do any complicated "button value -> method name" mapping. Part of it was because I didn't need to, but also because I discovered that you can easily just check if the button's name was passed in. Explaining this with code is probably easier. Let's say you have three buttons on a page:

The HTML code for the above buttons is:

<input type="submit" name="save" value="Save" />
<input type="submit" name="delete" value="Delete" />
<input type="submit" name="cancel" value="Cancel" />

Using the name as your key, you can easily check in your Action/Controller/etc. to see which button was clicked:

if (request.getParameter("save") != null) { 
    // do something
}

The nice thing about this is that it doesn't care what value you put on your button - just what you name it. It seems like all frameworks should use something like this, rather than a single parameter name (i.e. "method") that requires JavaScript on a button to change the method invoked. About a month ago, Rick Hightower mentioned that he uses a ButtonNameDispatcher for Struts. Rick, if you're reading this - I'm ready for that bad boy!

Posted in Java at May 03 2004, 09:27:52 AM MDT 12 Comments
Comments:

I just use a baseform and define the 4 or 5 standard buttons I would use. If need be, a specific subclass form can extend getSelectedButton to add a specific command.
public abstract class BaseForm extends ValidatorForm {

    public static final int
            UNDEFINED = -1,
    SAVE = 1,
    DELETE = 3;

    private String saveButton = null;
    private String deleteButton = null;

    public String getSaveButton() {
        return saveButton;
    }

    public void setSaveButton(String saveButton) {
        this.saveButton = saveButton;
    }

    public String getDeleteButton() {
        return deleteButton;
    }

    public void setDeleteButton(String deleteButton) {
        this.deleteButton = deleteButton;
    }

    public int getSelectedButton() {
        if ((saveButton != null) && (!saveButton.equals(""))) {
            return SAVE;
        } else if ((deleteButton != null) && (!deleteButton.equals(""))) {
            return DELETE;
        } else {
            return UNDEFINED;
        }
    }

Posted by Ted on May 03, 2004 at 12:23 PM MDT #

Your solution sure looks nice from the point of view where there is only one language in the world.
But have you given it a thought how those buttons could support i18N and not having to resort to scriptlet like HTML code for the buttons ?
I would be very eager to know how you see a solution for this ;-)

Posted by Werner Ramaekers on May 03, 2004 at 11:50 PM MDT #

Werner - if you use the "name" of the button to do your logic, rather than the "value" then you just have to synch up those two Strings. i18n shouldn't be an issue since you can change the "value" of the button and it doesn't affect any logic.

Posted by Matt Raible on May 03, 2004 at 11:53 PM MDT #

The same thing rather pretty can be done with Tapestry
input type="button" listener="ognl: listeners.doSave"> Where doSave - method in your PAGE class
Thats all. Very intuitive way IMHO. Tapestry the best :P

Posted by wassup on May 04, 2004 at 01:25 AM MDT #

Matt - i agree that as long as you can generate the HTML for the buttons as you have indicated you are able to work with the "name" of the button in the Struts Action.
But let me rephrase my question : I don't see how i can generate the HTML for the button using the Struts html tag library because there is no "name" attribute in the html:input tag. So in order for me to have i18n i can no longer use the Struts html taglib and i will need to use a scriptlet ?

Posted by Werner Ramaekers on May 04, 2004 at 06:30 AM MDT #

I'm assuming you mean the <html:submit> tag. You are correct in that you won't be able to use it, but (IMO) you don't really need it. Sure it saves you a few keystrokes, but it really does nothing more than that. To compare:

<html:submit styleClass="button">
    <fmt:message key="button.submit"/>
</html:submit>

... is really the same as ...

<input type="submit" class="button"
    value="<fmt:message key="button.submit"/>" />

Hmmm, it actually looks like the plain old HTML version requires less typing! Of course, if you're using HTML 4.0 compliant browsers, you could also do:

<button type="submit" class="button">
    <fmt:message key="button.submit"/>
</button>

Of course, I could be wrong - do you know if <html:submit> buys you anything over plain ol' HTML?

Posted by Matt Raible on May 04, 2004 at 10:05 AM MDT #

<html:submit property="saveButton" value="Save" styleClass="button"/>

becomes

<input type="submit" name="saveButton" class="button" value="Save">

Posted by Ted on May 04, 2004 at 11:55 AM MDT #

Hi Matt, I am actually using LookupDispatchAction, everything its nice, except when I am using links , then I have to add no translatable properties to the applicationProperties resource. I was wondering what its a better approach to that, or where could I find the work around that jaap provided. Thanks in Advance.

Posted by Javanese on May 04, 2004 at 04:05 PM MDT #

Javanese - here's my BaseAction.java. It basically re-writes LookupDispatchAction and is based on a nightly build of Struts from December.

Posted by Matt Raible on May 04, 2004 at 04:38 PM MDT #

The whole reason we use lookup dispatch in our code base is to avoid the giant if/else switch on the button properties. Using lookup dispatch lets us instead use individual methods for each button instead of a dispatching execute(...), and the code is much cleaner for it. We also provide some base mappings/methods that lookup dispatch actions inherit and because the control is in the map rather than an if/else switch, subclasses need not worry about these mappings/methods at all. The most important one for us is a "Load"/load(...) mapping that just returns getInputMapping(). The struts-config.xml uses "foo.tile" as the input for "/foo", and the standard link to one of these kinds of pages is "/foo?method=Load" so that it jumps straight to the controller for initial page load. Again, subclassed actions need not consider this at all--it "just happens". One drawback, however, is how poorly integrated controllers are compared to actions. How does a controller get at information from the form, say when the decision for what to display next depens on the input? We've been trying to keep action/controller distinct from each other, and have wound up sticking the form into the request attributes for the controller to tease back out. Not nice, but forced on us by the bolt-on nature of tiles/controllers.

Posted by B. K. Oxley (binkley) on May 05, 2004 at 08:05 AM MDT #

Thanks Matt for your prompt response, I was looking at the BaseAction.java and it seems pretty powerful action class, I wanted to use it but it will be a lot of refactoring to extend BaseAction in my classes, what could I do to avoid adding properties to the ResourceProperties file in order for my links to work.
as now its like : <.. href="user.do?action=edit" /> and in my lookupDispatchAction has:
protected Map getKeyMethodMap() {
Map map = new HashMap();
map.put("notranslate.edit", "edit"); in my ResourceProperties.properties I have the property:
notranslate.edit=edit

Posted by Javanese on May 05, 2004 at 02:58 PM MDT #

Javanese - that looks like it'll work, according to the LookupDispatchAction's javadocs.

Posted by Matt Raible on May 06, 2004 at 03:35 PM MDT #

Post a Comment:
  • HTML Syntax: Allowed