<- Constructing XHTML Documents Contents Static Analysis of JWIG Programs ->

Services and Sessions

JWIG is a session-centered language, in contrast to most other Web service programming languages. A session consists of a sequence of interactions between a server and a client. Sessions are initiated by the clients but are controlled by the service code, conceptually by threads running on the server. An interaction is performed by sending a Web page with a form to the client. The session thread waits for the client to fill out and submit the form, and then continues execution. A service consists of a number of session types, which are entry points for the session threads.

The Structure of a JWIG Program

A JWIG program consists of a service class, which is a subclass of Service. It will be instantiated upon the first client request to the service, and only a single instance will exist over the entire lifetime of the service.

The service class contains a number of session classes. These are non-static inner classes of the service class, and are subclasses of Service.Session. Each client request to start a session will instantiate the corresponding session class and run its main method in a freshly created thread. The session object will exist until the session terminates, either explicitly by executing an exit statement (described below), or implicitly due to a timeout caused by a nonresponding client.

Client interaction is performed through the show and exit statements. The statement show exp, where exp is an expression of type XML, sends the given document to the client, waits for the client's response, and then resumes execution of the session thread. The statement exit exp, where exp again is of type XML, sends the given document to the client and then terminates the session thread. If the session thread falls off the end of the main method, it will implicitly execute exit with a standard "Session terminated" document.

A document shown to the client, using either show or exit, must consist of a single <html> ... </html> element. The XHTML 1.0 document type declaration and a character encoding are automatically inserted. Any document given as argument to the show statement should contain at least one form element with no action attribute. This will instruct the JWIG runtime system to insert a special action attribute that will resume execution of the session thread. The client requests continuation of the session by submitting such a form. Other form elements with explicit action attributes may be present in the document, for submitting to other kinds of services. These are ignored by JWIG.

The values of the input fields in the submitted form can be read using the receive name expression. Here, name is the name of the field to read, and the result of the expression is a String containing the value submitted for the field. If no such field was submitted, or if more than one value was submitted for it, a ReceiveException is thrown. To read the values of an input field for which more than one value (or a varying number of values) is submitted, the expression receive[] name is used. This returns a String array containing all the values of the field, in the order in which they were submitted. This expression never fails. If no values were submitted for the given field, an empty array is returned.

Example:

    import dk.brics.jwig.runtime.*;
    
    public class Hello extends Service {
        private static final XML wrap = [[
            <html>
              <head>
                 <title>A JWIG example</title>
              </head>
              <body>
                <[body]>
              </body>
            </html>
        ]];
    
        private static final XML question = [[
            <form>
               What is your name?
               <input type="text" name="person" />
               <br/>
               <input type="submit" name="answer" value="Answer" />
            </form>
        ]];
    
        private static final XML greeting = [[
            <h1>Hello <[who]>!</h1>
        ]];
    
        public class Test extends Session {
            public void main() {
                show wrap <[body = question];
                exit wrap <[body = greeting <[who = receive person]];
            }
        }
    }

This JWIG program defines a service called Hello with a single session called Test. The session shows to the client a document containing a text input field named person and a submit button entitled "Answer". The session then waits for the client to press this button. The name entered in the text field is read using the receive person expression. This value is plugged into the who gap of the greeting template, and the resulting document is shown as the final output of the session. After sending this document to the client, the session terminates, without waiting for the client to respond. Notice the use of a wrapper template (the template assigned to the wrap variable) to supply the outer structure at every show and exit statement. This is a standard technique used in most JWIG programs.

Input Fields

Input fields in the submitted form result in name/value pairs being sent back to the server. These pairs are accessible from the JWIG program through the receive name and receive[] name constructs. To make it easier to handle the received information, some input fields behave somewhat differently than normal, as seen by the JWIG program. For this reason, the exact behavior of the different kinds of input fields are described in the following:

If the form was submitted but no submit button was pressed (which can happen in some browsers), receiving the name "submit" will give an empty string. If a non-graphical submit button was pressed, receiving the names "submit.x" and "submit.y" will both give -1.

The special behavior of submit buttons makes it easy to decide which submit button was pressed, since its name always appears under the name "submit". The value attribute of submit buttons can then be used to specify the textual label on the button, independent of the internal handling of the button.

In addition to the normal and graphical submit buttons, JWIG includes a special kind of submit button - the submit anchor. If an a element has a submit attribute but no href attribute, the whole anchor will act as a submit button with the given name. This way, anything that can be an anchor can also be a submit button. This is implemented by JavaScript code in the href attribute. If the a element in question furthermore contains a status attribute, this will be the text shown in the status line of the browser when the mouse is over the anchor.

Document Post-Processing

The XHTML specification require that lists, tables, menus, and some other constructs must contain at least one element. Requirements like this are very inconvenient when the output is generated dynamically, since any code that generates, for instance, a list with a dynamic number of elements must handle zero elements as a special case. For this reason, JWIG does some preprocessing of the generated XHTML to allow such constructs to be generated by the program and still show only valid XHTML to the client. Specifically, the post-processing does the following:

Furthermore, for form elements without a method attribute, method="POST" is inserted by default.

Pages and seslets

Service.Session is not the only inner class of the Service class that can be subclassed to create client-instantiable server threads. Two more such classes exist - Service.Page and Service.Seslet.

If a session always proceeds directly to an exit statement without ever executing a show statement, it can be a page instead of a session. A page is just like a session, except that shows and receives are not allowed. Its main method is invoked in exactly the same manner. For this single-page purpose, pages are usually more efficient than sessions.

A seslet is used for arbitrary communication with a non-browser client, such as, an applet or another Web service. As seslet's main method takes as arguments an InputStream and an OutputStream for the communication. A seslet produces no XHTML output. It should simply terminate when the communication is over. On the client side, an URLConnection should be opened to the seslet URL. The streams obtained by calling getInputStream() and getOutputStream() will then be connected to the seslet streams.

Exceptions

A number of exceptions can be thrown by the show, exit and receive constructs:

ShowException:
Thrown by the show and exit statements if some error, e.g. an I/O error, occurs while showing the document.
ValidateException:
If runtime validation is enabled (by the validate_xhtml field), this exception is thrown by the show and exit statements if the shown document does not validate according to the XHTML 1.0 specification.
TimeoutException:
Thrown by the show statement if the client does not respond within the show timeout set for the session.
CodeGapException:
Thrown by the show and exit statements if some error occurs while executing the code gaps in the document, or if an exception is thrown from within a code gap.
ReceiveException:
Thrown by the receive expression if no field of the given name was submitted by the client, or if more than one value was submitted for it.

The JWIG static analysis is able to verify statically for a given JWIG program, that neither the ValidateException nor the ReceiveException can occur at runtime, provided that the client behaves according to the specification with respect to the submitted field values, and that no external XML templates have been changed since the time of the analysis.


<- Constructing XHTML Documents Contents Static Analysis of JWIG Programs ->