Here's how to create your own simpler and more efficient version of a LookupDispatchAction.
First, your "buttons" will have the values "buttonName.dispatch" or whatever name you choose in place of ".dispatch". Once you get used to the idea, you can do fancy things with this. Second, you may want to override this with "parameters" in the Struts sense of "parameters" in your mapping. So, you will find a method name from the request as follows: protected static String getMethodName(HttpServletRequest request, ActionMapping mapping) { String methodName = null; String buttonValue = null; String paramProperty = mapping.getParameter(); if((paramProperty != null)) { methodName = paramProperty.substring(0,paramProperty.indexOf('.')); } else { Enumeration enum = request.getParameterNames(); while(enum.hasMoreElements()) { buttonValue = (String)enum.nextElement(); if(buttonValue.indexOf(".dispatch") >= 0) { methodName = buttonValue; break; } } } return methodName.substring(0,methodName.indexOf('.')); } Next you get the method itself. If there is no method, you create one and then cache it. This way you cache the methods you use for efficiency. protected Method getMethod(String name) throws NoSuchMethodException { synchronized(methods) { Method method = (Method) methods.get(name); if (method == null) { method = clazz.getMethod(name, types); methods.put(name, method); } return (method); } } The fields you need to do this are: protected Class clazz = this.getClass(); protected static MessageResources messages = MessageResources.getMessageResources ("org.apache.struts.actions.LocalStrings"); protected HashMap methods = new HashMap(); protected Class[] types = { ActionMapping.class, ActionForm.class, HttpServletRequest.class, Likewise you may want to handle unspecified and cancelled methods. protected ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String message = messages.getMessage( "dispatch.parameter", mapping.getPath(), getMethodName(request,mapping)); throw new ServletException(message); } protected ActionForward cancelled(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return null; } } Using these pieces in the execute method (coming up), you get the following dispatch method: protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String name) throws Exception { if (name == null) { return this.unspecified(mapping, form, request, response); } Method method = null; try { method = getMethod(name); } catch(NoSuchMethodException nsme) { String message = messages.getMessage("dispatch.method", mapping.getPath(), name); throw nsme; } ActionForward forward = null; try { Object args[] = {mapping, form, request, response}; forward = (ActionForward) method.invoke(this, args); } catch(ClassCastException cce) { String message = messages.getMessage("dispatch.return", mapping.getPath(), name); throw cce; } catch(IllegalAccessException iae) { String message = messages.getMessage("dispatch.error", mapping.getPath(), name); throw iae; } catch(InvocationTargetException ite) { Throwable t = ite.getTargetException(); if (t instanceof Exception) { throw ((Exception) t); } else { String message = messages.getMessage("dispatch.error", mapping.getPath(), name); throw new ServletException(t); } } return (forward); } The execute method is as follows: public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String name = getMethodName(request,mapping); if ("execute".equals(name) || "perform".equals(name)){ // Prevent recursive calls String message = messages.getMessage("dispatch.recursive", mapping.getPath()); throw new ServletException(message); } return dispatchMethod(mapping, form, request, response, name); } protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String name) throws Exception { if (name == null) { return this.unspecified(mapping, form, request, response); } Method method = null; try { method = getMethod(name); } catch(NoSuchMethodException nsme) { String message = messages.getMessage("dispatch.method", mapping.getPath(), name); throw nsme; } ActionForward forward = null; try { Object args[] = {mapping, form, request, response}; forward = (ActionForward) method.invoke(this, args); } catch(ClassCastException cce) { String message = messages.getMessage("dispatch.return", mapping.getPath(), name); throw cce; } catch(IllegalAccessException iae) { String message = messages.getMessage("dispatch.error", mapping.getPath(), name); throw iae; } catch(InvocationTargetException ite) { Throwable t = ite.getTargetException(); if (t instanceof Exception) { throw ((Exception) t); } else { String message = messages.getMessage("dispatch.error", mapping.getPath(), name); throw new ServletException(t); } } return (forward); } You put this all together into an abstract class and when you extend this class you add the methods you have as options. It is that simple. It is far simpler, I think, than the ServletFilter option. It is also really easy to code against. You can add a lot of options. Here is the abstract class: public abstract class BaseDispatchingAction extends Action { protected Class clazz = this.getClass(); protected static MessageResources messages = MessageResources.getMessageResources ("org.apache.struts.actions.LocalStrings"); protected HashMap methods = new HashMap(); protected Class[] types = { ActionMapping.class, ActionForm.class, HttpServletRequest.class, HttpServletResponse.class }; public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String name = getMethodName(request,mapping); if ("execute".equals(name) || "perform".equals(name)){ // Prevent recursive calls String message = messages.getMessage("dispatch.recursive", mapping.getPath()); throw new ServletException(message); } return dispatchMethod(mapping, form, request, response, name); } protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String name) throws Exception { if (name == null) { return this.unspecified(mapping, form, request, response); } Method method = null; try { method = getMethod(name); } catch(NoSuchMethodException nsme) { String message = messages.getMessage("dispatch.method", mapping.getPath(), name); throw nsme; } ActionForward forward = null; try { Object args[] = {mapping, form, request, response}; forward = (ActionForward) method.invoke(this, args); } catch(ClassCastException cce) { String message = messages.getMessage("dispatch.return", mapping.getPath(), name); throw cce; } catch(IllegalAccessException iae) { String message = messages.getMessage("dispatch.error", mapping.getPath(), name); throw iae; } catch(InvocationTargetException ite) { Throwable t = ite.getTargetException(); if (t instanceof Exception) { throw ((Exception) t); } else { String message = messages.getMessage("dispatch.error", mapping.getPath(), name); throw new ServletException(t); } } return (forward); } protected static String getMethodName(HttpServletRequest request, ActionMapping mapping) { String methodName = null; String buttonValue = null; String paramProperty = mapping.getParameter(); if((paramProperty != null)) { methodName = paramProperty.substring(0,paramProperty.indexOf('.')); } else { Enumeration enum = request.getParameterNames(); while(enum.hasMoreElements()) { buttonValue = (String)enum.nextElement(); if(buttonValue.indexOf(".dispatch") >= 0) { methodName = buttonValue; break; } } } return methodName.substring(0,methodName.indexOf('.')); } protected Method getMethod(String name) throws NoSuchMethodException { synchronized(methods) { Method method = (Method) methods.get(name); if (method == null) { method = clazz.getMethod(name, types); methods.put(name, method); } return (method); } } protected ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String message = messages.getMessage( "dispatch.parameter", mapping.getPath(), getMethodName(request,mapping)); throw new ServletException(message); } protected ActionForward cancelled(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return null; } } Essentially, all you do is iterate through the parameters until you get to one that ends with ".dispatch". Easy, right. This is the real solution to all the complexities of LookupDispatchAction. Note that you allow a Struts mapping "parameter" to override. This is a bit of sophistication you can dump. I like it though. On 4/7/06, Quinn Stone <[EMAIL PROTECTED]> wrote: > > OK. I contemplated creating a base class, but didn't like the idea of > having to > create a basically empty Action class for Actions that use ActionForward > to > forward to a jsp for display without calling an Action. And, frankly, > thought it > would be more complex to go learn the order of method calls of > LookupDispatchAction to figure out what to override and when and how I > return > without bypassing some necessary processing. Sometimes I like the easy way > out > (as long as it's not crappy). > > Q > > -----Original Message----- > From: Frank W. Zammetti [mailto:[EMAIL PROTECTED] > Sent: Friday, April 07, 2006 8:24 PM > To: Struts Users Mailing List > Subject: Re: Servlet Filter? > > > Hi Quinn, > > Quinn Stone wrote: > > 1. Does the Servlet filter seem a good solution? > > Yes, but not quite as described, and ironically its because of the > answer to #2 :) > > > 2. If I throw an EnrollmentDingBat exception from said Servlet Filter, > will a > > handler defined in <global-exceptions> catch it? My suspicion is that > the > filter > > might executing too early, before struts mechanics cut in. > > No, it won't. As you suspect, the filter fires before Struts gets > involved. > > However, what you *can* do, is simply forward somewhere from the filter. > It could be straight to a JSP, or it could be to an Action mapping, > whatever is appropriate. > > I think using a filter is generally a decent idea, but one thing to > consider: what are you going to map it to? It sounds like you have many > possible URLs that you would need to check, hence the reason for wanting > some "central" checkpoint in the first place. The problem is, the > filter is of course going to fire for *any* mapped request > indiscriminately. While filters, unless poorly written, tend to not add > a horrible amount of overhead, you may not want to add any at all where > it isn't necessary. So, onto #3... > > > No, three questions: > > > > 3. Any better ideas? > > I would probably do it instead with a custom Action base class that your > other Actions extend from. Then, only extend from it those Actions > where this check is needed. I mean, if you determine its needed for all > of them, or nearly all of them, then I'd probably go with the filter. > If you can narrow it down to just a handful though, the custom base > Action might be a better answer. > > > Q > > HTH, > Frank > > -- > Frank W. Zammetti > Founder and Chief Software Architect > Omnytex Technologies > http://www.omnytex.com > AIM: fzammetti > Yahoo: fzammetti > MSN: [EMAIL PROTECTED] > Java Web Parts - > http://javawebparts.sourceforge.net > Supplying the wheel, so you don't have to reinvent it! > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > -- "You can lead a horse to water but you cannot make it float on its back." ~Dakota Jack~