View Javadoc
1   /*
2    * $Id$
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts.extras.actions;
22  
23  import jakarta.servlet.ServletException;
24  import jakarta.servlet.http.HttpServletRequest;
25  import jakarta.servlet.http.HttpServletResponse;
26  
27  import org.apache.struts.action.ActionForm;
28  import org.apache.struts.action.ActionForward;
29  import org.apache.struts.action.ActionMapping;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  
33  /**
34   * <p>An abstract <strong>Action</strong> that dispatches to a public method
35   * that is named by the <code>parameter</code> attribute of the corresponding
36   * ActionMapping.  This is useful for developers who prefer to combine many
37   * related actions into a single Action class.</p>
38   *
39   * <p>To configure the use of this action in your <code>struts-config.xml</code>
40   * file, create an entry like this:</p>
41   *
42   * <pre><code>
43   *   &lt;action path="/saveSubscription"
44   *           type="org.example.SubscriptionAction"
45   *           name="subscriptionForm"
46   *          scope="request"
47   *          input="/subscription.jsp"
48   *      parameter="method"/&gt;
49   * </code></pre>
50   *
51   * <p>where 'method' is the name of a method in your subclass of
52   * MappingDispatchAction that has the same signature (other than method name)
53   * of the standard Action.execute method.  For example, you might combine the
54   * methods for managing a subscription into a  single MappingDispatchAction
55   * class using the following methods:</p>
56   *
57   * <ul>
58   *
59   * <li>public ActionForward create(ActionMapping mapping, ActionForm form,
60   * HttpServletRequest request, HttpServletResponse response) throws
61   * Exception</li>
62   *
63   * <li>public ActionForward edit(ActionMapping mapping, ActionForm form,
64   * HttpServletRequest request, HttpServletResponse response) throws
65   * Exception</li>
66   *
67   * <li>public ActionForward save(ActionMapping mapping, ActionForm form,
68   * HttpServletRequest request, HttpServletResponse response) throws
69   * Exception</li>
70   *
71   * <li>public ActionForward delete(ActionMapping mapping, ActionForm form,
72   * HttpServletRequest request, HttpServletResponse response) throws
73   * Exception</li>
74   *
75   * <li>public ActionForward list(ActionMapping mapping, ActionForm form,
76   * HttpServletRequest request, HttpServletResponse response) throws
77   * Exception</li>
78   *
79   * </ul>
80   *
81   * <p>for which you would create corresponding &lt;action&gt; configurations
82   * that reference this class:</p>
83   *
84   * <pre><code>
85   *  &lt;action path="/createSubscription"
86   *          type="org.example.SubscriptionAction"
87   *          parameter="create"&gt;
88   *      &lt;forward name="success" path="/editSubscription.jsp"/&gt;
89   *  &lt;/action&gt;
90   *
91   *  &lt;action path="/editSubscription"
92   *          type="org.example.SubscriptionAction"
93   *          parameter="edit"&gt;
94   *      &lt;forward name="success" path="/editSubscription.jsp"/&gt;
95   *  &lt;/action&gt;
96   *
97   *  &lt;action path="/saveSubscription"
98   *          type="org.example.SubscriptionAction"
99   *          parameter="save"
100  *          name="subscriptionForm"
101  *          validate="true"
102  *          input="/editSubscription.jsp"
103  *          scope="request"&gt;
104  *      &lt;forward name="success" path="/savedSubscription.jsp"/&gt;
105  *  &lt;/action&gt;
106  *
107  *  &lt;action path="/deleteSubscription"
108  *          type="org.example.SubscriptionAction"
109  *          name="subscriptionForm"
110  *          scope="request"
111  *          input="/subscription.jsp"
112  *          parameter="delete"&gt;
113  *      &lt;forward name="success" path="/deletedSubscription.jsp"/&gt;
114  *  &lt;/action&gt;
115  *
116  *  &lt;action path="/listSubscriptions"
117  *          type="org.example.SubscriptionAction"
118  *          parameter="list"&gt;
119  *      &lt;forward name="success" path="/subscriptionList.jsp"/&gt;
120  *  &lt;/action&gt;
121  * </code></pre>
122  *
123  * <p><strong>NOTE</strong> - Unlike DispatchAction, mapping characteristics
124  * may differ between the various handlers, so you can combine actions in the
125  * same class that, for example, differ in their use of forms or validation.
126  * Also, a request parameter, which would be visible to the application user,
127  * is not required to enable selection of the handler method. </p>
128  *
129  * @version $Rev$ $Date$
130  * @since Struts 1.2
131  */
132 public class MappingDispatchAction extends DispatchAction {
133     private static final long serialVersionUID = 8605425680931524975L;
134 
135     // -------------------------------------------------------- Class Variables
136 
137     /**
138      * The {@code Log} instance for this class.
139      */
140     private transient final Logger log =
141         LoggerFactory.getLogger(MappingDispatchAction.class);
142 
143     // --------------------------------------------------------- Public Methods
144 
145     /**
146      * Process the specified HTTP request, and create the corresponding HTTP
147      * response (or forward to another web component that will create it).
148      * Return an <code>ActionForward</code> instance describing where and how
149      * control should be forwarded, or <code>null</code> if the response has
150      * already been completed.
151      *
152      * This method dispatches the request to other methods of
153      * <code>MappingDispatchAction</code> using the 'parameter' attribute of
154      * <code>ActionMapping</code> and Java Introspection.
155      *
156      * @param mapping  The ActionMapping used to select this instance
157      * @param form     The optional ActionForm bean for this request (if any)
158      * @param request  The HTTP request we are processing
159      * @param response The HTTP response we are creating
160      * @return Return an <code>ActionForward</code> instance describing where
161      *         and how control should be forwarded, or <code>null</code> if
162      *         the response has already been completed.
163      * @throws Exception if an exception occurs
164      */
165     public ActionForward execute(ActionMapping mapping, ActionForm form,
166         HttpServletRequest request, HttpServletResponse response)
167         throws Exception {
168         // Use the overridden getMethodName.
169         return super.execute(mapping, form, request, response);
170     }
171 
172     /**
173      * Method which is dispatched to when there is no value for the parameter
174      * in the ActionMapping.  Subclasses of <code>MappingDispatchAction</code>
175      * should override this method if they wish to provide default behavior
176      * different than throwing a ServletException.
177      *
178      * @param mapping  The ActionMapping used to select this instance
179      * @param form     The optional ActionForm bean for this request (if any)
180      * @param request  The HTTP request we are processing
181      * @param response The HTTP response we are creating
182      * @return Return an <code>ActionForward</code> instance describing where
183      *         and how control should be forwarded, or <code>null</code> if
184      *         the response has already been completed.
185      * @throws Exception if an exception occurs
186      */
187     protected ActionForward unspecified(ActionMapping mapping, ActionForm form,
188         HttpServletRequest request, HttpServletResponse response)
189         throws Exception {
190         String message =
191             messages.getMessage("mapping.parameter", mapping.getPath());
192 
193         log.error(message);
194 
195         throw new ServletException(message);
196     }
197 
198     /**
199      * <p>Returns the parameter value.</p>
200      *
201      * @param mapping  The ActionMapping used to select this instance
202      * @param form     The optional ActionForm bean for this request (if any)
203      * @param request  The HTTP request we are processing
204      * @param response The HTTP response we are creating
205      * @return The <code>ActionMapping</code> parameter's value
206      */
207     protected String getParameter(ActionMapping mapping, ActionForm form,
208         HttpServletRequest request, HttpServletResponse response)
209         throws Exception {
210 
211         return mapping.getParameter();
212 
213     }
214 
215     /**
216      * Returns the method name, given a parameter's value.
217      *
218      * @param mapping   The ActionMapping used to select this instance
219      * @param form      The optional ActionForm bean for this request (if
220      *                  any)
221      * @param request   The HTTP request we are processing
222      * @param response  The HTTP response we are creating
223      * @param parameter The <code>ActionMapping</code> parameter's name
224      * @return The method's name.
225      * @throws Exception if an error occurs
226      * @since Struts 1.2.0
227      */
228     protected String getMethodName(ActionMapping mapping, ActionForm form,
229         HttpServletRequest request, HttpServletResponse response,
230         String parameter) throws Exception {
231         // Return the unresolved mapping parameter.
232         return parameter;
233     }
234 }