Small and Simple Web Applications - the Friki Way (Part 1)

Frank Carver, February 2003

Abstract

This article is the first of a series which laments the bloated and unmaintainable state of so many J2EE web applications and looks at ways to keep web applications small, simple and flexible. The series uses the author's Friki software as a case study, and discusses ways to design and build a powerful, flexible and usable web application in less space than a typical gif image.

This article introduces some problems of J2EE applications. It also gives some requirements for a wiki-like application. First steps are taken in the design of the application, with a focus on deferring storage decisions and deciding on a technology for dynamically producing web pages.

Introduction

Java is extremely popular for developing server-based web applications. Lots of big name web sites use Java technology to drive their customer interactions. Any Java developers' web site is full of material about J2EE, JSP, EJB, JMS, JNDI, JDBC, XML, SOAP and many more. It's an alphabet soup of abbreviations and jargon. New technologies are added to Java faster than we can keep up. Making sense of it all and trying to use the best of each bit could drive anyone crazy.

Sure, all this stuff is powerful, but sometimes it pays to stop, calm down, and think for a while.

The above is a quote from Shaker Built: The Form and Function of Shaker Architecture by Paul Rocheleau and June Sprigg. You can read a little more about this quote, and this book (appropriately enough) on Ward Cunningham's Wiki.

I have worked on many server-side Java applications in my years as a consultant, and vanishingly few of them exhibited any of the virtues of that simple Shaker quote. I've seen applications with a maze of twisty JSP pages, all (almost) alike. I've seen business data squeezed in and out of XML just because it seemed "cool". I've seen software which only works on old and unsupported versions of application servers and databases. I've seen software where none of the developers dared touch the existing code for fear it might break something. I've seen software where changing a text label on a web page required a database rebuild. I've seen a project running on six high-spec Sun workstations and needing a team of over 20 developers, testers and managers to maintain it switched off and replaced by a spreadsheet!

I don't want to build unmaintainable monsters like this, and I hope you don't either. But how can we learn to do things right? Surely there are some well-thought-out applications to study? Sad as it may be, there are very few, particularly if we are interested in Java web applications.

In this article I will use one of my own applications (Friki) as a case study. I don't claim that it is perfect, and I actively encourage anyone reading this to look for ways to simplify things. I also encourage you all to look for other examples of web applications which do a useful job in a simple, small and flexible way.

About Friki

Friki (pronounced "freaky") is "Frank's Wiki". A "Wiki" is a web site, where any user can create new pages, edit existing pages, create links, and search the site whenever they want to. This may seem weird, but it can be an extremely powerful and flexible way to take notes, collaborate and work on the web.

All you need to view and edit pages is the browser you are using to read this. Every page on a Wiki has some sort of "edit button", which shows the text of the page in an edit box, and allows you to change it and re-save the new version. Once you have created or edited some pages, most Wikis have a built-in "search" facility to find them. Making links and creating pages is as easy as typing the name of the (new or old) page while editing. You don't need to know HTML, Java, XML or any of the other buzzwords to use a Wiki. In most cases you can just type paragraphs of text, and the software will do its best to lay it out for you.

Friki is a pure Java web application which can be installed as simply as dropping "friki.war" into any modern servlet container or Java application server. Strictly that means anything which implements version 2.3 or later of the Java Servlet API. Friki is small, fast and flexible. The complete web application archive (war) file is just 66k bytes, and needs nothing apart from a servlet container to run.

Pre compiled web applications, source code and other documentation for Friki is available from http://www.efsol.com/. The original Wiki implementation by Ward Cunningham is in Perl and hosted at http://c2.com/cgi/wiki. For more information I highly recommend the definitive book: The Wiki Way - Quick Collaboration on the Web by Bo Leuf and Ward Cunningham. ISBN 0-201-71499-X.

Let's Make One

To show the design techniques which can help us keep things small, simple and flexibile, let's work through the process of designing and building a Wiki (which we'll call "Friki").

The most important part of a Wiki is the collection of pages. Pages are where people put their information, notes or opinions. Pages and their content are what makes a Wiki come alive! Such a page collection must support a few basic operations: The system needs to get the content of a named page to display it, save some new content to a named page, create a new page, and search all the pages for some supplied text or pattern. Although not strictly necessary, most Wikis also support a "does this page exist?" operation, so that an indicator can be shown to users if a linked page has no text yet.

If you are like me, your mind is already fizzing with ideas how to implement such a page store -- maybe a JDBC database, or perhaps a JNDI repository, even a high-performance distributed caching package you have recently read about....

Stop! That is the way to a bloated, multi-megabyte, undeployable, unmaintainable nightmare.

Instead, I suggest we defer the implementation details of how to store pages. Instead, we'll create an interface (a special type of Java class), with the operations we need, and use that. When we actually need to store some pages, we can use the simplest implementation we can get away with, as long as it implements this interface. Later, if we ever do need more performance, scalability or distributability, we just need to code a slightly more complex implementation of the same simple interface. Eventually, this approach might let us automatically build several specific versions of the software for different situations, each containing only what is actually needed and used.

  package com.efsol.friki;

  import java.util.Iterator;

  public interface PageRepository
  {
    public Page get(String name);
    public void put(String name, Page page);
    public boolean contains(String name);
    public Iterator matchingPageNames(String pattern);
  }

There are a few things to note about this interface:

  1. It's short. One of the many causes of bloated code is having to write lots of useless methods, just because they are required by an interface. If you have ever tried to write a class which implements java.util.Map, you'll understand what I mean. So be ruthless with what you don't put in an interface, and consider splitting methods into more than one interface wherever possible.
  2. It has a simple, descriptive but abstract name ("PageRepository"). It's easy to imagine classes implementing this interface, and to recognize the sort of names they might have: DatabasePageRepository, FilePageRepository, etc.
  3. We haven't decided how to represent a page and its contents yet, so we have deferred the decision by just inventing a class name for it.
  4. It only uses classes from the core Java APIs and this application. By all means use code from other sources when you are implementing an interface, but using external classes in an interface is extremely dangerous and can end up forcing your application to include some large jar file which it never even uses!
  5. Design doesn't stop just because we have started writing code. This interface may change or even disappear before any code is released. Don't worry. It has expressed what we know so far in simple, usable terms and enabled us to move on to design other parts of the system.

The next most important part of a Wiki is the user interface. We have already decided that we will be using a web interface, so it's pretty obvious that we need at least some way of producing HTML to send to a browser. What's not obvious is the best way to do this.

Conventional Java "wisdom" would indicate that this is a natural fit for JSP. Indeed, I did try an attempt at this using JSP, but found far too many problems. The main problems with JSP stem from the way that pages are compiled by the server after deployment (the rest of the code is compiled much earlier on the development machine). To run even the simplest common-sense validity check on a JSP can often involve building a war file, transferring the war file to the server machine, deleting an old directory structure, restarting the server, waiting for the server to expand the war file, using a browser to navigate to the page being tested (pausing for all intermediate pages to be compiled and loaded as we go) and eventually attempting to run the page. Only to see it fail with a simple syntax error in an embedded script. Yuck!

Testing JSPs is hard and slow. Debugging JSPs is hard and slow. Hard to test and debug means hard to change and hard to keep simple. If we are going to use JSP, we need to get all that code out of the pages and into real Java which can be compiled and tested before it is deployed.

In an attempt to solve this problem, the J2EE jargon machine provides "custom tag libraries", or "taglibs". Taglibs are a way of formalizing JSP scripts and referring to them using XML syntax in the JSP pages. For each script you would have put in the page, you create a class which implements an interface or extends a supplied base class, then make a method in your new class containing what you would have put in the script, then describe your new class in 10-20 lines of XML or so in a "TLD" file, put the "TLD" file in the right place, then make sure the application "web.xml" configuration refers to the TLD file. Does that sound easy, simple, or error-free? It isn't.

The latest enhancement added to JSP is JSTL, a "standard" tag library which is provided by the container, and you just need to link in to your "web.xml". Using JSTL can simplify the use of tags a bit; sometimes you can use the provided tags instead of writing your own. Taglibs can definitely help reduce some sorts of JSP problems. But maybe if you didn't use JSP, you wouldn't have these problems in the first place!

So, JSP seems problematic. But what other implementation choices are there?

JSP is usually contrasted against a beginners' approach to server-side code: embedding random fragments of HTML all through some huge servlet. In this case, the comparisons are right, even JSP is better than that! Imagine how slow and cumbersome things would be if you had to edit, recompile and redeploy the whole application every time you made a tiny change to the HTML.

Happily, there is another alternative. One that seems strangely absent from the J2EE examples. It's called "templates", and is actually very simple. In essence, a template is just a file with some "tokens" in it. Before the file is shown to the user, the "tokens" are replaced with real values. No compilation, no messing about.

For maximum flexibility, I like to allow web pages to be designed, produced and viewed using whatever tool the designer is most happy with. That may be Dreamweaver, it may be Notepad or Emacs. For this to work, we must be able to use "tokens" which don't get in the way of the text of the page. That means no "pseudo-html" (as used by JSP, Zope and FreeMarker). I reckon there aren't many "~" characters in most web pages, so let's use that as a way to indicate our tokens, at least for the moment.

In the case of Friki, all we really need is one token for the page content and one for the page title. To keep things simple, we'll use ~title~ for the page title, and ~content~ for the content. A very simple example web page using this format might look like:

  <html><head><title>Friki: ~title~</title><head>
  <body>
  <h2>~title~</h2>
  ~content~
  <hr width='100%'>
  <a href='edit?~title~'>edit this page</a>
  </body>
  </html>

I hope you can see just how easy that is. You can create and edit such HTML with any tool which can work with basic web pages. No fancy support for weird formats needed.

How are We Doing?

Well, we haven't made a Wiki yet! So far we have an interface which defines the API for a page repository, and an example HTML page with tokens for viewing page contents. This may not seem like much, but if we were working in a team, we'd already be able to start working three times as fast. One person could make the page repository, another could design some web pages, and another could carry on thinking about servlets and template processing and stuff. This is important, we've done just enough design to split off some achievable tasks and get productive straight away.

Next session we'll go into more details about how to make our own very lightweight template "engine" to expand these templates into web pages, and how to get some page content to put in them. In the meanwhile, to see what you can do with "full fat" templating software, you might enjoy looking at WebMacro and Velocity. Remember :- don't just take their word for it; it's your job to keep software small, simple and flexible.