In Tapestry 3 and 4 it was possible to throw a special kind of exception to redirect to another page. Howard has not implemented this in Tapestry 5 (as of T5.0.5) possibly because of criticism from many people who think (or perhaps read in a book ; - ) that it is misusing exceptions. Anyway, for the pragmatic ...

Comment from 9902468:

I personally use this as security measure: If user doesn't have enough rights the exception is great way to be sure that no other code is executed. If the exception carries information where this user should be redirected that's not going to harm anyone, right? =D

Here are some examples of how to use the exception in a page or component:

    throw new RedirectException(SomePage.class);

    // or

    throw new RedirectException("SomePage");

    // or

    @Inject
    ComponentResources resources; // use this to create a Link
    Link link = resources.createPageLink( // etc

    throw new RedirectException(link);

Here is the exception class. Put this in a utility package somewhere:

package yourApp.utilities;

import org.apache.tapestry.Link;

public class RedirectException extends RuntimeException
{
    private static final long serialVersionUID = -2927007059196754228L;

    protected Link pageLink;
    protected Class<?> pageClass;

    public RedirectException(String pageName)
    {
        super(pageName);
    }

    public RedirectException(Class<?> pageClass)
    {
        this.pageClass = pageClass;
    }

    public RedirectException(Link link)
    {
        this.pageLink = link;
    }

    public Link getPageLink()
    {
        return pageLink;
    }

    public Class<?> getPageClass()
    {
        return pageClass;
    }
}

Add this method to your AppModule.java:

    // handle RedirectException
    public static RequestExceptionHandler decorateRequestExceptionHandler(
        final Object delegate, final Response response,
        final RequestPageCache requestPageCache, final LinkFactory linkFactory,
        final ComponentClassResolver resolver)
    {
        return new RequestExceptionHandler()
        {
            public void handleRequestException(Throwable exception) throws IOException
            {
                // check if wrapped
                /*
                Throwable cause = exception;
                if (exception.getCause() instanceof RedirectException)
                {
                    cause = exception.getCause();
                }
                */

                //Better way to check if the cause is RedirectException. Sometimes it's wrapped pretty deep..
                int i = 0;
                while(true){
                    if(cause == null || cause instanceof RedirectException || i > 1000){
                        break;
                    }
                    i++;
                    cause = cause.getCause();
                }

                // check for redirect
                if (cause instanceof RedirectException)
                {
                    // check for class and string
                    RedirectException redirect = (RedirectException)cause;
                    Link pageLink = redirect.getPageLink();
                    if (pageLink == null)
                    {
                        // handle Class (see ClassResultProcessor)
                        String pageName = redirect.getMessage();
                        Class<?> pageClass = redirect.getPageClass();
                        if (pageClass != null)
                        {
                            pageName = resolver.resolvePageClassNameToPageName(pageClass.getName());
                        }

                        // handle String (see StringResultProcessor)
                        Page page = requestPageCache.get(pageName);
                        pageLink = linkFactory.createPageLink(page, false);
                    }

                    // handle Link redirect
                    if (pageLink != null)
                    {
                        response.sendRedirect(pageLink.toRedirectURI());
                        return;
                    }
                }

                // no redirect so pass on the exception
                ((RequestExceptionHandler)delegate).handleRequestException(exception);
            }
        };
    }

  • No labels