An Ex-nunc application is a compiled executable that handles HTTP requests received through a connector (CGI or FastCGI) from the Web server. It relies on OcamlNet to manage low-level communication with the Web server, to retrieve preprocessed parameters from the request, and to write the XHTML response to a transactional output channel. The Ex-nunc framework offers a higher level of abstraction to the programmer, because it takes care of some of the most common tasks required by Web applications.
The following diagram shows how the request flows from the Web browser to the Ex-nunc application server, and how the response gets back to the client.
The browser posts an HTTP request to the Web server, that forwards it to the application through the connector. The Ex-nunc server process the request and sends back an HTTP response containing the XHTML page that will show on the client.
The page to be served is determined server side: the Web browser points simply to the application executable and does not directly request a specific page. The first request in each session will show the start page, a page without parameters, whose name is specified in the application configuration file. The XHTML page served back to the client will contain all the navigation information (current page name and parameters), stored in hidden form fields. When the users submits the form, the application server will retrieve the navigation information, and will be able to determine which page is to be displayed. This way, there is no need to build a Web server module (e.g., an Apache module, or an IIS ISAPI filter) to handle the xnunc extension, simplifying the overall architecture, and permitting the use of standard connectors. Moreover, there is no need to deploy the template files to the server (or an empty placeholder), therefore simplifying the deploy of the application, because the Web server will not be queried for a specific resource file, and there is no risk to obtain a "file not found" (404) error. If any error occurs during the request processing, a customizable error page, whose name is specified in the application configuration file, will show up.
When a request is received by an Ex-nunc application, after the page dispatcher has determined which page to show, the selected page runs through a life cycle composed by a series of processing steps, depicted by this flowchart (see also the equivalent UML state machine diagram.)
From the runtime perspective, each page is an instance of an OCaml
class that implements the page_behavior
interface. The
class implementation is generated from the Ex-nunc template. The class
constructor is stored into a collection and retrieved using the template
name as the key.
After the object, representing the current page, has been
constructed, its init
method is called. If the current page
is the first page served in a session, the next step will be the
initialization of page parameters. Otherwise, the session was already
created and is ready to be loaded.
The load_session
method fulfills the task of retrieving
session data from the configured storage (e.g., server memory, or a
hidden field). After restoring session data, the runtime will load page
parameters.
If the current page is served for the first time, the page parameters will be initialized to values passed by the page dispatcher or by the calling page (as the consequence of a page change action). Now, the page state is fully restored and the next step is to build the page structure. Otherwise, if the page is resulted from a form submission, the runtime will load current page parameters, reading them from a hidden field. The next step is to validate user input.
The validation process is started building the input validator
collection, calling the build_validator_collection
method.
If the page is valid (i.e., the output of is_valid
is
true
), then the runtime will read user input and store it
into form parameters. Otherwise, user input will be ignored, and form
parameters will maintain their default value.
The runtime invoke the read_user_input
method. This
method will populate form parameters, the OCaml record containing the
strongly typed form field values, with values entered by the user. This
step completes the page state loading. Next, the runtime will build the
page structure.
The page structure is the tree data structure that stores all the
page elements composing the page. It is built by the
Build_page_structure
method. Next, if this is the first
invocation for the current page, the runtime will be ready to persist
the page state. Otherwise, the events, the user may have triggered, must
be handled.
When the user submits a form, he may trigger a series of events,
handled by one or more callback functions. The
handle_ui_events
methods executes the associated callbacks.
Next, the runtime will handle page changing.
As a consequence of an event triggered by a user, a page change may be required. To achieve this, the target page name and parameters must be specified. If the target page is different from the current page, the new page is served, restarting from the initialization step. Otherwise, the next step is state saving.
The runtime calls the save_state
method, to persist all
the page state to the proper storage. The current page and parameters
will be saved into hidden fields, while the session data is saved to the
configured storage. Then the page is ready to be rendered.
The render
method is invoked, to produce the XHTML
response, which will be written to the transactional output channel
provided by OcamlNet.
The complete
method takes care of committing what the
rendering step wrote to the transactional output channel. This step ends
the process. Now the response is sent back to the client.