JXTemplateGenerator JavaDoc

Keep in mind that there's also a JX!TemplateTransformer with the same functionality.

Current namespace: xmlns:jx="http://apache.org/cocoon/templates/jx/1.0"

Sitemap Configuration: <map:generator name="jx" src="org.apache.cocoon.generation.JXTemplateGenerator" label="content" logger="sitemap.generator.jx"/>

Accessing data with the JXTemplateGenerator

JSTL and XPath

The JX!TemplateGenerator provides a generic page templating mechanism. You can embed either JSTL or XPath expressions to access data from several implicitly defined Cocoon objects (e.g. request, session etc.), or from objects you have passed to the JX!TemplateGenerator from your flow script. For example, this is how you would access the current contination id using each expression language:

As one can see, you explicitly need knowledge about the object types and their methods when using the Javascript notation. The other to (JSTL and JXPath) are much easier, they simplify the access to Maps and getProperty() methods by using the "." notation.

Older Cocoon without cocoon. prefix (not sure when there was a change...):

Accessing data from implicitly defined Cocoon objects

You have access to some implicitly defined objects (available through both JSTL and XPath):

An access to the request uri for example would be (JSTL):  ${cocoon.request.uri} 

Accessing sitemap parameters

Cocoon sitemap parameters are accessed through the parameters object. For example, your sitemap might look like this: {{{<map:generate src="jxtemplate.xml" type="jx">

</map:generate}}} To access the value of my-param in your jxtemplate.xml file (using JSTL in this case) your expression would look like this: ${cocoon.parameters['my-param']} (when you have simpler names without special characters like "-", you won't need the ['something'] notation but can still use  ${cocoon.parameters.something} ).

Accessing data passed from your flow scripts

You may also pass Java Beans, DOM, JDOM, or JavaScript objects from your flow scripts. Once again, this will work in both JSTL and XPath. For example: {{{var greatlakes = Superior", "Michigan", "Huron", "Erie", "Ontario; sendPage(uri, {"greatlakes" : greatlakes});}}}

Those parameters can be accessed as top-level variables, eg. accessing "greatlakes" is as easy as (JSTL):  ${greatlakes} .

Basic features

jx:choose, jx:when, jx:otherwise

The choose tag performs conditional block execution by the embedded when sub tags. It renders the body of the first when tag whose test condition evaluates to true. If none of the test conditions of nested when tags evaluate to true, then the body of an otherwise tag is evaluated, if present.

<jx:choose>
    <jx:when test="Expression">
       body
    </jx:when>
    <jx:otherwise>
       body
    </jx:otherwise>
</jx:choose>

jx:forEach

Iterate over a collection of objects.

<jx:forEach [var="Name"][items="Expression"][begin="Number"][end="Number"][step="Number"]>
    body
</jx:forEach>

jx:formatDate

The formatDate tag provides facilities to format Date values.

<jx:formatDate value="Expression"
               [dateStyle="Style"]
               [timeStyle="Style"]
               [pattern="Expression"]
               [type="Type"]
               [var="Name"]
               [locale="Expression"]> 

jx:formatNumber

The formatNumber tag is used to display numeric data, including currencies and percentages, in a locale-specific manner. The formatNumber> action determines from the locale, for example, whether to use a period or a comma for delimiting the integer and decimal portions of a number.

<jx:formatNumber value="Expression"
                 [type="Type"]
                 [pattern="Expression"]
                 [currencyCode="Expression"]
                 [currencySymbol="Expression"]
                 [maxIntegerDigits="Expression"]
                 [minIntegerDigits="Expression"]
                 [maxFractionDigits="Expression"]
                 [minFractionDigits="Expression"]
                 [groupingUsed="Expression"]
                 [var="Name"]
                 [locale="Expression"]> 

jx:if

Conditional logic based on evaluation of an expression in @test.

<jx:if test="Expression">
    body
</jx:if>

jx:import

Import a JXTemplate, the uri will be resolved by cocoon (possible to use cocoon:/ etc.).

<jx:import uri="URI" [context="Expression"]/>

This tag is not for including XML, but just for other JXTemplates.

jx:macro, jx:parameter

Define a new custom tag. When calling a macro, the line will be substituted with the body of the macro.

<jx:macro name="customTagName" [targetNamespace="Namespace"]>
    <jx:parameter name="paramA" [optional="Boolean"] [default="Value"]/>*
     body
</jx:macro>

Once defined, call your macro with:

<customTagName paramA="someValue"/>

If you pass the 'greatlakes' as in the example above, you may have a macro:

<jx:macro name="tablerows">
    <jx:parameter name="list"/>
    <jx:parameter name="color"/>
    <jx:forEach var="item" items="${list}">
        <tr><td bgcolor="${color}">${item}</td></tr>
    </jx:forEach>
</jx:macro>

<table>
    <tablerows list="${greatlakes}" color="blue"/>
</table>

Your result would be:

<table>
   <tr><td bgcolor="blue">Superior</td></tr>
   <tr><td bgcolor="blue">Michigan</td></tr>
   <tr><td bgcolor="blue">Huron</td></tr>
   <tr><td bgcolor="blue">Erie</td></tr>
   <tr><td bgcolor="blue">Ontario</td></tr>
</table>

In cocoon 2.2-dev you can call your macro like this:

<jx:call macro="customTagName">
  <jx:withParam name="paramA" value="someValue"/>
</jx:call>

You are allowed to use expressions in macro name:

<jx:set var="macroName" value="customTagName"/>
<jx:call macro="${macroName}">
  <jx:withParam name="paramA" value="someValue"/>
</jx:call>

jx:out

Evaluates an expression and outputs the result of the evaluation:

<jx:out value="Expression"/>

Please note that jx:out automatically handles objects of type Node, Node[], NodeList, XMLizable and renders them as SAX events.

Cocoon 2.2: You can make JXTG parse expression string result into SAX events by using following syntax:

<jx:out value="Expression" xmlize="true"/>

Additionally you can ignore root element of generated content with strip-root="true" attribute.

Example:

myXml = "<root><p>content</p><p>content2</p></root>";

<nonxmlized><jx:out value="${myXml}"/></nonxmlized>
<xmlized><jx:out value="${myXml}" xmlize="true" strip-root="true"/></xmlized>

result is:
<nonxmlized>&lt;root&gt;&lt;p&gt;content&lt;/p&gt;&lt;p&gt;content2&lt;/p&gt;&lt;/root&gt;</nonxmlized>
<xmlized><p>content</p><p>content2</p></xmlized>

jx:set

Define/set a variable

<jx:set var="Name" value="Value"/>
or
<jx:set var="Name">
    [Value=body]
</jx:set>

jx:template

Defines a new JXTemplate

<jx:template>
    jx-elements
</jx:template>

jx:attribute (cocoon 2.2-dev)

Set's an attribute.

<jx:attribute name="Name" value="Value"/>

Allows for conditional attribute injection. Example:

<jx:set var="a" value="cd"/>
<two>
    <jx:if test="${a == 'dd'}">
        <jx:attribute name="second" value="twoAttr"/>
    </jx:if>
    xyz
</two>
<three foo="bar">
    <jx:attribute name="foo2" value="bar2"/>
    <jx:attribute name="${a}" value="${a}"/>
    <abc>def</abc>
</three>

evaluates to:

<jx:set var="a" value="cd"/>
<two>
    xyz
</two>
<three foo="bar" foo2="bar2" cd="cd">
    <abc>def</abc>
</three>

Advanced

This section describes some advanced options.

Caching

It is possible for cocoon to cache output of this generator. In order to do so you need to provide two pieces of information: the key under which to register the cached response object in the cache and an object that describes the validity of the cached contents.

Note: This feature is experimental and only available in the cocoon 2.2.0-dev branch in CVS

jx:cache-key

Specify the cache key using jx:cache-key attribute.

<element jx:cache-key="Expression"/>

jx:cache-validity

Specify the cache validity using jx:cache-validity attribute.

<element jx:cache-validity="Expression"/>

Example

* template.xml:

<?xml version="1.0"?>
<page jx:cache-key="${cacheKey}" jx:cache-validity="${cacheValidity}"
      xmlns:jx="http://apache.org/cocoon/templates/jx/1.0"/>

* flow.js:

importPackage(Packages.org.apache.excalibur.source.impl.validity);

function foo() {
  sendPage("bar", {cacheKey: "theKey", cacheValidity: new ExpiresValidity(1000)})
}

* sitemap.xmap:

<?xml version="1.0"?>
<map:sitemap>

...

  <map:pipeline type="caching">

    <map:match pattern="foo">
      <map:call function="foo"/>
    </map:match>

    <map:match pattern="bar">
      <map:generate type="jx" src="template.xml"/>
      <map:serialize type="xml"/>
    </map:match>

  </map:pipeline>
</map:sitemap>

Heavy business object instantiation

Even though JXTemplateGenerator caches the view data it does not mean the controller will know about that. If your script contains heavy calculations or database operations this is what you can do (based on: http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=108617011419745&w=2)

If your business object takes an age to instantiate, and you can decide whether or not to instantiate it based upon request parameters, then wrap it in a lighter component that does (in pseudocode):

lightObject.getValidity() {
  return request.parameters["a"]+ request.parameters["b"];
}

lightObject.getHeavyBusinessObject() {
  if (this.heavyBusinessObject == null) {
     this.heavyBusinessObject = HeavyBusinessObjectBuilder.newObject();
  }
  return this.heavyBusinessObject;
}

Then, in your jxt, you use jx:cache-validity="${lightObject.getValidity()}" construct, and then later in your jxt, you access your heavy object with #{/lightObject/HeavyObject/property1} . This latter expression will only be invoked if the page is not cached.

JXTemplateGenerator (last edited 2009-09-20 23:43:09 by localhost)