Return-Path:
* The general flow of actions in an application which uses the control flow
* is as described below.
*
* The request is received by Cocoon and passed to the sitemap for
* processing. In the sitemap, you can do two things to pass the control to
* the Controller layer:
*
*
* <map:call function="function-name"/>
* construction.
* <map:continue with="..."/>
construction.
* This restarts the computation saved in a continuation object
* identified by the string value of the with
attribute.
* This value could be extracted in the sitemap from the requested URL,
* from a POST or GET parameter etc. When the computation stored in the
* continuation object is restarted, it appears as if nothing happened,
* all the local and global variables have exactly the same values as
* they had when the computation was stopped.
*
* Once the JavaScript function in the control layer is restarted, you're * effectively inside the Controller. Here you have access to the request * parameters, and to the business logic objects. The controller script * takes the appropriate actions to invoke the business logic, usually * written in Java, creating objects, setting various values on them etc... *
* ** When the business logic is invoked, you're inside the Model. The business * logic takes whatever actions are needed, accessing a database, making a * SOAP request to a Web service etc. When this logic finishes, the program * control goes back to the Controller. *
* *
* Once here, the Controller has to decide which page needs to be sent back
* to the client browser. To do this, the script can invoke either the
* sendPage
or the sendPageAndContinue
functions.
* These functions take two parameters, the relative URL of the page to be
* sent back to the client, and a context object which can be accessed
* inside this page to extract various values and place them in the
* generated page.
*
* The second argument to sendPage
and
* sendPageAndContinue
is a context object, which can be a
* simple dictionary with values that need to be displayed by the View. More
* generally any Java or JavaScript object can be passed here, as long as
* the necessary get methods for the important values are provided.
*
* The page specified by the URL is processed by the sitemap, using the * normal sitemap rules. The simplest case is an XSP generator followed by * an XSLT transformation and a serializer. This page generation is part of * the View layer. If an XSP page is processed, you can make use of JXPath * elements to retrieve values from the context objects passed by the * Controller. *
* ** The JXPath elements mirror similar XSLT constructions, except that * instead of operating on an XML document, operate on a Java or JavaScript * object. The JXPath logicsheet has constructs like *
jpath:if
,jpath:choose
,jpath:when
,jpath:otherwise
,jpath:value-of
andjpath:for-each
,
* A special instruction, jpath:continuation
returns the id of
* the continuation that restarts the processing from the last point. It can
* actually retrieve ids of earlier continuations, which represent previous
* stopped points, but I'm not discussing about this here to keep things
* simple.
*
* Going back to the sendPage
and
* sendPageAndContinue
functions, there is a big difference
* between them. The first function will send the response back to the
* client browser, and will stop the processing of the JavaScript script by
* saving it into a continuation object. The other function,
* sendPageAndContinue
will send the response, but it will not
* stop the computation. This is useful for example when you need to exit a
* top-level JavaScript function invoked with
* <map:call function="..."/>
.
*
* The above explains how MVC could be really achieved in Cocoon with the * control flow layer. Note that there is no direct communication between * Model and View, everything is directed by the Controller by passing to * View a context object constructed from Model data. In a perfect world, * XSP should have only one logicsheet, the JXPath logicsheet. There should * be no other things in an XSP page that put logic in the page (read View), * instead of the Model. If you don't like XSP, and prefer to use JSP or * Velocity, the JXPath logicsheet equivalents should be implemented. *
* ** As hinted in the previous section, an application using Cocoon's MVC * approach is composed of three layers: *
* In more complex applications, the flow of pages can be thought of smaller * sequences of pages which are composed together. The natural analogy is to * describe these sequences in separate JavaScript functions, which can then * be called either from the sitemap, can call each other freely. *
* ** An example of such an application is the user login and preferences * sample I've just checked into the * Cocoon CVS *
* ** This application is composed of four top-level JavaScript functions: *
login
,registerUser
,edit
andlogout
.* The entry level point in the application can be any of these functions, * but in order for a user to use the application, (s)he must login first. * Once the user logs in, we want to maintain the Java User object which * represents the user between top-level function invocations. *
* *
* If the script does nothing, each invocation of a top-level function
* starts with fresh values for the global variables, no global state is
* preserved between top-level function invocations from the sitemap. In
* this sample for example, the login
function assigns to the
* global variable user the Java User object representing the
* logged in user. The edit
function trying to operate on this
* object would get a null value instead, because the value is not shared by
* default between these top-level function invocations.
*
* To solve the problem, the login
and
* registerUser
functions have to call the
* cocoon.createSession()
method, which creates a servlet
* session and saves the global scope containing the global variables' value
* in it. Next time the user invokes one of the four top-level functions,
* the values of the global variables is restored, making sharing very easy.
*
* Even if you don't need complex control flow in your application, you may
* still choose to use the MVC pattern described above. You can have top-
* level JavaScript functions which obtain the request parameters, invoke
* the business logic and then call sendPageAndContinue
to
* generate a response page and return from the computation. Since there's
* no continuation object being created by this function, and no global
* scope being saved, there's no memory resource being eaten. The approach
* provides a clean way of separating logic and content, and makes things
* easy to follow, since you have to look at a single script to understand
* what's going on.
*
* Originally taken from * Ovidiu Predescu's Weblog. *
* **