STRUTS ACTION - AGGREGATING ACTIONS IN STRUTS
If you are a Struts developer then you might have experienced the pain of writing huge number of Action classes for your project. The latest version of struts provides classes using which you can aggregate a related set of actions into a single unified action. In this article we will see how to achieve this. Struts provides four important classes for this purpose. These classes are called as Dispatchers. The important Dispatchers that struts provides includes : DispatchAction, ActionDispatcher , LookupDispatchAction and MappingDispatchAction.
All these classes can be found in the package org.apache.struts.actions. Let us look in to each of these in detail. Our examples use the simple CRUD actions.
DispatchAction: In this type of aggregation, the action class must extend DispatchAction class as shown.
public final class CRUDDispatchAction extends DispatchAction {
public ActionForward create(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
return (mapping.findForward("success"));
}
...
and the action mapping will be as
<action path="/crudDispatchAction" type="com.companyname.projname.CRUDDispatchAction" name="formName" scope="request" input=" homeDef" parameter="methodToCall">
<forward name="success" path="targetDefName"/>
</action>
in your jsp you can call this action as
<html:link action="crudDispatchAction?methodToCall=create">Create</html:link>
...
Observe that the above class extends DispatchAction and so you cannot use this method if your class already extends your (some) super class (eg., the class where the session is validated/invalidated). Here the user has to send a query string variable (methodToCall) to set the action name to call.
ActionDispatcher: This flavor of aggregation is same as DispatchAction except that we need not extend ActionDispatcher, so we can use this method even if our class extends a super class. The following code snippet shows this scenario.
public final class CRUDActionDispatcher extends Action {
protected ActionDispatcher dispatcher = new ActionDispatcher(this, ActionDispatcher.DEFAULT_FLAVOR);
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
return dispatcher.execute(mapping, form, request, response);
}
The DEFAULT_FLAVOR field suggests that the default parameter is "method" if none is specified as parameter in struts-config.xml (eg,. methodToCall).
ActionDispatcher flavor also needs methodToCall parameter to be set (using hidden variable or a query string) as in case of DispatchAction.
LookupDispatchAction: This type of aggregation is useful in situations where in you have multiple submit buttons in a single form. The class must extend LookupDispatchAction. However, the great thing about this type is that its java script free. That means, you need not set any hidden variables or pass query string however, you must use submit buttons as shown.
<html:submit property="submit"><bean:message key="button.create"/></html: submit >
<html:submit property="submit"><bean:message key="button.read"/></html: submit >
...
The example Action class will be as follows
public class CRUDLookUpDispatchAction extends LookupDispatchAction {
protected Map getKeyMethodMap() {
Map map = new HashMap();
map.put("button.create", "create");
…
return map;
}
public ActionForward create(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
return (mapping.findForward("success"));
}
Observe the getKeyMethodMap() method. The submit button names are specified in a Map and their keys comes from MessageResources file. Struts picks up the name from this file and redirects it to the value specified in the Map. The calling code in jsp however has multiple submit buttons only differing in their names.
MappingDispatchAction: This aggregation extends MappingDispatchAction class. This is the most useful type among the four types available. But as seen in other cases, you can use this type only when your action does not extend any other action. The good thing about this type is that the action mappings can differ and so need not be the same as in all other cases. To illustrate this consider the below mappings.
<action path="/createMappingAction" type="com.bodhtree.CRUDMappingDispatchAction" scope="request" input="homeDef" parameter="create">
<forward name="success" path="targetDef"/>
</action>
<action path="/readMappingAction" type="com.bodhtree.CRUDMappingDispatchAction" name=" formName" scope="request" input="homeDef" parameter=" read">
<forward name="success" path="targetDef"/>
</action>
Notice that in the first action mapping, there is no form bean while in the second the bean name is specified. This means that the user has the flexibility to change the mapping according to his needs and hence not been contained to use a constant mapping for all the CRUD actions. Note that in all the other types of aggregations, we must use the same mapping for all the CRUD actions.
Conclusion: Each of these types has their own pros and cons. DispatchAction is the default type which uses java script and we must extend DispatchAction to use it, ActionDispatcher is same as DispathAction except that we do not extend any action , LookupDispatchAction gives the flexibility to use multiple submit buttons while MappingDispatchAction allows us to change the action mappings according to our need. So each one of these has a particular usage and which one to use depends on the user requirement.
About Author:
Mr. Praveen, You can contact him at kbabu@bodhtree.com
|
Current Comments
20 comments so far (post your own) View All Comments Latest 10 Comments:I'm getting this error can anyone help me?
500 Internal Server Error
java.lang.NoClassDefFoundError: org/apache/struts/actions/LookupDispatchAction
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at com.evermind[Oracle Application Server Containers for J2EE 10g (9.0.4.0.0)].util.OC4JSecureClassLoader.defineClassEntry(OC4JSecureClassLoader.java:172)
at com.evermind[Oracle Application Server Containers for J2EE 10g (9.0.4.0.0)].naming.ContextClassLoader.defineClass(ContextClassLoader.java:1154)
at com.evermind[Oracle Application Server Containers for J2EE 10g (9.0.4.0.0)].naming.ContextClassLoader.findClass(ContextClassLoader.java:390)
at java.lang.ClassLoader.loadClass(Unknown Source)
at com.evermind[Oracle Application Server Containers for J2EE 10g (9.0.4.0.0)].naming.ContextClassLoader.loadClass(ContextClassLoader.java:138)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.apache.struts.chain.commands.util.ClassUtils.getApplicationClass(ClassUtils.java:54)
at org.apache.struts.chain.commands.util.ClassUtils.getApplicationInstance(ClassUtils.java:71)
at org.apache.struts.chain.commands.servlet.CreateAction.createAction(CreateAction.java:98)
at org.apache.struts.chain.commands.servlet.CreateAction.getAction(CreateAction.java:68)
at org.apache.struts.chain.commands.AbstractCreateAction.execute(AbstractCreateAction.java:90)
at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)
at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:190)
at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:304)
at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:190)
at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at com.evermind[Oracle Application Server Containers for J2EE 10g (9.0.4.0.0)].server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:765)
at com.evermind[Oracle Application Server Containers for J2EE 10g (9.0.4.0.0)].server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:317)
at com.evermind[Oracle Application Server Containers for J2EE 10g (9.0.4.0.0)].server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:790)
at com.evermind[Oracle Application Server Containers for J2EE 10g (9.0.4.0.0)].server.http.HttpRequestHandler.run(HttpRequestHandler.java:270)
at com.evermind[Oracle Application Server Containers for J2EE 10g (9.0.4.0.0)].server.http.HttpRequestHandler.run(HttpRequestHandler.java:112)
at com.evermind[Oracle Application Server Containers for J2EE 10g (9.0.4.0.0)].util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:186)
at java.lang.Thread.run(Unknown Source)
Posted by assa on Friday, 01.25.08 @ 15:07pm | #46119
Refer this link for an extended version of this article :
http://www.roseindia.net/struts/aggregating-actions-struts.shtml
Posted by Praveen on Friday, 12.7.07 @ 17:58pm | #41548
Hi ,
I'm getting the same message of Request[/search] does not contain handler parameter named 'reqCode'.
Does any one get have the solution
Posted by HASNAOUI BILEL on Thursday, 11.15.07 @ 14:24pm | #37485
i am rajesh,how to aggregate actoin classes in struts.Can anyone shown with an example.The shown above is not so clear.
Posted by Rajesh Reddy on Wednesday, 10.3.07 @ 11:34am | #31288
the code u have given r tresure worth.thanks praveen...
Posted by armsoft on Tuesday, 08.7.07 @ 14:58pm | #22857
Article is good for a fresher to know about Dispatchers but we need more description with examples that should help us more.
Thanks
Sowjanya.
Posted by sowjanya on Wednesday, 08.1.07 @ 22:26pm | #22446
Hi I am getting this error Can anyone please solve it???
I am using DispatchAction and while posting data this error occurs on JRun Server.How can I sort out this problem??
Thanks
Deepak
deepaksrivastavaz@gmail.com
07/12 16:55:14 warning Error while parsing POST data
java.lang.IllegalArgumentException: Connection reset
at javax.servlet.http.HttpUtils.parsePostData(HttpUtils.java:242)
at jrun.servlet.JRunRequest.parsePostData(JRunRequest.java:402)
at jrun.servlet.JRunRequest.getParameters(JRunRequest.java:382)
at jrun.servlet.JRunRequest.getParameter(JRunRequest.java:273)
at jrun.servlet.ForwardRequest.getParameter(ForwardRequest.java:169)
at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:118)
at jrun.servlet.FilterChain.doFilter(FilterChain.java:94)
at jrun.servlet.FilterChain.service(FilterChain.java:101)
at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:91)
at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:252)
at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:527)
at jrun.servlet.http.WebService.invokeRunnable(WebService.java:168)
at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:451)
at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)
- Request[/displayNOSCockpit] does not contain handler parameter named command
- Unhandled Exception thrown: class java.net.SocketException
07/12 16:55:14 error Connection reset by peer: socket write error
java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at jrun.servlet.http.WebOutputStream$PendingOutputStream.write(WebOutputStream.java:127)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:66)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:124)
at jrun.servlet.http.WebOutputStream.close(WebOutputStream.java:52)
at jrun.servlet.JRunResponse.closeFinal(JRunResponse.java:337)
at jrun.servlet.JRunResponse.sendError(JRunResponse.java:573)
at jrun.servlet.JRunResponse.sendError(JRunResponse.java:479)
at org.apache.struts.actions.DispatchAction.unspecified(DispatchAction.java:238)
at org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:260)
at org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:216)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at jrun.servlet.FilterChain.doFilter(FilterChain.java:86)
at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125)
at jrun.servlet.FilterChain.doFilter(FilterChain.java:94)
at jrun.servlet.FilterChain.service(FilterChain.java:101)
at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:91)
at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:252)
at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:527)
at jrun.servlet.http.WebService.invokeRunnable(WebService.java:168)
at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:451)
at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)
Posted by Deepak on Thursday, 07.12.07 @ 17:00pm | #21151
i had one doubt
how many action classes are developing in on project
Posted by shyamprasad on Thursday, 06.14.07 @ 12:26pm | #19184
i had an doubt, that while i was developing a project with 4 buttons using struts validations. I have developed the buttons using html tags lib.
when i click on the every button it is showing to provide the info that has tobe stored. now what exactly i need to do. for getting the info of 4buttons.
Posted by manju on Sunday, 06.10.07 @ 11:57am | #18786
Please mail me to this mail id : kpraveen@myself.com. Also, please note that your questions are specific or related to the topic discussed above.
Regards,
P R A V E E N
http://www.javahome.co.nr
kpraveen@myself.com
Posted by Praveen on Thursday, 06.7.07 @ 11:45am | #18473