You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Fabien Le Floc'h <lo...@gmail.com> on 2007/07/13 11:01:52 UTC

T5 - How to do custom URL mapping?

Hi All,
I am new to Tapestry and would like to have a particular mapping for some
pages. For example, I would like that a call to
/user/MyUserName/viewSomething/withThisParameter maps to a page called
ViewSomething, where a user field would be initialized with MyUserName.

Now I can easily achieve similar goal using the url
/viewSomething/MyUserName/withThisParameter by using onActivate(x,y). But
the url does not have the same meaning and is less logical. As a concrete
example, try /tag/billgates/microsoft, it is not obvious what this is, but
/user/billgates/tag/microsoft is easy to guess.

So I would like to do a filter that intercepts the request and if it starts
with /user, get the page let's say in userpages packages instead of pages
package, and then pass the parameter after user/ and before /pageName to it.
It is quite simple to do using regular ServletFilter, how do i do that with
Tapestry Pages?

Regards,

Fabien.

PS: note that I don't expect this to be automatically done by T5, but I hope
there would be a simple programmatic way to do that.

Re: T5 - How to do custom URL mapping?

Posted by Fabien Le Floc'h <lo...@gmail.com>.
Thank you for your explanations,

I am not sure to understand correctly, when you speak about the path of
least resistance about page activation/passivation, you speak of it as an
alternate simpler solution than the dispatcher based solution?

If yes, I don't see how simpler it is. The way I understand it is you have a
User page with onActivate that renders another target page, the name of the
page being the 2nd parameter in the onActivate method. The logic I saw on
how to render a page by its name is in PageRenderDispatcher, so I would need
to mostly duplicate that logic. If I redirect to another page using a
string, then I suppose the real page link is the one for the redirected
page, and i still have the problem of having the right links.

If no, I don't see how it can be used in combination with the Dispatcher, as
onActivate/onPassivate only allows you to modify what's after the page name
in the url. If /user/howard/account/ is calling
/userpages/account/user/howard (Account page for user howard) then you can
not tell Account to change the /userpages prefix with
onActivate/onPassivate.

Best regards,

Fabien.



On 7/13/07, Howard Lewis Ship <hl...@gmail.com> wrote:
>
> Part of the solution here is a custom Dispatcher, contributed to the
> MasterDispatcher service configuration.
>
> A Dispatcher is provided with the Request and Response, and can decide
> how and if to response, much like a servlet.
>
> The different Dispatchers form a chain-of-command.  You can "schedule"
> your Dispatcher ahead of the default Dispatchers to ensure no
> conflicts.
>
> The hard(er) part is to generate proper links to your pages with this
> extra data.
>
> The path of least resistance is to use the page activation /
> passivation events built into Tapestry, which give a reasonable, if
> not fully custom, URL.
>
>
> On 7/13/07, Fabien Le Floc'h <lo...@gmail.com> wrote:
> > Hi All,
> > I am new to Tapestry and would like to have a particular mapping for
> some
> > pages. For example, I would like that a call to
> > /user/MyUserName/viewSomething/withThisParameter maps to a page called
> > ViewSomething, where a user field would be initialized with MyUserName.
> >
> > Now I can easily achieve similar goal using the url
> > /viewSomething/MyUserName/withThisParameter by using onActivate(x,y).
> But
> > the url does not have the same meaning and is less logical. As a
> concrete
> > example, try /tag/billgates/microsoft, it is not obvious what this is,
> but
> > /user/billgates/tag/microsoft is easy to guess.
> >
> > So I would like to do a filter that intercepts the request and if it
> starts
> > with /user, get the page let's say in userpages packages instead of
> pages
> > package, and then pass the parameter after user/ and before /pageName to
> it.
> > It is quite simple to do using regular ServletFilter, how do i do that
> with
> > Tapestry Pages?
> >
> > Regards,
> >
> > Fabien.
> >
> > PS: note that I don't expect this to be automatically done by T5, but I
> hope
> > there would be a simple programmatic way to do that.
> >
>
>
> --
> Howard M. Lewis Ship
> TWD Consulting, Inc.
> Independent J2EE / Open-Source Java Consultant
> Creator and PMC Chair, Apache Tapestry
> Creator, Apache HiveMind
>
> Professional Tapestry training, mentoring, support
> and project work.  http://howardlewisship.com
>

Re: T5 - How to do custom URL mapping?

Posted by Howard Lewis Ship <hl...@gmail.com>.
Part of the solution here is a custom Dispatcher, contributed to the
MasterDispatcher service configuration.

A Dispatcher is provided with the Request and Response, and can decide
how and if to response, much like a servlet.

The different Dispatchers form a chain-of-command.  You can "schedule"
your Dispatcher ahead of the default Dispatchers to ensure no
conflicts.

The hard(er) part is to generate proper links to your pages with this
extra data.

The path of least resistance is to use the page activation /
passivation events built into Tapestry, which give a reasonable, if
not fully custom, URL.


On 7/13/07, Fabien Le Floc'h <lo...@gmail.com> wrote:
> Hi All,
> I am new to Tapestry and would like to have a particular mapping for some
> pages. For example, I would like that a call to
> /user/MyUserName/viewSomething/withThisParameter maps to a page called
> ViewSomething, where a user field would be initialized with MyUserName.
>
> Now I can easily achieve similar goal using the url
> /viewSomething/MyUserName/withThisParameter by using onActivate(x,y). But
> the url does not have the same meaning and is less logical. As a concrete
> example, try /tag/billgates/microsoft, it is not obvious what this is, but
> /user/billgates/tag/microsoft is easy to guess.
>
> So I would like to do a filter that intercepts the request and if it starts
> with /user, get the page let's say in userpages packages instead of pages
> package, and then pass the parameter after user/ and before /pageName to it.
> It is quite simple to do using regular ServletFilter, how do i do that with
> Tapestry Pages?
>
> Regards,
>
> Fabien.
>
> PS: note that I don't expect this to be automatically done by T5, but I hope
> there would be a simple programmatic way to do that.
>


-- 
Howard M. Lewis Ship
TWD Consulting, Inc.
Independent J2EE / Open-Source Java Consultant
Creator and PMC Chair, Apache Tapestry
Creator, Apache HiveMind

Professional Tapestry training, mentoring, support
and project work.  http://howardlewisship.com

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


Re: T5 - How to do custom URL mapping?

Posted by Fabien Le Floc'h <lo...@gmail.com>.
I found a way to do it by implementing a PageRenderRequestFilter. However
this is a bit tricky, since it requires a "User" page defined for it to work
(even if it is not used by the app), because this filter is only called if
_componentClassResolver.isPageName(pageName) is successful (cf
PageRenderDispatcher source code).

For my use, it would be best for PageRenderDispatcher to be independent from
ComponentClassResolver, and PageRenderRequestHandler dependent on it. To me
it makes more sense if PageRenderRequestHandler (and Filter) class knows if
it can handle a given logicalPageName or not, rather than directly use the
ComponentClassResolver in the dispatcher.

What do you think?

Fabien.

PS: My current solution is the following

    public PageRenderRequestFilter
buildNewsbeefPageRenderRequestFilter(final Log log) {
    return new PageRenderRequestFilter() {

        public ActionResponseGenerator handle(String logicalPageName,
String[] context,
            PageRenderRequestHandler handler) {
        if (log.isDebugEnabled()) {
            log.debug("pagerenderrequestfilter, logicalPageName=" +
logicalPageName
                + ",context="+Arrays.toString(context));
        }
        if (logicalPageName.equalsIgnoreCase("user") && context.length >= 2)
{
            //this is a user specific page
            // /user/userId/page/ddddd/nnnn becomes
/userpages/Page/dddd/nnnn/user/userId
            if (context[1].length() > 0) {
            String newPageName = Character.toUpperCase(context[1].charAt(0))
                + context[1].substring(1);
            newPageName = "userpages/" + newPageName;
            String[] newContext = new String[context.length];
            for (int i=2; i<context.length;i++) {
                newContext[i-2] = context[i];
            }
            newContext[context.length-2] = logicalPageName;
            newContext[context.length-1] = context[0];
            return handler.handle(newPageName, newContext);
            }
        }
        return handler.handle(logicalPageName, context);
        }
    };
    }

On 7/13/07, Fabien Le Floc'h <lo...@gmail.com> wrote:
>
> Hi All,
> I am new to Tapestry and would like to have a particular mapping for some
> pages. For example, I would like that a call to
> /user/MyUserName/viewSomething/withThisParameter maps to a page called
> ViewSomething, where a user field would be initialized with MyUserName.
>
> Now I can easily achieve similar goal using the url
> /viewSomething/MyUserName/withThisParameter by using onActivate(x,y). But
> the url does not have the same meaning and is less logical. As a concrete
> example, try /tag/billgates/microsoft, it is not obvious what this is, but
> /user/billgates/tag/microsoft is easy to guess.
>
> So I would like to do a filter that intercepts the request and if it
> starts with /user, get the page let's say in userpages packages instead of
> pages package, and then pass the parameter after user/ and before /pageName
> to it. It is quite simple to do using regular ServletFilter, how do i do
> that with Tapestry Pages?
>
> Regards,
>
> Fabien.
>
> PS: note that I don't expect this to be automatically done by T5, but I
> hope there would be a simple programmatic way to do that.
>