Sunday, July 15, 2012

A Frege Servlet

I was playing around with Frege to create a small Servlet. There is no web framework for Frege available yet so it is going to be mostly interfacing with native Java classes. Here is the code snippet in Frege.

First, we need to create native declarations in Frege for the Java classes and methods that we are interested in. For this example, we will be defining data types for HttpServletRequest, HttpServletResponse, HttpServlet classes and an implementation for Servlet's doGet method.

In HttpServletRequest class, we will be encoding getParameter method. The type signature for that method,

Since this method could return null in case of missing parameters from the request, the return type is Maybe String. Frege automatically handles null if the return type is "Maybe".

Now let us declare a getWriter function to it's native counterpart in HttpServletResponse class.

Since HttpServletResponse.getWriter method can throw IOException and since it is not a pure method, the return type is IO (Exception PrintWriter).

The definitions for ServletContext and HttpServlet are not of much interest since we are not going to use any of the methods from those classes for this example.

The definition of doGet function is where we are actually writing to response. From the signature of the function, it takes a servlet, a request and a response instance and returns IO () since it is a side-effect function which doesn't return any value. Another important point is that the parameter names are prefixed by bang character which makes the parameters strict which would otherwise be all lazy since Frege is by default lazy.

The last missing piece is how do we specify a servlet class in web.xml? I don't really know yet in Frege how to create a named class that extends a Java class. So I created the servlet in Scala which will forward the request to our doGet function defined in Frege.

Here FregeServlet.doGet(this, request, response) calls the doGet function defined in FregeServlet module and returns an IO lambda. Then we call that IO action by passing an arbitrary integer representing the real world. Here the Scala's support for 'apply' method is helpful.
FregeServlet.doGet(this, request, response)(realWorld)
is actually
FregeServlet.doGet(this, request, response).apply(realWorld)
where the doGet function defined in Frege module returns frege.rt.Lambda which has an apply method. The final method call _e is to evaluate the lazy value which is where the IO action is actually executed and our response is sent to the client. We can add this class as servlet in web.xml and point to the servlet URL to see the Frege/Scala servlet in action.