Document last updated January 21, 2001. We are very interested in feedback that would make these materials better. Feel free to write the author, Jonathan Revusky.

Dissecting the "Hello, Niggle" servlet

In this document, we dissect the various parts of this first minimal example. We assume that you managed to go through the concrete steps outlined in the accompanying instructions that explain how to build and deploy the example.

The minimal servlet consists of the following parts:

The Java code

Conventionally, to create a new servlet, you define your own concrete subclass of the abstract class javax.servlet.http.HttpServlet and implement the methods doGet() and doPost(), as well as init() and destroy() if it is necessary to initialize/cleanup any resources used while the servlet is running.

By contrast, the Niggle framework already provides a concrete subclass of the abstract class HttpServlet that you can use directly: com.niggle.servlet.NiggleServlet. (clarifying note) So really, the Niggle framework's comparable subclassing point is com.niggle.servlet.ServletInteraction. An instance of this class represents the servicing of a single request to your servlet. A new instance of your ServletInteraction subclass is instantiated each time the doPost() or doGet() method in com.niggle.servlet.NiggleServlet is invoked. Basically, a NiggleServlet instance delegates the real work of processing the request to an instance of ServletInteraction. And since com.niggle.servlet.ServletInteraction is an abstract class, you must define a concrete subclass and also, you must tell Niggle about it via your servlet engine's configuration mechanism.

Below is the full code of HelloServletInteraction.java:


import com.niggle.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

public class HelloServletInteraction extends ServletInteraction
{
    /**
     * The obligatory constructor. Your ServletInteraction subclass must have a 
     * constructor with this signature. This is the case even though we don't
     * actually have to do anything in the constructor (besides invoking
     * the superclass's constructor, that is.)
     */
     public HelloServletInteraction(HttpServletRequest request, HttpServletResponse response, NiggleConfig config)
     throws IOException
     {
         super(request, response, config);
     }
    
    /**
     * The "default" action handler. This will be invoked
     * if there is no "action" parameter defined in the request parameters.
     * Otherwise, if your request defines a parameter "action=foo"
     * the framework will take this as a signal to invoke the 
     * ServletInteraction's execFoo() method. Our simple "Hello, World"
     * servlet has only a single "default" action so we only define execDefault().
     */
    public void execDefault() throws IOException
    {
        this.page = getPage("hello.html");
        page.expose("title", "Hello, World");
        page.expose("message", "Welcome to the brave new niggle world!");
    }
}

Take a look at the execDefault() method above. In the first of the three lines, the page variable is set and in the next 2 lines, a couple of template variables are set or exposed -- title and message.

So, what is going on here? Well, as you likely now at this point, the philosophy of the Niggle framework is based on a rigorous separation of presentation from application logic. Thus, the presentation details of any output to the client are encapsulated in a page template, which is completely separate from the application logic per se. So, the ServletInteraction class has a member variable called page and this must be set in the course of any execXXXX method. The above code is a case in point.

In short, the ServletInteraction instance has a member variable called page that encapsulates this template construct. Note that the page variable is an instance of the com.niggle.templates.Page interface.

The page template

The last section deliberately (or necessarily) left certain questions unanswered. The code in the above example assumes the existence of a page template corresponding to "hello.html" and assumes a mechanism for exposing the template variables in the page was left deliberately vague.

Now it is time to get concrete about this. Below is the trivial "hello.html" template that uses the 2 template variables that the java code sets.


 
<html> 
<head> <title>${title}</title> </head> 
<body> 
<P>Message: ${message}</P>
</body> 
</html> 

Note that the above page template code looks just like an HTML page. Well, it basically is an HTML page. The only thing special about it is the presence of the two strings ${title} and ${message} that are treated specially. As you likely notice, they correspond to the 2 template variables defined in the java code above via the calls to page.expose().

Essentially, the difference between a page template and a plain old static HTML page is that some of the content is determined dynamically. Note that, by default, the niggle framework leverages the open-source Freemarker template engine. A key feature of freemarker's syntax is that strings enclosed in ${...} are escaped, i.e. determined dynamically.

The webapp configuration file

The third and last element of our minimal example is the configuration file that tells the servlet server about our servlet.


<?xml version="1.0"?>
<web-app>
    <servlet>
        <servlet-name>
            helloniggle
        </servlet-name>
        <servlet-class>
            MinimalNiggleServlet
        </servlet-class>
        <init-param>
            <param-name>INTERACTION_CLASS</param-name>
            <param-value>HelloServletInteraction</param-value>
        </init-param>
    </servlet>
</web-app>

This file defines the mapping of "helloniggle" to our actual servlet class MinimalNiggleServlet. In the later, more complex examples, we will need to define more configuration parameters.

Addendum: A note about the Classpath

1. Note about subclassing NiggleServlet

In this example, we actually create a trivial subclass of NiggleServlet even though it is not strictly necessary. And, you probably noticed that our subclass contains no functionality at all! In fact, as you might suspect, we could have specified com.niggle.servlet.NiggleServlet as our servlet class in the web.xml file and the example would have worked equally well.

The reasoning behind creating a trivial subclass of NiggleServlet is really hypertechnical in nature. In the above example, we put all our classes, libraries, and supporting files under the WEB-INF directory. This means that we expect it all to be loaded via the servlet context classloader, not the "global" system classloader (i.e. system-level CLASSPATH). There is a looming gotcha here though. You see, the you will likely find that the most natural way of developing and deploying a niggle app will likely be to add niggle.jar and the other libraries it depends on to the system CLASSPATH. What this means is that classes in the com.niggle.* space will be loaded by the system classloader. However, it turns out to be more convenient if your servlet subclass is loaded by a servlet-specific classloader. That is why you might want to do as we do here, and define a completely trivial subclass of NiggleServlet and put it under WEB-INF/classes. This corresponds to the recommended deployment servlet deployment model, and, for one thing, allows the dynamic reloading of servlets available in most servlet runners to work. This is a feature that can help make your development and deployment cycles more efficient.

A related gotcha is that if your niggle-based servlet is loaded by the system classloader, your ServletInteraction class and the related page templates must also be located relative to the system CLASSPATH, since the attempt by the com.niggle.servlet.* code to load them will fail, as these resources do not exist in the context of the system classloader!

Back to main text