Copyright © This document is created under the Mozilla Public License
Abstract
This document describes all possible mechanisms for JSP pages to include other pages. These mechanisms (of which 3 are MMBase specific) can be used to build modular sites.
Table of Contents
Since the release of MMBase 1.5 there are two tags within the MMBase
taglib which are introduced in this document:
<mm:treeinclude>
and
<mm:leafinclude>
. These tags
allow a site to be set up in a very modular way; this documentation
is meant to aid templaters to use these tags efficiently.
In the next sections we will first describe the existing include mechanisms, and later on elaborate on the specifics of the two newly introduced tags.
With a JSP Include Directive, one can directly insert the content of another JSP as if it was part of the calling JSP. The servlet engine will combine these JSPs before compilation; one big JSP file is the result. The following syntax is used for this directive:
<%@ include file="includes/header.jsp" %>If a page 'A' does an include of page 'B', this means that all information defined in page 'A' (most importantly: methods and variables) are available in page 'B'. This means that all methods and variables need to have unique names, otherwise conflicts will occur.
You can (and must if using JSPX) also use the following syntax:
<jsp:directive.include file="includes/header.jsp" />
The main benefit of using this directive is speed: inclusion is done at compile-time and it has no cost on execution time. The disadvantage is that the name of the page to be included needs to be known at compile-time; dynamic inclusion of pages is not possible.
Another way of inclusion of another JSP page is by using the JSP Include Action. The difference with the Include Directive is that not the source of the JSP, but it's output is included. The include JSP page is being executed within the servlet engine and it's output is returned to the calling page. The following syntax is used:
<jsp:include page="includes/page.jsp?param1=value"> <jsp:param name="param2" value="value2" /> </jsp:include>The example shows that there are two ways of passing named variables: either pass them on directly in the URL, or add them using
<jsp:param>
tags.
The main benefit of using the Include Action is that the URL to include can be constructed during execution of the page; and that double variable names in pages are no problem. However, every included page results in a new request to the servlet engine, which means there is a bit of a performance impact when compared to the include directive.
Actually not a complete new request is done. The same request is reused. The performance overhead is probably neclectible.
The MMBase Include has great resemblance with the JSP Include Action, parameter names and subtags have the same names:
<mm:include page="includes/page.jsp?param1=value"> <mm:param name="param2" value="value2" /> </mm:include>The advantage of using the MMBase Include instead of the JSP Include Action is that contextvariables can be used. By using the
referids
parameter you can
easily pass on any variables that were given to this page. For example,
in the includes/page.jsp
file one
could use the following code snippet:
<mm:include page="subinclude.jsp" referids="param1,param2" />
TreeInclude is an extension to the MMBase Include, which chooses a page from a list of possible pages; and then includes the one best suited. The general idea is that TreeInclude receives a path of objects that are used to find a file on disk that fits the given objects most closely.
The functionality that finds a template for a given list of
objects is called smartpath. Smartpath is a function on a node,
which returns the best possible path for that node. The standard
behavior of Smartpath is to return a path that exists of the
node numbers, possibly postfixed by a random string. So, if
getSmartPath()
is called on
node number 138, in a directory where one of the subdirectories
is 138something
, getSmartPath()
will return this path. If there is no matching path, a null
value is returned.
The default behavior described here can be overridden by a
developer by creating a new builder class for a nodemanager.
For all following examples, we assume that such a special class
has been written, that uses the value of the title
field of the node as the path to return.
NOTE: when getSmartPath()
is called,
it always operates by default from the HTML root
of the servlet context. That means that TreeInclude does NOT include files from the
current working directory.
When doing a TreeInclude, you need to specify a list of objects. These are then
used to create a list of possible pages to include. First, getSmartPath()
is called on the first object. Then, it is called on the second object from the directory that
was just found; this procedure continues until all objects are used,
or until one of the getSmartPath()
s returns
a null
value. The following example will make this
a bit more clear:
<mm:treeinclude page="includes/page.jsp?param1=value" objectlist="100,140,321"> <mm:param name="param2" value="value2" /> </mm:include>The three objects mentioned in the
objectlist
parameter have the following properties:
100; this is an object of type portals
with
title 'mmbase'
140; this is an object of type events
with
title 'mmevent3'
321; this is an object of type news
with
title 'introduction'
getSmartPath()
method
on all objects; it stops as soon as a null
value
is returned. All possible pages that could be included are:
/mmbase/mmevent3/introduction/includes/page.jsp
/mmbase/mmevent3/includes/page.jsp
/mmbase/includes/page.jsp
/includes/page.jsp
The LeafInclude and TreeInclude tags bear great similarities: they both
use getSmartPath()
on the objects passed
in the objectlist
parameter in order
to find a page to include. The difference is that when TreeInclude discards
objects that return a null
value, while
the LeafInclude continues with substituting this null
value with the builder name of the object. An example will shed some light
on this:
<mm:leafinclude page="includes/page.jsp?param1=value" objectlist="100,140,321"> <mm:param name="param2" value="value2" /> </mm:include>The three objects mentioned in the
objectlist
parameter have the following properties:
100; this is an object of type portals
with
title 'mmbase'
140; this is an object of type events
with
title 'mmevent3'
321; this is an object of type news
with
title 'introduction'
getSmartPath()
method
on all objects; if this yields a null
value, the
name of the builder will be used. The following list of possible pages is compiled:
/mmbase/mmevent3/introduction/includes/page.jsp
/mmbase/mmevent3/news/includes/page.jsp
/mmbase/events/news/includes/page.jsp
/portals/events/news/includes/page.jsp
In newer servlet containers, also the possibilities to use tag-files exists. These are very similar to dynamic includes like jsp:include and mm:include but provide a nicer syntax, and better way of packaging for general reuse (they can be included in jars).
An example of a custom image-tag. A file WEB-INF/tags/my/image.tagx was placed, containing this:
<jsp:root version="1.2" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:mm="http://www.mmbase.org/mmbase-taglib-2.0"> <jsp:directive.attribute name="template" /> <mm:node> <mm:image template="s(800x800>)+f(png)"> <a title="${_node.title}" href="${_}" onclick="window.open(this.href, '${mm:escape('identifier', _node.title)}', 'width=${dimension.width + 20},height=${dimension.height + 20}'); return false;"> <mm:image template="$template" mode="img" /> </a> </mm:image> </mm:node> </jsp:root>
Now it can be used as follows (in a JSPX):
<sometag xmlns:vl="urn:jsptagdir:/WEB-INF/tags/my"> ... <mm:listnodes type="images" max="5"> <my:image template="s(x200)" /> </mm:listnodes> ....Which creates (maximal) 5 images in the HTML which are clickable, and produce a pop-up window with a bigger version of the same image if you click on them.
When using dynamic includes (like tag-files, mm:include or mm:leafinclude), you may want to use the REQUEST scope to pass stuff around to this included page.
MMBase variables can be explicitely written to the request scope:
<mm:write referid="foo" request="bar" />
And also be explictely picked up:
<mm:import from="request" externid="bar" />Though that is not even necessary, because EL also expresses variables on the request.
Since MMBase-1.8.1 several implicit variables are on default scoped in the request, which makes dynamic include even easier to use. These are:
The locale settings of mm:locale and mm:content. Effectively included pages have the same locale a the including page, which makes much sense.
The escaper parameter of the mm:content tag. No need to use a mm:content on all included pages.
The _node implicit 'current' node variable. This is also picked up by a mm:node tag with no parents. The effect is that you can easily refer to the 'current' node in a include page, simply by surrounding an empty mm:node. The tag-file example makes use of this.
This is part of the MMBase documentation.
For questions and remarks about this documentation mail to: [email protected]