Recipe6.9.Submitting a Form from Localized Form Controls


Recipe 6.9. Submitting a Form from Localized Form Controls

Problem

You want to use a single Action class to process related operations where each button, which has a localized value, on a form corresponds to a specific method in the Action class.

Solution

Extend the Struts pre-built LookupDispatchAction with your own class. Provide methods for each operation you wish to be called. Each method should have the same signature as the execute( ) method. Implement the getKeyMethodMap() method, mapping the button label resource bundle key to the corresponding method name to call. The Action class shown in Example 6-6 provides three related operations in one class: create( ), update( ), and delete( ). The getKeyMethodMap( ) method returns a map where the map key is a MessageResources key for the button label, and the map value is the corresponding method name.

Example 6-6. LookupDispatchAction for related operations
package com.oreilly.strutsckbk.ch06; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.actions.LookupDispatchAction; public class MyLookupDispatchAction extends LookupDispatchAction {         public MyLookupDispatchAction( ) {         keyMethodMap = new HashMap( );         keyMethodMap.put("button.add", "create");         keyMethodMap.put("button.edit", "update");         keyMethodMap.put("button.remove", "delete");     }     protected Map getKeyMethodMap( ) {         return keyMethodMap;     }                  public ActionForward create( ActionMapping mapping,                                   ActionForm form,                                  HttpServletRequest request,                                   HttpServletResponse response)                                   throws Exception {         // create data         request.setAttribute("dispatchedTo","create");         return mapping.findForward("success");   }             public ActionForward update( ActionMapping mapping,                                   ActionForm form,                                  HttpServletRequest request,                                   HttpServletResponse response)                                   throws Exception {         // update data         request.setAttribute("dispatchedTo","update");         return mapping.findForward("success");     }             public ActionForward delete( ActionMapping mapping,                                   ActionForm form,                                  HttpServletRequest request,                                   HttpServletResponse response)                                   throws Exception {         // delete data         request.setAttribute("dispatchedTo","delete");         return mapping.findForward("success");     }         }

In the actions that use your LookupDispatchAction, specify the request parameter whose value will be the button's value. When your custom Action receives the request, the base LookupDispatchAction performs a reverse lookup on the MessageResources, retrieving the matching key for the value from the bundle:

<action    path="/LookupDispatchActionTest"            name="TestForm"            type="com.oreilly.strutsckbk.ch06.MyLookupDispatchAction"        parameter="methodToCall">     <forward name="success" path="/lookup_dispatch_test.jsp"/> </action>

On a form that submits to this action, use the bean:message tag as the body for each submit button rendered using html:submit. The property attribute value on the html:submit tag must match the parameter attribute value for the corresponding action in the struts-config.xml file. Struts will look up the method to call from your LookupDispatchAction implementation, using the map returned in the getKeyMethodMap( ) method. The JSP page in Example 6-7 (lookup_dispatch_test.jsp) specifies three submit buttons corresponding to the three operations provided by the class in Example 6-6.

Example 6-7. JSP that submits to a LookupDispatchAction
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <html> <head>   <title>Struts Cookbook - Chapter 6 : Lookup Dispatch Action Test</title> </head> <body bgcolor="white"> <h2>Lookup Dispatch Action Test</h2>   <html:form method="get" action="/LookupDispatchActionTest">     Name:&nbsp;<html:text property="name"/>     <p>     <html:submit property="methodToCall">          <bean:message key="button.add"/>     </html:submit>      <html:submit property="methodToCall">         <bean:message key="button.edit"/>     </html:submit>      <html:submit property="methodToCall">         <bean:message key="button.remove"/>     </html:submit>      </p>   </html:form>   <hr />   <c:if test="${not empty TestForm.map.name}">     Name:&nbsp;<c:out value="${TestForm.map.name}"/><br />     Dispatch Method:&nbsp;<b><c:out value="${dispatchedTo}"/></b>   </c:if> </body> </html>

Discussion

The LookupDispatchAction, included with Struts, performs the same function as the DispatchAction that it extends. It is designed to allow for a single Action class to service related operations triggered by clicking submit buttons on a form. Unlike the DispatchAction, the LookupDispatchAction doesn't require the use of JavaScript to set a request parameter. Instead, you add a method to your subclass of LookupDispatchAction that returns a map of key/value pairs. The key matches the MessageResources key for the corresponding button label, and the value represents the name of the corresponding method to call.

In the Solution, the relevant key/value pairs values defined in the MessageResources properties file are shown here:

button.add = Add Me button.edit = Change Me button.remove = Remove Me

Each property valuethat is, the right-side of the pairis retrieved using the bean:message tag:

<html:submit property="methodToCall">     <bean:message key="button.add"/> </html:submit>

When you click this button, the URL will look something like:

http://localhost/jsc-ch06/LookupDispatchActionTest.do? name=Bill&methodToCall=Add+Me

Struts will use the value of the methodToCall request parameter to look up the key for the value from the MessageResources. For this example, it will retrieve the key "button.add". Struts then uses the Map returned in your class's getKeyMethodMap( ) method to determine the method to call. For the example, this will be the create() method. The method is discovered and invoked using Java reflection.

The performance of reflection operations has improved in JDK 1.4. In particular, reflective method invocation, used by the DispatchAction (and subclasses), and object instantiation have been rewritten. These operations perform several times faster than in previous releases of the JDK. For Struts applications the overhead of using reflection is minimal.


Using the LookupDispatchAction can seem a little tricky at first. Once you understand how it works, it can reduce substantially the number of classes you have to maintain. It ties nicely into Struts support for internationalization. If you are localizing button labels using Struts bean:message tags, you have the necessary presentation hooks in place to leverage the LookupDispatchAction.

See Also

If you are using images as submit buttons instead of text-based buttons, use the DispatchAction shown in Recipe 6-8 and set the methodToCall request parameter using JavaScript. For an alternative approach when using image buttons, check out Michael McGrady's page on the Struts Wiki at http://wiki.apache.org/struts/StrutsCatalogMultipleImageButtonsWithNoJavaScript.



    Jakarta Struts Cookbook
    Jakarta Struts Cookbook
    ISBN: 059600771X
    EAN: 2147483647
    Year: 2005
    Pages: 200

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net