As Java Web application frameworks have become more powerful and flexible, they've also become more complex. John O'Hanley's WEB4J framework in many ways flies in the face of this trend: it offers few customization options, but is easy to learn and work with. Read on to learn about the unusual (and somewhat contrarian) development principles behind WEB4J. You'll also have the opportunity to test out the framework by building a feature for a sample Web application.
For me, a good framework should be understandable by a goat -- or at least by the lower orders of primates. I don't like a framework that could effectively double as an IQ test. I like tools that make me say, "Oh, is that all there is? Is it really that simple?" I like them because I know my coding will sprint like Usain Bolt, not waddle along like an aging Orson Welles. The simpler the framework, the faster you can learn it, and the faster you can use it.
When it comes to the development process, most tools should be pain-killers -- that is, they should address some sort of pain. At best, they should remove the pain entirely; if that's not possible, they should minimize the pain. But my experience in building Java Web apps has been that the tools currently in wide use often cause more pain than they relieve. The types of pain I've suffered have been many and various:
Most Web applications are too complex -- and complex tools are, by definition, hard to learn and hard to use. Many popular Web frameworks include hundreds or thousands of classes published in their javadocs; in contrast, WEB4J has only 85 published classes. Building plain, boring Java Web apps that just pump data into and out of a database should be just that -- boring. But it's often a long-distance phone call away from boring, because it's so complicated. The fundamental thesis of WEB4J is that currently building Java web apps is unnecessarily complex. If you don't accept this thesis, then WEB4J is not for you, and you should not waste another femtosecond reading this article.
Many tools make extensive use of XML files. But coding in XML is widely recognized as a particularly fruitful source of pain. XML files aren't part of compiled code, so errors are often found only at runtime. XML syntax is widely regarded as verbose and clunky, and many modern IDEs are wonderfully rich tools for editing Java but not much help with XML files. Unfortunately, many frameworks place XML at the very core of their design.
Some tools force you to abandon things you already know how to do, and replace them with a parallel set of techniques specific to that tool. For instance, in Struts 1.x, you typically don't implement form controls using standard HTML; instead, the framework forces you to replace standard form controls with a set of custom tags, one for each type of control. Tools should build upon what you already know, and not force you to learn a different way of doing essentially the same thing.
Many tools explicitly declare themselves to be "flexible" and "powerful" in their marketing blurbs. But flexibility necessarily implies a certain amount of added complexity. It simply takes more time and experience to understand all the options, and to make the right choices. If you are looking for a simpler approach, then all these decision points can be a source of pain.
The larger the set of tools used by a given app, the more difficult it becomes to train people to build and maintain that app. If, in addition, some of those tools have a long learning curve, then the problem is aggravated. Moving less experienced folk onto projects becomes increasingly difficult.
What's different about WEB4J?
What's different about WEB4J is its central design goal. Simply put, WEB4J's central design goal is aggressive minimalism, a kind of minimalism not seen in other Java tools. This minimalism is manifest in two ways: the small size of its API, and in the concision of apps built using the framework.
Here's a summary of what's different about WEB4J:
- It's very small, and has a philosophy of deep simplicity and minimalism.
- It's not free of charge, it's not open source, and it has nothing to do with rich Internet apps.
- It enables package-by-feature. Each feature gets its own directory. That directory contains all items related to a single feature, and only that feature (code, JSP, and SQL statements, and the like).
- It lets you put SQL in plain .sql text files. It does not use object-relational mapping.
- It lets you implement forms with plain HTML.
- it lets your model objects be immutable, instead of being JavaBeans.
- It lets your model objects be responsible for their own validation.
- It lets multilingual apps have almost exactly the same style as single-language apps.
- It lets your apps assist in their own translation, by avoiding
ResourceBundleand using the database instead.
Some other important things about WEB4J:
- It's a full stack, and helps you build all parts of your app.
- It's focused on the task of creating a plain vanilla HTML interface to a relational database.
- It's about request/response, not components and events.
- It has no custom annotations.
- It has no custom XML files (only web.xml is used).
- It uses convention over configuration in several important ways.
- It requires a minimal toolset: JDK 1.5+, Servlets 2.4+, JSP 2.0+, JSTL 1.1+, and SQL.
- It doesn't depend directly on any third-party JARs.
- It has good protection against common hacks such as cross-site scripting, cross-site request forgery, and SQL injection.
How does WEB4J work?
This article will show you how you can implement a typical feature using the WEB4J framework. It uses code taken from the WEB4J tutorial application, called Electricity Tracker. This is a minimal application that tracks spending on electricity. It doesn't exercise all aspects of WEB4J, but it's suitable for learning about the framework's core features.
WEB4J vs. harmful idioms
My earlier JavaWorld article, "Four harmful Java idioms, and how to fix them," discusses some of the common Java programming problems that I tried to address in the WEB4J framework. In particular, the article discusses the advantages to using package-by-feature, and to preferring immutable objects over JavaBeans.
The code that you'll examine in this article does not encompass the full Electricity Tracker application; rather, it represents the implementation of a single, typical feature of the app. (In WEB4J, the term feature denotes a screen or page within an application.) Figure 1 is a screenshot of the Edit feature of Electricity Tracker, which will be the subject of analysis for the remainder of this article.
Figure 1. Electricity Tracker's Edit screen (click to enlarge)
It's very plain and simple, which is appropriate for a tutorial application. As you can see, the feature is a single page that includes a form and a listing. This single page implements five different operations:
- It can list existing records.
- It can add a new record, using the form.
- It can fetch an existing record, and populate the form with it, in preparation for editing.
- It can edit a record using the form, and
POSTthe changes (this operation forms a pair with the preceding one).
- It can delete a record.
This feature is implemented with three Java classes, a JSP, and an .sql file containing SQL statements:
- Spending.java: The model object
- SpendingDAO.java: The Data Access Object (DAO)
- SpendingAction.java: The action
- view.jsp: The user interface
- statements.sql: The underlying SQL for each operation
These items all live in the same directory/package. That particular directory belongs to the feature. The directory includes all items related to the feature, and only those items -- an example of package-by-feature, which is WEB4J's recommended packaging style. Over the course of the rest of this article, we will examine each of the items in this directory in turn.