Just another idea I had. Let me know if you foresee any problems with it...

If you have your web application set up so T5 renders your 404 pages,
more than likely you've noticed the relative URI links on your error
page are incorrect.

Say you have these pages /page1, /error404 and /viewMember and a menu
displayed on every page with a <t:pagelink page="page1">.

Then when you navigate to "/viewMember/dontExist" the web app forwards
you to /error404 which T5 happily renders. Only the menu renders a
relative link to <a href="page1"> (and not <a href="../page1">) which
your browser, after requesting /viewMember/dontExist, interprets as <a
href="/viewMember/page1">. Which leads to another 404...

Whilst the idea of this 404 vicious circle amuses me, it's not
particularly helpful!

You could add a HTML base tag to your error pages but that requires
you to know the deployed host URL in advance and it's just extra
configuration to deal with.

Instead, consider this; an annotation to add to your page class which
renders all links on the page as absolute URIs. So simply add
@RenderAbsoluteURIs to your /error404 page and job done! Here's the
code:

First the annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface RenderAbsoluteURIs { }

Then an advice to the RequestPathOptimizer so we may optionally bypass it:

import java.lang.annotation.Annotation;
import org.apache.tapestry5.ioc.Invocation;
import org.apache.tapestry5.ioc.MethodAdvice;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.ComponentClassResolver;
import org.apache.tapestry5.services.ComponentEventLinkEncoder;
import org.apache.tapestry5.services.Request;


public class OptimizePathAdvice implements MethodAdvice {

        @Inject
        private Request request;

        @Inject
        private ComponentEventLinkEncoder linkEncoder;

        @Inject
        private ComponentClassResolver classResolver;

        public void advise(Invocation invocation) {
                boolean renderAbsolute = 
pageHasAnnotion(RenderAbsoluteURIs.class);

                if (renderAbsolute) {
                        String absolutePath = (String) 
invocation.getParameter(0);
                        invocation.overrideResult(absolutePath);
                } else
                        invocation.proceed();
    }

        private <A extends Annotation> boolean pageHasAnnotion(Class<A> 
annotation) {
                String pageName;
                try {
                        pageName = 
linkEncoder.decodePageRenderRequest(request).getLogicalPageName();
                } catch(IllegalArgumentException e) {
                        // ignore those stoopid invalid path errors
                        return false;
                }

                String className = 
classResolver.resolvePageNameToClassName(pageName);

                Class<?> pageClass;
                try {
                        pageClass = Class.forName(className);
        } catch (ClassNotFoundException e) {
                return false;
        }

                return pageClass.isAnnotationPresent(annotation);
        }
}

and finally the Module configuration to add the advice:

@Match("RequestPathOptimizer")
public static void adviseRequestPathOptimizer(MethodAdviceReceiver
receiver, OptimizePathAdvice optimizePathAdvice) throws
SecurityException, NoSuchMethodException {
        Method method = RequestPathOptimizer.class.getMethod("optimizePath",
String.class);
        receiver.adviseMethod(method, optimizePathAdvice);
}

Have fun,

Steve.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org

Reply via email to