cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel Fagerstrom <dani...@nada.kth.se>
Subject Re: [RT] Escaping Sitemap Hell
Date Thu, 06 Jan 2005 17:12:39 GMT
Ugo Cei wrote:

> Il giorno 06/gen/05, alle 01:54, Daniel Fagerstrom ha scritto:
>
>>
>> The requested resource will often be based on some content or 
>> combination of content that we can access from Cocoon. The content 
>> can be a file, data in a db, result from a business object etc. Let 
>> us assume that it resides in some kind of content repository. Now if 
>> we think about it, isn't it more natural to ask the content, that we 
>> are going to use, about its propertiies like type, format, status, 
>> access rights, etc, than to encode it in the URL? This properties can 
>> be encoded in the file name, in metadata in some property file, 
>> within the file, in a DB etc. Now instead of having the rule:
>>
>> *.x.y.z ==> XYZPipeline
>>
>> we have
>>
>> * where repository:{1} have properites {x, y, z} ==> XYZPipeline
>>
>> or
>>
>> * where repository:{1}.x.y.z exists ==> XYZPipeline
>>
>> We get the right pipeline by querying the repository instead of 
>> encoding it in the URL. A further advantage is that the rule becomes 
>> "listable" as the "where" clause in the match expresses what are the 
>> allowed values for the wildcard.
>
>
> Unless I misinterpret what you mean, we already can do this:
>
> <map:match pattern="*">
>   <map:call function="fun">
>     <map:parameter name="par" value="{1}"/>
>   </map:call>
> </map:match>
>
> function fun() {
>   var entity = repo.query("select * from entities where id = " + 
> cocoon.parameters.par + " and {x, y, z}");
>   cocoon.sendPage("views/XYZPipeline", { entity : entity });
> }
>
> <map:match pattern="XYZPipeline">
>   <map:generate type="jx" src="xyz.jx.xml"/>
>  ...
> </map:match> 

My example was a little bit unclear what I meant was that you could have 
a number of sitemap rules:

* where repository:{1} have properites {x, y, z} ==> XYZPipeline
* where repository:{1} have properites {a, b, c} ==> ABCPipeline
* where repository:{1} have properites {a, b, d} ==> ABDPipeline

Which rather would correspond to:

<map:match pattern="*" where="repository:{1} have properites {x, y, z}" 
type="property">
   <!-- call XYZPipeline -->
</map:match>
<map:match pattern="*" where="repository:{1} have properites {a, b, c}" 
type="property">
   <!-- call ABCPipeline -->
</map:match>
etc

That would be rather inneficient in the current sequencial search based 
sitemap, while it could be efficient in a tree based matcher.

> Apart from the obviously contrived example, isn't the Flowscript just 
> what we need to "get the right pipeline by querying the repository"? 

You could implement that above example by putting the property based 
switch in a flowscript instead, thats true. My own experience with using 
a flowscript as switchboard, have made me believe that it is an anti 
patern that should be avoided. But maybe other people have been luckier.

One of my aims with the RT was to make the sitemap more usable as a map 
over the site, by making it tree structured and more declarative. From 
that view using flowscripts instead of sitemaps is a step in the wrong 
direction IMO.

>> I would propose to go even further, in the "real" site map it should 
>> only be allowed to call VPC pipelines, no pipeline construction is 
>> allowed, that should be done in the component area.
>
>
> In my sitemaps, public pipelines contain almost only <map:call> and 
> <map:read> (for static resources) elements. All "classical" 
> generator-transformer-serializer pipelines go into an "internal-only" 
> pipeline that can be called from flowscripts only.
>
> Admittedly, this is fine for webapps, and maybe not so much for 
> publishing-oriented websites. But what I want to point out is that 
> your otherwise very well thought-out RT is incomplete if it doesn't 
> take Flowscript in consideration, IMHO.

I hoped that no one would notice, and that we could discuss the publish 
oriented stuff before handling such complications ;)

But you are completely right, flowscripts must also be discussed. This 
breaks down in two parts: how do we design a cool URL space for a 
flowscript driven webapp, and how do we implement such a URL space in 
Cocoon. Does what we have give good support or do we need new mechanisms?

I'll try to say something about cool URLs for flowscripts and leave the 
second part to another time or as a rather non trivial exercise for the 
interested reader ;)

Cool URLs for webapps
=====================

Ok, I continue to uncritically assume that the guidelines in 
http://www.w3.org/TR/2003/NOTE-chips-20030128/ are good and try to apply 
them on the current situation. Given that, I don't consider:

  12345.cont

particulary cool. No way back at all after your web-continuations have 
expired. Sometimes that might be the most reasonable response that is 
available. But we could do better than always using it.

When planning the URL space for the webapp, all allowed access points to 
the webapp must be given a "cool" URL. Let us say that we have a wizard 
and that users only are allowed to access it from the first screen when 
they don't have a valid session. in this case we could have:

  wizard

as URL to the start point and

  wizard?cont=12345

as URL to a screen within the session. If that URL is bookmarked and 
used after the expiration of the continuation, the user will get a 
permanent redirect to the "wizard" URL as response, possibly with an 
"session expired" message in the respons page.

If we follow this idea, we can think of our webapps in a transaction 
oriented way. Each time we have "commited a transaction" in our 
flowscript we could give a "cool" URL for the next screen in the flow 
(if it is allowable as a starting point). Now, this is a little bit 
tricky as the user probably made a post to something like:

  wizard?cont=23456

where the transaction was committed, and that the flow could continue to 
"wizard2" or "wizard3" depending on user choice. This could maybe be 
solved by doing a redirect to the new wizard.

If we are creating a persistent object in the wizard we can take it 
further if we want to. Then we start the wizard the object is given an id:

  123456/wizard

then we can go back to a wizard initialized from the object later. If we 
want to use some other identification after the object is commited, we 
have to save a mapping from the initial id to the correct one and do a 
permanent redirect when the URL is accesed. If we don' like going to a 
wizard we do a permanent direct to something more relevant. We could 
even let the user go back to specific pages for persistent objects:

  123456/wizard/3

for such cases there are not much use in having a continuation id at all 
in the URL except if we want to let the user having multiple instances 
of the same page with different content.

If we follow the URL style without continuation IDs we use the session 
for differing between users instead.

                                 --- o0o ---

How much work you should spend in creating "cool" URLs in your webapp, 
varies of course from application to application. I just wanted to point 
out that we can do more than 123456.cont if we want to. I have used more 
than one webapp that goes through many "transactions" during use, but 
force me to start the navigation from some start screen if my session 
expires. At least I would found such applications more userfriendly if 
they had used "cooler" URIs.

If you think that reusable URLs is a good idea, not only in publishing 
oriented sites but in webapps as well, you will need to have more 
external URLs and your webapp will get more in common with publishing 
oriented sites.

/Daniel



Mime
View raw message