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:
- In Flowscript, access and query the DatabaseFacade
- Pass the data from Flowscript to a page which uses the JXTemplateGenerator to access
it
- 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:
- A request for view/allTasks comes in
-
The query_allTasks() Flowscript function is called and uses the Java DatabaseFacade
to retrieve a Java List of TaskBean objects.
-
Flowscript uses the cocoon.sendPage() function to trigger the execution of a sitemap
pipeline, passing to it some data as JavaScript variables.
-
The pipeline uses the JXTemplate generator to dynamically insert data in an XML template
document, generating one of our <page> documents.
-
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.