Templates
In the previous section we learned how the mapper
uses a links file to
map an external address space (the module's public address space) to a set of named internal URI requests.
In this section and the next, we will explore how a requested resource can be dynamically composed
using the xrl
runtime and templates.
XRL Templates
An XRL template is simply an XML document that is processed by the xrl
accessor.
A template may refer to other templates using XRL to an unlimited depth.
To support unlimited levels of composition, the XRL runtime recursively descends into the template and
resolves xrl: URI references until all are satisfied.
To initiate the recursive XRL processing of a template, issue a URI request for active:xrl
with a template argument.
Below is an excerpt from a links document which shows how to initiate active XRL template processing.
<links basepath="ffcpl:/workbench/xrldemo/">
<link>
<name>index2</name>
<ext>/part2/index</ext>
<int>active:xrl+template@xrl:part2-template</int>
<args>links</args>
</link>
<link>
<name>part2-template</name>
<int>ffcpl:/xrldemo/part2/template.xml</int>
</link>
</links>
In this example, the template is a static resource, a very basic HTML shell and
XRL only descends one level.
Later we will see how to leverage the power of NetKernel to create very
flexible and adaptable applications.
<html xmlns:xrl="http://1060.org/xrl">
<body>
<h1>Part2 Template</h1>
</body>
</html>
To run this example, request
http://localhost:8080/workbench/xrldemo/part2/index
.
As before, the request is directed to the mapper.
The mapper located the matching link and the corresponding internal URI to issue as a subrequest.
In this case it is an active: URI request which executes the XRL runtime.
The runtime loads the template and, since this template is very basic, simply returns the
template as the response.
This example illustrates two points.
First, the XRL recursively descends through templates to resolve all references.
Second, this is a very simple, static template that does not request additional
services.
We will explore more complex examples next.
XRL Resource Widgets
XRL uses templating to support the notion of XML resource widgets.
Resource widgets are separate, resuable, NetKernel resources that can be recursively
composed to create other sophisticated, flexible, and easily maintained
NetKernel resources.
At any level of application implementation abstraction, one can focus on
the composition of resources defined by the next lower level to build
the required services provided to the layer above.
NetKernel strong and complete support for isolation between layers
and resources results in rapid development and easy maintenance of
applications.
NetKernel supports dynamic content within static templates, static
resources within a dynamic template, and other combinations.
We will explore several variations in the remainder of this tutorial.
Dynamic Resource Content Push
An XRL resource widget may accept content that is pushed to it at runtime.
For example, the following XRL template defines HTML framing code that might be used
by a web site for all of its pages.
<html xmlns:xrl="http://1060.org/xrl">
<body>
<h1>Part3 Template</h1>
<xrl:include href="xrl:content" />
</body>
</html>
Notice the <xrl:include .../>
tag.
That indicates to XRL that this template can accept content
dynamically at runtime.
The href="xrl:content"
portion of the
tag indicates that content will be provided externally.
Let's see how the widget is given the HTML page's content.
In the links structure for this example:
<links basepath="ffcpl:/workbench/xrldemo/">
<link>
<name>index3</name>
<ext>/part3/index</ext>
<int>active:xrl-html+template@xrl:part3-template+content@xrl:part3-content</int>
<args>links</args>
</link>
<link>
<name>part3-template</name>
<int>ffcpl:/xrldemo/part3/template.xml</int>
</link>
<link>
<name>part3-content</name>
<int>ffcpl:/xrldemo/part3/content.xml</int>
</link>
</links>
You can see that the active:xrl URI has an additional argument content.
Here is the static content for the link xrl:part3-content.
<div xmlns:xrl="http://1060.org/xrl" style="background-color: silver; padding:10px;">
Part 3 Content
</div>
Now, run the example:
http://localhost:8080/workbench/xrldemo/part3/index
.
We see from the result that the content
has been placed within the template.
During execution the xrl runtime locates xrl:include tags and replaces them with the
resource referenced by the tag's href attribute URI.
Therefore in this example, the href URI in the template's xrl:include tag indicates to the XRL runtime
to replace the tag with the
resource with URI xrl:content.
But, during the XRL runtime's recursion, xrl:content is a special link which references the
content argument which was passed to the runtime.
So, as we saw, the net result is that the content is pushed into the template.
Dynamic Resource Content Pull
Instead of having content pushed into an XRL resource widget,
the widget can pull the content.
For example, the following template defines an HTML <div>
section
that uses the xrl:include
tag to reference an XRL resource
to pull when the template is evaluated at runtime.
<div xmlns:xrl="http://1060.org/xrl" style="background-color: silver; padding:10px;">
Part 4 Content
<xrl:include href="xrl:red-box" />
</div>
In this example, the red-box
resource that is reference (and pulled) is the following:
<div xmlns:xrl="http://1060.org/xrl" style="background-color:red; height: 50px; width: 50px; margin:10px;" />
The links document that defines the overall structure of this example is very
similar to the last example...
<links>
<link>
<name>index4</name>
<ext>/part4/index</ext>
<int>active:xrl-html+template@xrl:part4-template+content@xrl:part4-content</int>
<args>links</args>
</link>
<link>
<name>part4-template</name>
<int>ffcpl:/xrldemo/part4/template.xml</int>
</link>
<link>
<name>part4-content</name>
<int>ffcpl:/xrldemo/part4/content.xml</int>
</link>
<link>
<name>red-box</name>
<ext>/widgets/red-box</ext>
<int>ffcpl:/xrldemo/widgets/red-box.xml</int>
</link>
</links>
As before, a template is populated with a content fragment which is passed as an argument on the request
to the active:xrl runtime.
However, in this case the content resource also contains an xrl:include tag that
defines the resource to pull into the widget.
No prizes for guessing what we get when we try this:
http://localhost:8080/workbench/xrldemo/part4/index
.
We see that the XRL runtime has recursively located the xrl:include within the initial content
substitution and has pulled that resource into the content, which in turn was pushed into the template.
XRL recursion can be nested in this way to any depth.
Exercises
- See what happens when you duplicate the xrl:include tag in workbench/part4/content.xml
- Try creating a new static content resource with an associated link and include that into the template as well.
- Advanced exercise: try requesting a dynamically generated active: URI resource as an include.
How does it work?
Starting from an
initial template, XRL discovers embedded URI resource-references and populates
the template by issuing requests to the NetKernel URI address space.
Each resource that is sourced is parsed to locate further resources for inclusion;
this recursive composition continues until there are
no more references left to resolve.
To provide a flexible level of indirection, resource references may be named
in a links document.
The links document allows the XRL functionality to
be cleanly separated into two distinct phases.
-
Request Mapping: using the mapper
accessor a request
for a resource on a public URI interface is resolved via the
links document to the implementing URI function.
-
XRL Recursion: the production of a resource is achieved by processing
a template in the XRL
runtime which
recursively sources XML resources to compose the final composite XML resource.
As we will discover in this tutorial, the separation of the XRL composition model into
these parts provides a number of benefits.
- The public URL structure of a site is independent of the implementing code - this offers several benefits including:
- rapid development of site structure using scaffolding techniques which can be independently replaced with active functionality.
- refactoring of internal implementation can occur with no disruption to the public application.
- Functional overlays, such as access control and logging, can be applied transparently to independent regions of an application.
-
The implementation of a function to produce a resource is decoupled - it may be static or dynamically generated using a variety of
languages.
-
The 'logical' URI addresses of internal resources may be rewritten to 'physical' public URLs as part of the XRL recursion.
In this way
a developer need only think about the logical structure which eliminates the possibility of broken-link bugs.
Lastly, before we start working through some examples, this guide is intended to be interactive -
all of the examples are located in the workbench module located
in the modules/ directory of the NetKernel installation.
The inline examples presume that the workbench module is imported into the front-end-fulcrum
such that the workbench is exposed to the HTTP transport running on localhost port 8080.