[ http://mc4j.org/jira/browse/STS-268?page=all ]

Tim Fennell updated STS-268:
----------------------------

    Fix Version/s: Release 1.5

> Cleaner URLs
> ------------
>
>                 Key: STS-268
>                 URL: http://mc4j.org/jira/browse/STS-268
>             Project: Stripes
>          Issue Type: New Feature
>          Components: ActionBean Dispatching
>    Affects Versions: Release 1.4
>            Reporter: Patrick Lightbody
>         Assigned To: Tim Fennell
>             Fix For: Release 1.5
>
>
> To implement "cleaner URLs", I had to set up both a filter and a servlet in 
> web.xml. I also had to create a custom ActionNameResolver.
> web.xml:
> ---------------
>     <filter>
>         <filter-name>StripesActionFilter</filter-name>
>         
> <filter-class>com.cparty.stripes.util.CPartyActionBeanFilter</filter-class>
>     </filter>
>     <filter-mapping>
>         <filter-name>StripesActionFilter</filter-name>
>         <url-pattern>/*</url-pattern>
>         <dispatcher>REQUEST</dispatcher>
>     </filter-mapping>
>     <servlet>
>         <servlet-name>ServletHelper</servlet-name>
>         
> <servlet-class>com.cparty.stripes.util.CPartyServletHelper</servlet-class>
>         <load-on-startup>1</load-on-startup>
>     </servlet>
> ---------------
> Servlet:
> ---------------
> package com.cparty.stripes.util;
> import javax.servlet.http.HttpServlet;
> import javax.servlet.ServletConfig;
> import javax.servlet.ServletException;
> public class CPartyServletHelper extends HttpServlet {
>     public static CPartyServletHelper servlet;
>     public void init(ServletConfig servletConfig) throws ServletException {
>         super.init(servletConfig);
>         CPartyServletHelper.servlet = this;
>     }
> }
> ---------------
> Filter:
> ---------------
> package com.cparty.stripes.util;
> import net.sourceforge.stripes.action.ActionBeanContext;
> import net.sourceforge.stripes.action.Resolution;
> import net.sourceforge.stripes.config.Configuration;
> import net.sourceforge.stripes.controller.*;
> import net.sourceforge.stripes.exception.StripesServletException;
> import net.sourceforge.stripes.validation.BooleanTypeConverter;
> import javax.servlet.*;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
> import javax.servlet.jsp.JspFactory;
> import javax.servlet.jsp.PageContext;
> import java.io.IOException;
> import java.lang.reflect.InvocationTargetException;
> import java.util.Stack;
> public class CPartyActionBeanFilter implements Filter {
>     public static final String RUN_CUSTOM_VALIDATION_WHEN_ERRORS =
>             "Validation.InvokeValidateWhenErrorsExist";
>     private Boolean alwaysInvokeValidate;
>     private FilterConfig filterConfig;
>     public void init(final FilterConfig filterConfig) throws ServletException 
> {
>         this.filterConfig = filterConfig;
>     }
>     public void doFilter(ServletRequest servletRequest, ServletResponse 
> servletResponse, FilterChain filterChain) throws IOException, 
> ServletException {
>         // It sucks that we have to do this here (in the request cycle), but 
> there doesn't
>         // seem to be a good way to get at the Configuration from the Filter 
> in init()
>         doOneTimeConfiguration();
>         HttpServletRequest request = (HttpServletRequest) servletRequest;
>         HttpServletResponse response = (HttpServletResponse) servletResponse;
>         if ("/".equals(request.getServletPath())) {
>             filterChain.doFilter(request, response);
>             return;
>         }
>         Configuration config = StripesFilter.getConfiguration();
>         ActionBeanContext context = 
> config.getActionBeanContextFactory().getContextInstance(request, response);
>         try {
>             // we look up the bean name to see if we should pass the request 
> through or not
>             
> StripesFilter.getConfiguration().getActionResolver().getActionBean(context);
>         } catch (StripesServletException e) {
>             filterChain.doFilter(servletRequest, servletResponse);
>             return;
>         }
>         
> ///////////////////////////////////////////////////////////////////////
>         // Here beings the reall processing of the request!
>         
> ///////////////////////////////////////////////////////////////////////
>         PageContext pageContext = null;
>         try {
>             context.setServletContext(filterConfig.getServletContext());
>             // Then setup the ExecutionContext that we'll use to process this 
> request
>             final ExecutionContext ctx = new ExecutionContext();
>             
> ctx.setInterceptors(config.getInterceptors(LifecycleStage.ActionBeanResolution));
>             ctx.setLifecycleStage(LifecycleStage.ActionBeanResolution);
>             ctx.setActionBeanContext(context);
>             // It's unclear whether this usage of the JspFactory will work in 
> all containers. It looks
>             // like it should, but still, we should be careful not to screw 
> up regular request
>             // processing if it should fail. Why do we do this?  So we can 
> have a container-agnostic
>             // way of getting an ExpressionEvaluator to do expression based 
> validation
>             try {
>                 ActionBeanContext abc = ctx.getActionBeanContext();
>                 pageContext = 
> JspFactory.getDefaultFactory().getPageContext(CPartyServletHelper.servlet, // 
> the servlet inst
>                         abc.getRequest(), // req
>                         abc.getResponse(), // res
>                         null,   // error page url
>                         true,   // need session
>                         abc.getResponse().getBufferSize(),
>                         true); // autoflush
>                 DispatcherHelper.setPageContext(pageContext);
>             }
>             catch (Exception e) {
>                 // Don't even log this, this failure gets reported if action 
> beans actually
>                 // try and make use of expression validation, otherwise this 
> is just noise
>             }
>             // Resolve the ActionBean, and if an interceptor returns a 
> resolution, bail now
>             Resolution resolution = resolveActionBean(ctx);
>             saveActionBean(request);
>             if (resolution == null) {
>                 resolution = resolveHandler(ctx);
>                 if (resolution == null) {
>                     // Then run binding and validation
>                     resolution = doBindingAndValidation(ctx);
>                     if (resolution == null) {
>                         // Then continue on to custom validation
>                         resolution = doCustomValidation(ctx);
>                         if (resolution == null) {
>                             // And then validation error handling
>                             resolution = handleValidationErrors(ctx);
>                             if (resolution == null) {
>                                 // And finally(ish) invoking of the event 
> handler
>                                 resolution = invokeEventHandler(ctx);
>                                 // If the event produced errors, fill them in
>                                 DispatcherHelper.fillInValidationErrors(ctx);
>                             }
>                         }
>                     }
>                 }
>             }
>             // Whatever stage it came from, execute the resolution
>             if (resolution != null) {
>                 executeResolution(ctx, resolution);
>             }
>         }
>         catch (ServletException se) {
>             throw se;
>         }
>         catch (RuntimeException re) {
>             throw re;
>         }
>         catch (InvocationTargetException ite) {
>             if (ite.getTargetException() instanceof ServletException) {
>                 throw (ServletException) ite.getTargetException();
>             } else if (ite.getTargetException() instanceof RuntimeException) {
>                 throw (RuntimeException) ite.getTargetException();
>             } else {
>                 throw new StripesServletException
>                         ("ActionBean execution threw an exception.", 
> ite.getTargetException());
>             }
>         }
>         catch (Exception e) {
>             throw new StripesServletException("Exception encountered 
> processing request.", e);
>         }
>         finally {
>             // Make sure to release the page context
>             if (pageContext != null) {
>                 
> JspFactory.getDefaultFactory().releasePageContext(pageContext);
>                 DispatcherHelper.setPageContext(null);
>             }
>             restoreActionBean(request);
>         }
>     }
>     public void destroy() {
>     }
>     /**
>      * Responsible for resolving the ActionBean for the current request. 
> Delegates to
>      * [EMAIL PROTECTED] 
> DispatcherHelper#resolveActionBean(ExecutionContext)}.
>      */
>     protected Resolution resolveActionBean(ExecutionContext ctx) throws 
> Exception {
>         return DispatcherHelper.resolveActionBean(ctx);
>     }
>     /**
>      * Responsible for resolving the event handler method for the current 
> request. Delegates to
>      * [EMAIL PROTECTED] DispatcherHelper#resolveHandler(ExecutionContext)}.
>      */
>     protected Resolution resolveHandler(ExecutionContext ctx) throws 
> Exception {
>         return DispatcherHelper.resolveHandler(ctx);
>     }
>     /**
>      * Responsible for executing binding and validation for the current 
> request. Delegates to
>      * [EMAIL PROTECTED] 
> DispatcherHelper#doBindingAndValidation(ExecutionContext, boolean)}.
>      */
>     protected Resolution doBindingAndValidation(ExecutionContext ctx) throws 
> Exception {
>         return DispatcherHelper.doBindingAndValidation(ctx, true);
>     }
>     /**
>      * Responsible for executing custom validation methods for the current 
> request. Delegates to
>      * [EMAIL PROTECTED] 
> DispatcherHelper#doCustomValidation(ExecutionContext, boolean)}.
>      */
>     protected Resolution doCustomValidation(ExecutionContext ctx) throws 
> Exception {
>         return DispatcherHelper.doCustomValidation(ctx, alwaysInvokeValidate);
>     }
>     /**
>      * Responsible for handling any validation errors that arise during 
> validation. Delegates to
>      * [EMAIL PROTECTED] 
> DispatcherHelper#handleValidationErrors(ExecutionContext)}.
>      */
>     protected Resolution handleValidationErrors(ExecutionContext ctx) throws 
> Exception {
>         return DispatcherHelper.handleValidationErrors(ctx);
>     }
>     /**
>      * Responsible for invoking the event handler if no validation errors 
> occur. Delegates to
>      * [EMAIL PROTECTED] 
> DispatcherHelper#invokeEventHandler(ExecutionContext)}.
>      */
>     protected Resolution invokeEventHandler(ExecutionContext ctx) throws 
> Exception {
>         return DispatcherHelper.invokeEventHandler(ctx);
>     }
>     /**
>      * Responsible for executing the Resolution for the current request. 
> Delegates to
>      * [EMAIL PROTECTED] DispatcherHelper#executeResolution(ExecutionContext, 
> Resolution)}.
>      */
>     protected void executeResolution(ExecutionContext ctx, Resolution 
> resolution) throws Exception {
>         DispatcherHelper.executeResolution(ctx, resolution);
>     }
>     /**
>      * Performs a simple piece of one time configuration that requires access 
> to the
>      * Configuration object delivered through the Stripes Filter.
>      */
>     private void doOneTimeConfiguration() {
>         if (alwaysInvokeValidate == null) {
>             // Check to see if, in this application, validate() methods 
> should always be run
>             // even when validation errors already exist
>             String callValidateWhenErrorsExist = 
> StripesFilter.getConfiguration()
>                 
> .getBootstrapPropertyResolver().getProperty(RUN_CUSTOM_VALIDATION_WHEN_ERRORS);
>             if (callValidateWhenErrorsExist != null) {
>                 BooleanTypeConverter c = new BooleanTypeConverter();
>                 this.alwaysInvokeValidate = 
> c.convert(callValidateWhenErrorsExist, Boolean.class, null);
>             }
>             else {
>                 this.alwaysInvokeValidate = false; // Default behaviour
>             }
>         }
>     }
>     /**
>      * Fetches, and lazily creates if required, a Stack in the request to 
> store ActionBeans
>      * should the current request involve forwards or includes to other 
> ActionBeans.
>      *
>      * @param request the current HttpServletRequest
>      * @return the Stack if present, or if creation is requested
>      */
>     protected Stack getActionBeanStack(HttpServletRequest request, boolean 
> create) {
>         Stack stack = (Stack) 
> request.getAttribute(StripesConstants.REQ_ATTR_ACTION_BEAN_STACK);
>         if (stack == null && create) {
>             stack = new Stack();
>             request.setAttribute(StripesConstants.REQ_ATTR_ACTION_BEAN_STACK, 
> stack);
>         }
>         return stack;
>     }
>     /**
>      * Saves the current value of the 'actionBean' attribute in the request 
> so that it
>      * can be restored at a later date by calling [EMAIL PROTECTED] 
> #restoreActionBean(HttpServletRequest)}.
>      * If no ActionBean is currently stored in the request, nothing is 
> changed.
>      *
>      * @param request the current HttpServletRequest
>      */
>     protected void saveActionBean(HttpServletRequest request) {
>         if (request.getAttribute(StripesConstants.REQ_ATTR_ACTION_BEAN) != 
> null) {
>             Stack stack = getActionBeanStack(request, true);
>             
> stack.push(request.getAttribute(StripesConstants.REQ_ATTR_ACTION_BEAN));
>         }
>     }
>     /**
>      * Restores the previous value of the 'actionBean' attribute in the 
> request. If no
>      * ActionBeans have been saved using [EMAIL PROTECTED] 
> #saveActionBean(HttpServletRequest)} then this
>      * method has no effect.
>      *
>      * @param request the current HttpServletRequest
>      */
>     protected void restoreActionBean(HttpServletRequest request) {
>         Stack stack = getActionBeanStack(request, false);
>         if (stack != null && !stack.empty()) {
>             request.setAttribute(StripesConstants.REQ_ATTR_ACTION_BEAN, 
> stack.pop());
>         }
>     }
> }
> ---------------
> ActionNameResolver:
> ---------------
> package com.cparty.stripes.util;
> import net.sourceforge.stripes.controller.NameBasedActionResolver;
> /**
>  * We prefer "home" rather than "Home.action", which this class takes care of.
>  */
> public class CPartyNameBasedActionResolver extends NameBasedActionResolver {
>     protected String getUrlBinding(String string) {
>         String original = super.getUrlBinding(string);
>         int end = original.indexOf(".action");
>         String temp = original.substring(0, end);
>         int begin = temp.lastIndexOf("/");
>         String name = original.substring(begin + 1, end);
>         name = name.substring(0, 1).toLowerCase() + name.substring(1);
>         return original.substring(0, begin + 1).toLowerCase() + name ;
>     }
> }
> ---------------

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://mc4j.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to