Servlet Integration

Introduction

The ObjectBox can run within a Servlet container as a Struts Action, as a Servlet, or as a Servlet Filter. Regardless of configuration, the ObjectBox will respond to requests by dynamically invoking an o:XML program. Which program is invoked depends on the configuration - it is either a static program or resolved dynamically from the request URL. Regardless of which, the program will be compiled and cached the first time it is called, then reused each time it is executed.

Requirements

These instructions assume that you have a Java Servlet engine, eg Apache Tomcat, installed on your system. You will also need a JAXP compliant XML parser and XSL Transform Engine, such as Xerces and Xalan from Apache XML. In addition you will need to install Struts if you wish to use the ObjectBox as a Struts Action. Follow the links below if you need to download any of these:

If you are running JDK/JRE 1.4 or newer, Xalan and Xerces will already be part of your configuration.

Configuration

In order for the ObjectBox to work as a Servlet, you need to include the required jar-files in the WEB-INF/lib directory of you web application. You will also need to define the ObjectBox servlet in the web application descriptor file, WEB-INF/web.xml.

If you create your own web.xml file, it needs to include as a minimum the servlet definition and at least one mapping, for example:


<servlet>
  <servlet-name>ObjectBox</servlet-name>
  <servlet-class>org.oXML.extras.http.ObjectBoxServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>ObjectBox</servlet-name>
  <url-pattern>*.oml</url-pattern>
</servlet-mapping>

The first section tells your Java Servlet Engine about the ObjectBox Servlet, the second sets up a file name mapping so that all files ending with .oml will be processed by the o:XML compiler/interpreter.

The configuration may include certain optional parameters, such as: log-level and upload-directory. The first one sets the runtime log level to either debug, info, warning or error. Default is info.

The upload-directory parameter tells the ObjectBox Servlet where to save attachments that are received with multipart MIME requests.

Configuration parameters may be set either on the Servlet level, with init-param, or as top-level context-param elements. Specific servlet init-param values override any context-param settings.


 <servlet>
  <servlet-name>ObjectBox</servlet-name>
  <servlet-class>org.oXML.extras.http.ObjectBoxServlet</servlet-class>
  <init-param>
    <param-name>log-level</param-name>
    <param-value>debug</param-value>
  </init-param>
  <init-param>
    <param-name>upload-directory</param-name>
    <param-value>upload</param-value>
  </init-param>
 </servlet>

Additionally, you can specify in the configuration which o:XML program should be invoked.


  <init-param>
    <param-name>program</param-name>
    <param-value>foobar.oml</param-value>
  </init-param>

If the program parameter is not supplied, the program name is resolved dynamically from the request URL. This is most useful when used with wildcard Servlet mappings, such as *.oml.

HTTP parameters are by default passed to a program as 'normal' program parameters. In addition, the Servlet request, response and session objects may be provided if the program declares them (see Program Parameters for details). This behaviour can be disabled in the configuration. The configuration below will instantiate a Servlet which accepts no input parameters.


  <init-param>
    <param-name>servlet-parameters</param-name>
    <param-value>false</param-value>
  </init-param>
  <init-param>
    <param-name>http-parameters</param-name>
    <param-value>false</param-value>
  </init-param>

URL Parameters

REST is an increasingly popular development paradigm which favours URL's that directly name and identify web resources. For example, to locate book number 55 in your library, a suitable REST-ful URL might be http://localhost/library/book/55. If you've written a program as part of a library application that retrieves books based on their book number, you would probably like to pass the last part of the URL to your program as a parameter.

URL parameters enables exactly this, by tokenizing the part of the URL that follows the Servlet identifier. Any number of parameters may be passed as delimited parts of the URL, using by default a forward slash as the delimiter character. For example you may configure a Servlet and mapping hence:


<servlet>
  <servlet-name>ObjectBox</servlet-name>
  <servlet-class>org.oXML.extras.http.ObjectBoxServlet</servlet-class>
  <init-param>
    <param-name>program</param-name>
    <param-value>retrieve-book.oml</param-value>
  </init-param>
  <init-param>
    <param-name>url-parameters</param-name>
    <param-value>true</param-value>
  </init-param>
  <init-param>
    <param-name>url-parameter-delimiters</param-name>
    <param-value>/</param-value>
  </init-param>
</servlet>

<servlet-mapping>
  <servlet-name>ObjectBox</servlet-name>
  <url-pattern>book</url-pattern>
</servlet-mapping>

By default, URL parameters are disabled, so they need to be explicitly enabled with the url-parameters configuration parameter. The default delimiter for parameter tokens is /, but any character or characters may be used. The parameters will be delivered to the program in the order they are declared,

Program Invokation

If the program configuration parameter is not set, then the Servlet will resolve the program filename from the request URL. For example, if an ObjectBox Servlet is configured with a mapping to all .oml files, then a request for http://host/app/foobar.oml will call the program foobar.oml.

The first time a program is invoked it will automatically be parsed and compiled. It is then stored in a cache, so that subsequent requests can be handled more efficiently. If the program file changes on disk, then it will be automatically recompiled the next time it is requested.

Program Parameters

The ObjectBox servlet will automatically set any program parameters to the value of the corresponding HTTP request parameter. If more than one parameter value is supplied in the request, the program will receive a nodeset with all values. If the request is missing a parameter and a default is not supplied, then a Servlet exception is thrown.

A Servlet program can also define the special variables s:req (request object), s:res (response object) and s:servlet (servlet instance object), where the prefix "s" corresponds to the o:XML servlet extension namespace: http://www.o-xml.com/servlet/. These o:XML objects are wrappers for the underlying Java Servlet HTTP implementations, and all the usual Servlet methods can be called (see the Java Serlvet API).

By default, the program receives request parameter values as o:XML String objects. However parameters may be declared to be of Number or Boolean type, in which case they are parsed and instantiated accordingly.

Example 1: Using Request Parameters


<?xml version="1.0"?>
<?xml-stylesheet href="foobar.xsl" type="text/xsl"?>
<o:program xmlns:o="http://www.o-xml.org/lang/" 
           xmlns:s="http://www.o-xml.com/servlet/">
    <o:param name="amount" type="Number"/>
    <o:param name="currency" select="'GBP'"/>
    <o:param name="o:session"/>
    <o:param name="s:req"/>
...
</o:program>

If the program declares an o:session parameter, this will be initiated with a Map representing the current user session (cookie- or URL-rewriting-based). Any values stored in the session will be retained across requests - unless of course the user has disabled cookies and URL-rewriting is not working.

Program Output

An o:XML Servlet program generally produces XML, HTML or text output as a response. However it may also return a Redirect, Forward or Include directive, or an HTTP error response.

The output is primarily controlled by the program content-type. If it is declared as text/xml, which is the default, or application/xml, then the result is processed by an XSLT engine before it is returned to the client. The type of transformation is determined by an XSLT processing instruction in the program output. If no transformation is declared, the XML output is sent back as is.

Example 2: Response Output


<?xml-stylesheet href="foobar.xsl" type="text/xsl"?>
<o:program>
    <o:param name="amount" type="Number"/>
    <o:param name="currency" select="'GBP'"/>
    <transaction><o:eval select="concat($currency, $amount)"/></transaction>
</o:program>

Instead of XSL transforming the result, a program can generate XML, HTML or text responses directly. The correct content-type should always be declared.

Example 3: HTML Response Output


<o:program content-type="text/html">
  <o:import href="lib/time.oml"/>
  <html>
    <body>
      <p>The time is: <o:eval select="time:Date().string()"/></p>
    </body>
  </html>
</o:program>

Sometimes it is useful to have programs that don't produce any output. This is particularly true of Servlet Filters, which usually delegate the response to other request handlers. To avoid producing output, the content-type should be set to none.

If the program returns a value, then this should be either a net:Message or one of the responses defined in the o:Lib servlet module: Redirect, Forward, Include or Error. The ObjectBox handles the return values accordingly: net:Message objects are written to the response stream, Redirects are returned to the client. Forward and Include directives are processed on the server, the client only receives the final response once all request handlers have completed.

Example 4: Redirection Example


<o:program content-type="none">
  <o:param name="o:session"/>

  <o:import href="lib/servlet.oml"/>

  <-- check if there's a valid login: redirect to login screen if not -->
  <o:if test="not($o:session.get('user-id'))">
    <o:return select="s:Redirect('login.oml)"/>
  </o:if>

</o:program>

ObjectBox as a Java Servlet

When receiving a request, the ObjectBox servlet will execute an o:XML program. The output is then be further processed by an XSL Transform Engine (such as Xalan) only if the program content-type is text/xml or application/xml, and the result contains a valid xml-stylesheet Processing Instruction (eg <?xml-stylesheet href="stylesheet.xsl" type="text/xsl"?>).

ObjectBox as a Servlet Filter

The ObjectBox Servlet Filter is a request handler that executes an o:XML program before passing on control to the next handler. Typically filters collect information or control certain generic aspects of a web application such as security policies. The ObjectBox filter allows processing to continue as normal unless the program it calls returns a value. The value can be a Redirect, Forward or Include directive, or a net:Message, as descrived above.

ObjectBox as a Struts Action

o:XML programs can be easily integrated with an existing Struts application. Redirect, Forwarding and Error handling follows the Struts conventions. To use the ObjectBox Action, you need to declare Struts action mappings. The program parameter can be supplied in the mapping, otherwise the program filename will be deduced from the request URL, same as with Servlet operation.

Example 5: Struts Action Mappings


<action-mappings>
  <action path="*.oml" type="org.oXML.extras.http.ObjectBoxAction"/>
  <action path="/Welcome" type="org.oXML.extras.http.ObjectBoxAction" parameter="welcome.oml"/>
</action-mappings>

Remember that the usual rules for Struts URL's apply: for the action to be invoked the request must be suffixed with .do, or the equivalent site-configured Struts mapping.

Using Struts, o:XML program developers can take advantage of Struts path abstraction. Forward and Include directives are resolved using the available action mappings. A heterogenous web application can freely mix o:XML Servlet programs with JSP's and custom Actions.

Request Attachments

Attachments may be sent by browsers when submitting forms that contain file upload parameters. Such forms may be recognised by the encoding type multipart/form-data.

To access attachments you need to declare the s:req, ie the request object parameter in your program. The attachments can then be retrieved by calling $s:req.getAttachment(name), where name is the corresponding form input parameter. If a form specifies more than one file parameter, they must have different parameter names.

Servlet Context

The Servlet Extensions define a function that may be used to retrive the servlet context. This works the same both for filters and servlets.

To access the ServletContext Java object simply call the function s:context().

Redirect, Forward and Error

The ObjectBox servlet handles several different types of program return values. Returning a value from a program is different from letting it terminate normally, and is generally only useful for handling specific circumstances such as errors or redirections.

By using the various types in the o:Lib servlet module as return values, you can control exactly the type and content of the response that is sent back to the client. One advantage of using return values over calling functions on the Servlet response object, is that you don't have to declare any specific Servlet input parameters. This makes it easy to write flexible web-application programs that can be tested and run directly from the command line, without having to deploy them to a Servlet engine.

To send a redirection response, simply return an instance of the s:Redirect type.


   <o:return select="s:Redirect('target.html')"/>

Instead of redirecting, the current request can be forwarded to a different handler. Forwarding doesn't generate a response, instead the responsibility of responding is delegated. Hence the client will not be aware of the URL or resource changing.

To create any other responses using the established HTTP response codes (see RFC2616 Section 10), you can instantiate a s:Response directly.


   <o:return select="s:Response(204)"/> <-- send a 204 No Content response -->

Errors don't generally contain a response body, instead one is created by the Servlet engine using the configured error pages. Errors can be created with an error code (in the 4xx or 5xx ranges) and an optional error description. If the error description is not given, the default is used - each error code has its own default description.


   <o:return select="s:Error(404, 'Not Found')"/> <-- send a 404 error response -->

The API documentation for the Servlet response library types is available here.