[ 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