Understanding Cocoon Mount

The Root Sitemap

The default Cocoon web application reads the Sitemap (sitemap.xmap file) in the $COCOON_HOME directory for instructions about how to process incoming requests

This means that if the Cocoon web application is installed in

$TOMCAT_HOME/cocoon

Then all requests with the base URL of:

http://localhost:8080/cocoon/...

will be serviced by asking this sitemap for a suitable pipeline. The matchers defined in that sitemap can allow for arbitrary amounts of additional path information, but it is this initial root 'mount point' that determines basic request processing.

So for example a pipeline with:

<map:match pattern="my/long/url/path/*.html"/>

Will match:

http://localhost:8080/cocoon/my/long/url/path/doc.html

So while the Cocoon web application is mounted at /cocoon in the servlet container, the pipelines are mounted from /cocoon/

However placing all pipeline and component configurations in a single sitemap can be unwieldy, it's better to partition up the web application. This can be done by creating additional sitemaps which contain related functionality. E.g. all form processing relating to registration, searching, etc.

See also: Blocks, which are a planned development to extend sub-sitemaps with metadata and provide facilities to allow users to construct web apps from these "components". -- Con

Mounting Sub-Sitemaps

Partitioning a sitemap in this way involves use of the <map:mount/> element. This indicates that a second sitemap should be processed, and includes the location of that sitemap.

E.g.

<map:match pattern="my/long/url/path/*.html">
 <map:mount src="my/long/dir/structure/sitemap.xmap"/>
</map:match>

Will cause the sitemap in $CATALINA_HOME/cocoon/my/long/dir/structure/ to be queried for pipelines that can process this request. The second sitemap is referred to as a sub-sitemap. It inherits all component declarations from it's parent, so there is no need for them to be redeclared.

Note : in the compiled sitemap engine (used up to version 2.0.3), default components are not inherited, and you may want to declare empty container elements to specify these defaults (e.g. <map:generators default="file"/>"). This is not needed with the newer interpreted engine.

However, any Matchers in this sitemap would still have to use the full request path for their match to work as expected

I couldn't do:

<map:match pattern="*.html"/>

As this actually matches

http://localhost:8080/cocoon/*.html.

To enable additional unwanted path information to be ignored, we need to add an additional uri-prefix attribute to the <map:mount> element, as follows:

<map:match pattern="my/long/url/path/*.html">
 <map:mount src="my/long/dir/structure/sitemap.xmap"
                   uri-prefix="my/long/url/path/"/>
</map:match>

Which means that a matcher with the pattern *.html in $CATALINA_HOME/cocoon/my/long/dir/structure/sitemap.xmap will match:

http://localhost:8080/cocoon/my/long/url/path/doc.html

but not

http://localhost:8080/cocoon/*.html

The other additional parameter to the mount element is check-reload which can have the value yes or no. This indicates whether the mounted sitemap should be reloaded if it changes.

Location Independence

Note also that the sitemap location is completely separate to the path info in the URL. I can maintain my sitemap.xmap file anywhere on the file system that can be read by Cocoon. As is usual in Cocoon pipelines, it's the matching components that dictate how a request path is tied to a sequence of processing.

Partitioning Options

The above example have assumed that the Cocoon application has been partitioned into a collection of sub-sitemaps according to the request path.

However it's perfectly acceptable to partition an application based on any criteria. In fact any Selector or Matcher component can be used as the means to delegate processing to a sub-sitemap.

So, for example I could use the HostSelector to select an alternate sitemap based on the host name used in the request. Or I could use the BrowserSelector to separate processing based on user-agents. The ParameterMatcher could select sub-sitemaps based on request parameters, and so on.

Auto-Mounting

Extending this facility to its natural conclusion, we can use the power of the Wildcard Matcher component and the <map:mount/> element to create an auto-mount feature that will allow sitemaps underneath a given directory structure to be automatically loaded by Cocoon.

We can achieve this with the following:

<map:match pattern="auto/*/**">
   <map:mount uri-prefix="auto/{1}/" src="auto/{1}"/>
</map:match>

This uses wildcard, and sitemap parameters to automatically match a base request url, in this case:

http://localhost:8080/cocoon/auto/...

The first path element is matched and stored in {1}. This is then used as the name of the directory from which to load the sitemap. In this case a request for

http://localhost:8080/cocoon/auto/foo/bar.html

Will cause the sitemap in:

$CATALINA_HOME/cocoon/auto/foo

to be loaded and the prefix /auto/foo/ automatically stripped.

Auto-mounting can use the flexibility required earlier to auto-mount sitemaps based on request parameters, and a whole range of other options. However doing so using a correlated request-path and directory structure makes the functionality more intuitive.

Note that directories under /auto/ are recognized without having to restart Cocoon. The sitemap found in a newly created directory will be compiled when the first request for this directory is processed by Cocoon -- BertrandDelacretaz

Auto-Mounting and Users

Auto-mounting is a good way to allow multiple users to share a Cocoon instance. Their public_html directories can be symbolically linked to the 'auto' directory, and they can then operate independently of one another.

However all users sharing this instance will be sharing a classloader, they'll be sharing classes/libs -- this means that it's probably of most use in environments where people are building Cocoon applications from pre-developed components. E.g. configuring sitemaps, writing XSLT transforms, etc.

Some design ideas.

Auto-Mount may be a very powerful feature to design your cocoon server, and share resources between users/clients. Now, the problem is, what to let to the root sitemap, and what is the minimum to ask to sub-sitemaps.

Components

Inheritance of components have been a little problem between some versions of Cocoon, it's now solved. But after experience, it's not so bad to keep the components you need in each sitemap, especially to have your own names for generators or transformers, and be able to move your app under any other sitemap, or put it directly as root.

Static Resources

An interesting feature to ask to a root sitemap is service of static resources. Example :

{{{<map:match pattern="**.ai">

</map:match> <map:match pattern="**.aif">

</map:match> <!-- ... -->}}}

There are lot of mime/type, and they are very useful in case of downloading on some browsers. Not funny to copy/paste the list everywhere. First, put it as Resources. It will be easier to manipulate.

{{{<map:resources>

<!-- ... --> </map:resources>

<!-- call it like that where you want in a pipeline process --> <map:call resource="static"/>}}}

Now, where to put this call relatively to a mount?

If you put it like that {{{<map:call resource="static"/> <map:match pattern="*/**">

</map:match>}}} All urls like **.js, or **.css will be handled before sub-sitemap matches. Nice, no more need to declare them in each sub-sitemaps. But sadly, now your clients will not be allowed to use the virtual matching of cocoon on common file extensions (example: producing images on request with a **.png url). Bad solution

If you put it like that {{{<map:match pattern="*/**">

</map:match>}}} FixMe, but sub-sitemap seems to throw the "Resource not found" error, before the call in the root sitemap.

An idea was to copy the pipeline in all sub-sitemaps (heavy). FixMe, but it seems impossible to use resource from root sitemap in sub-sitemaps.

Forget the idea? There's an elegant solution with ResourceExistsAction. The contract of the root sitemap will become, "Serves static resource if exists, if not, give hand to sub-sitemaps". This is expressed, like that {{{<map:match pattern="**">

</map:match> <map:match pattern="*/**">

</map:match>}}}

It works for us, in hope this helps, FredericGlorieux


Using databases with cocoon mounts - a discovery :)

As I understood it, a big disadvantage of a using a cocoon auto-mount is that you couldn't use databases, as you can't define the database connection without modifying global property pages (which defeats the point of using a mount?). However, I discovered that you can define a database connection directly, as and when you use it, in your mounted sitemap, e.g:

{{{<map:transform type="sql">

</map:transform>}}}

I haven't seen this documented anywhere else, but I think its a useful feature. If you use this in conjunction with HSQLDB's in-memory database, you can build and use a database on the fly with no more set up than this. -nicola


Question: I believe it is possible using the cocoon:/ protocol to access any pipeline in the whole cocoon space; including those marked internal-only="true". Would there be security issues with a 'shared' arrangement? -- MarkLeicester

Answer: Yes, it is possible to access any pipeline in any sitemap using the cocoon:// protocol (note: two slashes). And, using cocoon:/ (one slash), it is possible to access any pipeline in the current sitemap. Flag internal-only="true" on the pipeline means that this pipeline will not be available via the browser, but will be available only through cocoon: (either one or two slashes) protocol. -- Vadim

(internal-only="true" is handy on auto-mounted sub-sitemaps when you want to aggregate for example header and footer from the root and then call the previously mounted pipelines to match content. -- Patrik )

UnderstandingCocoonMounts (last edited 2009-09-20 23:40:14 by localhost)