This page contains the information explaining how to develop Java servlets using OCaml-Java. The first sections describe how to compile and link servlets, as well as listeners. Then, a section explains how to deploy compiled servlets. Finally, the last section consists in a complete example of a simple HTTP servlet.

Servlets and related listeners are Java classes that extend or implement a given Java type. However, when ocamljava is used to compile OCaml modules, its default behavior is to generate Java with only static methods, for the various OCaml functions. As such, ocamljava-compiled modules cannot be used as servlets by a servlet container. This is why a dedicated compilation mode, triggered by the -servlet command-line switch, is introduced.

The -servlet command-line switch informs the compiler that a proper Java class should be generated for latter use by a servlet container. The command-line switch takes a parameter used to indicate the kind of servlet or listener the user is interested in. Of course, the different servlet/listener kinds requires differents sets of functions to define their behaviour. The following table indicates the module type that a module should implement in order to be successfully compiled.

Java type-servlet parameterOCaml module type
javax.servlet.GenericServletgenericJavaServlet.Generic
javax.servlet.http.HttpServlethttpJavaServlet.HTTP
javax.servlet.ServletContextListenercontext-listenerJavaServlet.ServletContextListener
javax.servlet.ServletContextAttributeListenercontext-attribute-listenerJavaServlet.ServletContextAttributeListener
javax.servlet.http.HttpSessionListenersession-listenerJavaServlet.HTTPSessionListener
javax.servlet.http.HttpSessionActivationListenersession-activation-listenerJavaServlet.HTTPSessionActivationListener
javax.servlet.http.HttpSessionAttributeListenersession-attribute-listenerJavaServlet.HTTPSessionAttributeListener
javax.servlet.http.HttpSessionBindingListenersession-binding-listenerJavaServlet.HTTPSessionBindingListener
javax.servlet.http.HttpSessionIdListenersession-id-listenerJavaServlet.HTTPSessionIdListener

When an OCaml module M is compiled with the -servlet command-line switch, a class named MImpl is generated, in the package set by the -java-package command-line switch (defaulting to pack).

The actual deployment depends on the actual servlet container used to run the web application. Any container able to handle war files running on an 1.7+ JVM can be used. Deployment has been successfully tested with Apache Tomcat and Jetty. Cloud facilities based on such containers can then be used to host the servlets (Heroku and CloudBees have been successfully used to host servlets).

This example shows how to compile and link a simple servlet greeting a user whose name is passed to the servlet as a GET parameter. We first define the signature of our module in the hello.mli; as it is an HTTP servlet, the file is simply:

include JavaServlet.HTTP
As we are only interested in answering to GET requests, we only redefine the do_get function (note that the type t of the module is used to store data in the servlet instance), leading to the following contents for hello.ml:
type t = unit

let init _ = ()

include JavaServlet.Default_HTTP

let print out s =
  Java.call "javax.servlet.ServletOutputStream.println(String)"
    out
    (JavaString.of_string s)

let get req s =
  Java.call "javax.servlet.ServletRequest.getParameter(String)"
    req
    (JavaString.of_string s)
  |> Java.wrap

let do_get _ _ req resp =
  Java.call "javax.servlet.http.HttpServletResponse.setContentType(_)"
    resp
    (JavaString.of_string "text/html");
  let out = Java.call "javax.servlet.http.HttpServletResponse.getOutputStream()" resp in
  print out "<html>";
  print out "  <body>";
  begin match get req "name" with
  | Some name -> already_seen := name :: !already_seen;
                 print out (Printf.sprintf "    Hi %s!<br>" (JavaString.to_string name))
  | None      -> print out "    Hi!<br>"
  end;
  print out "    <form action=\"hello\" method=\"get\">";
  print out "      <input type=\"text\" name=\"name\">";
  print out "      <input type=\"submit\" value=\"go\"><br>";
  print out "    </form>";
  print out "  </body>";
  print out "</html>"

let do_options _ _ _ resp =
  JavaServlet.options resp [`GET; `OPTIONS]
The code of the servlet heavily relies on the Java extensions that are presented here.

In order to deploy this code, a web.xml file is also necessary, with a contents akin to:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

  <display-name>Hello Application</display-name>
  <description>...</description>

  <servlet>
    <servlet-name>HelloImpl</servlet-name>
    <servlet-class>pack.HelloImpl</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>HelloImpl</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>

</web-app>

The following commands are then used to build the archive:

ocamljava -c hello.mli
ocamljava -c -java-extensions hello.ml
ocamljava -o hello.war -war web.xml javalib.cmja hello.cmj

The hello.war is finally ready to be deployed to a servlet container. For example, if copied to the webapps directory of an Apache Tomcat instance, the servlet can be tested at an URL such as http://localhost:8080/hello/hello?name=xyz.