Jigsaw

Jigsaw resource's filter tutorial

This tutorial assumes that your are familiar with Jigsaw architecture, and that you have read both the configuration and the resource tutorials. It will explain you the last major concept of Jigsaw you should be aware of: resource filters.

As was said in the architectural overview of Jigsaw, each HTTP request ends up performed by some target resource instance. For the sake of simplicity, we didn't mentioned at that time, that most resource classes provided with the Jigsaw server inherits from the FilteredResource class. All instances of this class are able to manage a set of filters: these filters, which are to be instances of sub-classes of ResourceFilter, are called-back twice during request processing:

A resource filter is itself a resource: this means, in particular, that it is described - like all other resources - by a Java class, and a set of attributes. It also means that it can be pickled/unpickled, etc.

The remaining of this tutorial will walk through the code of the CounterFilter. This filter just counts the number of hits to its target resource. Before going any further, you should again make sure you have understand the resource tutorial. This tutorial has two sections: the first one will describe our filter's code, and the second one will explain how to attach it to a target resource.

The CounterFilter class

Its my hope that you will be amazed by how easy this filter is to code. As for writing new resource classes, the first thing we need to is to define the set of attributes that our filter will handle. In the case of a simple counter filter, the only attribute we need is simply the counter itself. Assuming we want our class to be in the w3c.jigsaw.filters package, we start by writing the following piece of code:

package w3c.jigsaw.filters;

import w3c.jigsaw.http.*;
import w3c.jigsaw.resources.*;

public class CounterFilter extends ResourceFilter {
    /**
     * Attribute index - The counter attribute.
     */
    protected static int ATTR_COUNTER = -1 ;

    static {
        Attribute a   = null ;
        Class     cls = null ;
        
        try {
            cls = Class.forName("w3c.jigsaw.filters.CounterFilter") ;
        } catch (Exception ex) {
            ex.printStackTrace() ;
            System.exit(1) ;
        }
        // Declare the counter attribute
        a = new IntegerAttribute("counter"
                                 , new Integer(0)
                                 , Attribute.EDITABLE) ;
        ATTR_COUNTER = AttributeRegistry.registerAttribute(cls, a) ;
    }
}

This code does the following: it starts by declaring our resource filter class, and specify (through the static statement) its counter attribute, which is an editable integer attribute, whose default value is 0. We register this attribute to the AttributeRegistry, and get back the token for accessing the attribute. If some of this seems unfamiliar, then refer to the resource tutorial.

We can now implement the ingoingFilter method of our filter, which is as simple as you might expect:

package w3c.jigsaw.filters;

import w3c.jigsaw.http.*;
import w3c.jigsaw.resources.*;

public class CounterFilter extends ResourceFilter {
    /**
     * Attribute index - The counter attribute.
     */
    protected static int ATTR_COUNTER = -1 ;

    static {
        Attribute a   = null ;
        Class     cls = null ;
        
        try {
            cls = Class.forName("w3c.jigsaw.filters.CounterFilter") ;
        } catch (Exception ex) {
            ex.printStackTrace() ;
            System.exit(1) ;
        }
        // Declare the counter attribute
        a = new IntegerAttribute("counter"
                                 , new Integer(0)
                                 , Attribute.EDITABLE) ;
        ATTR_COUNTER = AttributeRegistry.registerAttribute(cls, a) ;
    }

    /**
     * We count all accesses, even the one that failed.
     * @param request The request being processed.
     */

    public synchronized int ingoingFilter(Request request) {
        int i = getInt (ATTR_COUNTER, 0) ;
        setInt(ATTR_COUNTER, i+1) ;
        return DontCallOutgoing ;
    }


}

That's all ! However, this needs a bit more explanations. First of all, you might be surprised that we didn't provide an implementation for the outgoingFilter method. There is two reasons for this: the first one is that our super-class provide an empty outgoingFilter method, this solves the compiler problem. The second one is that as you might have noticed, our ingoingFilter returns a special integer, DontCallOutgoing. This integers tells the target filtered resource that the filter has performed all its tasks in the ingoingFilter method, so there is no need to call its outgoingFilter method.

Note that the counter value will be made persistent across servers invocation by the Jigsaw runtime. To be clear, this means that you can shutdown the server, and restart it: the count will keep up to date. Now, enough coding, let's play with our filter, the next section explains how to attach an instance of the filter to some target resource.

Installing the filter

First, let's decide on some resource we want to count access to. For the sake of simplicity, let's say we want to count the number of accesses to the /User directory resource. As you might have guess, the first thing we want to do is to point our favorite browser to /Admin/Editor/User. This, as expected, brings up the form to edit the /User directory resource. We follow the AddFilter link at the bottom of the page, which prompts us for the filter's class. We fill this with w3c.jigsaw.filters.CounterFilter, and press the OK button. The /User directory resource editor now has two more link (at the bottom of the page), we follow the w3c.jigsaw.filter.CounterFilter one, to customize our filter attributes. The count is 0, and we don't care about the filter's name.

Now, we can access /User (point your browser to /User). Reload the filter's editor...the value is still 0, however, internally the value is now 1. To check this, restart the server (by using the /Admin/PropertiesEditor restart button). NOTE: form some reason, the editor of a resource doesn't update the attribute value it displays when they change behind the scene, this is why you still see the count has being 0. This should be fixed really soon.

Further reading

If you want to understand better the concept of filters, then you can look at the available filters, here is a path (by increasing complexity):

Enjoy !


Jigsaw Team
$Id: filter.html,v 1.11 1998/05/27 13:39:18 yves Exp $