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:
ingoingFilter
method of the filter gets called with the request as a parameter.
outgoingFilter
of the filter gets called with the request and
the reply as parameters.
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.
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.
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.
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):
outgoingFilter
method, and doesn't represent a
significant step in complexity.
Enjoy !
Jigsaw Team
$Id: filter.html,v 1.11 1998/05/27 13:39:18 yves Exp $