Tasks list

Let's look at the implementation of the view/allTasks application page, which lists all tasks provided by the DatabaseFacade.

The scenario is the following:

  1. In Flowscript, access and query the DatabaseFacade
  2. Pass the data from Flowscript to a page which uses the JXTemplateGenerator to access it
  3. In the JXTemplate page, iterate over the data elements and display them

Sitemap

Here's the first pipeline definition in sitemap, activated by the view/allTasks request:

<map:match id="view" pattern="view/*">
<map:call function="query_{1}"/>
</map:match>

This causes the above request to call the query_allTasks() Flowscript function (Flowscript listing here).

Later, the Flowscript will call the internal/generate-view/taskList pipeline to generate a view using the JXTemplateGenerator and the views/taskListView.xml page:

<map:match id="genView" pattern="internal/generate-view/*">
<map:generate src="cocoon-app/views/{1}View.xml" type="file"/>
<map:transform type="jx" label="jxDebug"/>
<map:call resource="html"/>
</map:match>

Java beans to JXTemplate page

The following lines of Flowscript code implement the first two steps of our scenario, getting a List of TaskBean objects from the DatabaseFacade and passing it to the taskList pipeline.

0006 // Access java "database" facade object
0007 var db = Packages.org.apache.cocoon.samples.tour.beans.DatabaseFacade.getInstance();
...
0010 function query_allTasks() {
0011    list = db.getTasks();

0013    cocoon.sendPage("internal/generate-view/taskList", {
0014        title : "List of tasks",
0015        task : list,
0016        db : db
0017    });
            
As the taskList pipeline uses a JXTemplate generator, the corresponding page will have access to the variables passed with the sendPage call.

The db object is also passed to the page, but it is only used to access its db.version field.

We're not using continuations here (there's no sendPageAndWait), Flowscript serves only as a thin layer of glue between our Java objects and our JXTemplate view page.

JXTemplate page

Here's the JXtemplate page that generates the taskList view, using the title, task and db variables supplied by the above Flowscript code:

<page id="page">
<title> #{title} </title>
<content>
<table>
<tr>
<td class="legend"> id </td>
<td class="legend"> Assigned to </td>
<td class="legend"> Task name </td>
</tr>
<c:forEach select="#{task}">
<tr class="listRow">
<td>
<a href="singleTask?taskId=#{id}"> #{id} </a>
</td>
<td> #{assignedTo} </td>
<td> #{taskName} </td>
</tr>
</c:forEach>
</table>
<p class="footer"> #{format-number(count(task),'###')} tasks in list - #{db/version}
<br/>
<a href="../../"> Table of contents </a>
</p>
</content>
</page>

Note the use of a <c:forEach> element, from the JXTemplate namespace, to iterate over members of the task collection.

That's it!

Let's summarize what happened here:

  1. A request for view/allTasks comes in
  2. The query_allTasks() Flowscript function is called and uses the Java DatabaseFacade to retrieve a Java List of TaskBean objects.
  3. Flowscript uses the cocoon.sendPage() function to trigger the execution of a sitemap pipeline, passing to it some data as JavaScript variables.
  4. The pipeline uses the JXTemplate generator to dynamically insert data in an XML template document, generating one of our <page> documents.
  5. Our usual XML-to-HTML conversion transformation is used for final presentation.
This might seem complicated when explained in so much detail, but the interesting thing to note is that, once again, very little code must be written to make this work. And the whole thing stays very flexible and customizable.