Overview

Great software requires a fanatical devotion to beauty.
- Paul Graham

The important things about WEB4J are : Graphic

In the interest of not wasting your time, please see below for a listing of its drawbacks.

If you can accept the above, then WEB4J is often the best tool for the job of creating browser interfaces to databases. Because of its deep simplicity, it allows markedly faster delivery of applications.

WEB4J Has a Clear Philosophy

WEB4J stands aggressively for the following :
  • simplicity and minimalism
  • concision
  • reducing the pain of programming in Java
  • showing compassion for the typical programmer just wanting to get their work done
  • using tools that have been proven over a long period of time
  • treating the data as king, not the code

WEB4J stands aggressively against the following :

  • complexity
  • verbosity
  • requiring the programmer to be an uber-geek
  • using fashionable-but-unproven programming techniques
  • assuming the programmer has a lot of time available to learn new tools
  • treating the database as secondary to the code
  • forcing the programmer to learn new ways to do the same old thing

WEB4J is Small

One measure of complexity is size. Here is a listing of the number of documented classes in various tools :

NameNum ClassesRelative Size
WEB4J 94Graph
Servlet/JSP API 96Graph
Rails 346Graph
Tapestry 706Graph
Struts 720Graph
Rife 1,110Graph
JEE 1,188Graph
Spring 2,464Graph

As you can see, most tools have a size that might be described as "rather large". Note that WEB4J has the smallest surface area of any tool in its class. It's a quarter of the size of Ruby on Rails, which is widely recognized for its ease of use. Correspondingly, it takes a shorter time to learn WEB4J, and to implement features with it.

Not only is WEB4J compact, but, more importantly, applications built with WEB4J are compact as well. Here are some typical line counts per feature, taken from a cross section of several features in the Fish & Chips Club example application. (Documentation comments are included in the line counts.)

ItemAvg LinesRelative Size
SQL file (.sql)25Graph
Presentation (.jsp)108Graph
Total133 
Model (.java)111Graph
Action (.java)144Graph
DAO (.java)46Graph
Total301 

In general, your code will only be roughly twice the size of the non-code elements of your application.

(DAOs are often short and simple, consisting only of a few single-line methods. In such cases, it is recommended that those methods be moved into the Action class.)

WEB4J Requires A Minimal Toolset

You use the following tools when building a WEB4J application :
  • views use HTML/CSS, JSP 2.0+/JSTL 1.1+, plus some custom WEB4J tags. The custom tags are minimal, and do not interfere with regular HTML. In particular, forms use plain HTML. (Note that WEB4J does not require javascript.)
  • data access objects (DAOs) reference standard SQL statements placed in .sql text files. There is no database mapping of any kind.
  • in general, your code uses web4j.jar, and the following commonly used tools : JDK 1.5+ and Servlets 2.4+. (EJBs are not used.)
In short, you use existing, well known tools appropriate for each layer. In addition, there are no other dependencies on third-party tools, other than widely used tools published by Sun Microsystems.

WEB4J Uses Convention Over Configuration

Convention over configuration is used to reduce the effort needed to create and maintain your application. It is used in the following ways :
  • a default naming convention maps request URIs to corresponding Actions. See RequestParserImpl.
  • in JSPs, a naming convention for the names of input controls allows for automatic mapping between controls and corresponding getXXX methods of a Model Object. This convention allows painless population of forms with data. See RequestParameter.
  • an ordering convention for the columns of a ResultSet is used to map columns to corresponding parameters in a Model Object constructor. See the overview of the database package.
  • an ordering convention is used for SQL statements with '?' parameters : when your DAO passes values for such parameters to the framework, the order of the passed parameters matches the order of the '?' items appearing in the underlying SQL statement. See Db.
  • where possible, default implementations of required interfaces can be used with no effort on the part of the application programmer. If there is no default implementation, or if the default implementation is overridden, then a naming convention for the package/class can be used. See BuildImpl.
  • the set of acceptable RequestParameters for each Action are found automatically by the framework upon startup, with no configuration required. See ApplicationFirewallImpl.

WEB4J Application Classes Are Usually Simple

The quality of a framework can be measured by examining the concrete classes which use it. Questions to ask of a such a class include :

  • is it fairly simple and compact?
  • does it read at a high level of abstraction?
  • does it read clearly?
WEB4J performs well in this regard. Here are some examples of typical implementations :

Model Objects :

Data Access Objects (DAOs) :

Actions :

WEB4J Has Nice Building Block Classes

Your application's model objects are built out of simpler classes such as Integer, BigDecimal, and so on, which WEB4J refers to as building block classes. The framework supplies building block classes appropriate to most web apps. Included among these are several custom building block classes designed to make your life significantly easier :
  • SafeText is the recommended replacement for String, since it protects you from Cross-Site Scripting (XSS) attacks.
  • Decimal is the recommended replacement for BigDecimal, since it's simpler to calculate with. It also corresponds nicely to the DECIMAL data type used in databases. Decimal is meant mainly for monetary amounts.
  • Id is specifically for identifiers, and helps them stand out more clearly in your code.
  • DateTime is recommended for dates and times. Although masochists can still use java.util.Date if desired, WEB4J recommends DateTime as a replacement.
The other building block classes are simply taken from the JDK :
  • String
  • BigDecimal
  • Date
  • Locale
  • TimeZone
  • Integer and int
  • Long and long
  • Boolean and boolean

WEB4J Enables Package-By-Feature

The package-by-feature technique is a powerful method for organizing your code. It has many advantages, and is superior to the package-by-layer style so often promoted by other tools.

All items related to a single feature can usually be isolated in their own directory/package - Action, Model Object, DAO, plain text SQL statements, and even the JSP. This gathering together of all items related to a single feature (and only that feature) is extremely satisfying. It allows the following goodness:

  • say goodbye to tedious navigation from directory to directory to change closely related items - everything is in one place
  • it allows deletion of unwanted features simply by deleting a single directory
  • it allows some items to reduce scope from public to package-private. (Minimizing scope is a central idea of lasting value in programming, and should always be aggressively pursued.)
  • in many source-code control environments, it allows developers to see immediately if another developer has checked out an item related to their current work

WEB4J Forms Use Plain HTML

Forms are an important part of web applications. Most frameworks implement forms with a large set of custom tags, that are different for each framework. These are meant to replace the existing, well known HTML controls such as <INPUT>, <SELECT>, and so on. That style is not the best, since it forces you to learn a new set of tools to do something you already know how to do - build an HTML form. This is neither necessary nor desirable.

In WEBJ, the typical form looks like this :

<w:populate using="member">
<form action='MemberEdit.do' method="post">
<input name="Id" type="hidden">
<table align="center">
<tr>
 <td><label>Name</label> *</td>
 <td><input name="Name" type="text"></td>
</tr>
<tr>
 <td><label>Is Active?</label></td>
 <td><input name="Is Active" type="checkbox" value="true"></td>
</tr>
</w:populate>
<tr>
 <td align="center" colspan=2>
  <input type="submit" value="Add/Edit">
 </td>
</tr>
</table>
The population of the form is done by wrapping a normal HTML form with a single <w:populate> tag - that's it. There are no custom tags for the various kinds of form controls. The WEB4J mechanism is the simplest possible way of populating forms.

WEB4J Has No Custom XML Files

The only XML file required by WEB4J is the deployment descriptor, web.xml. Whereas many other tools force you to spend significant time coding in XML, WEB4J was explicitly designed to let you avoid it.

In a WEB4J app, you implement features using JSPs, Java, and text files containing SQL statements. That's it. If you are looking for "XML hell", you won't find it here (but you can certainly find it in many other tools).

WEB4J Doesn't Use Object Relational Mapping

When building DAOs, you may use either WEB4J's data layer, or any other persistence tool of your choice. By design, WEB4J's data layer doesn't use object-relational mapping (ORM). For the majority of cases, implementing a DAO method with WEB4J's data layer will be more compact than an ORM implementation. The minority case in which an ORM tool may result in less coding effort and increased elegance is that of building an extensive object graph.

However, building an extensive object graph is the exception, not the rule. The majority of pages in a typical application relate not to relatively complex views of data, but to relatively simple ones. The reason for this is that it matches how people think, and how they work - on one specific thing at a time. Yes, large summary pages are very often part of an application, but such pages are usually the exception, not the rule.

There are some serious drawbacks to object-relational mapping :

  • it replaces standard SQL with alternate query mechanisms (reinventing the wheel).
  • it makes it difficult to debug and tune SQL, since the SQL is generated behind the scenes.
  • it often forces you to code in XML, which is inherently more difficult to work with.
  • its details are often non-trivial to learn and use.
  • it's often tedious and verbose.
  • it destroys the clear separation between application layer and data layer.
  • it violates encapsulation of database secrets, since the application layer repeats information that's usually hidden in the database: column types, nullity, key information, and so on. (SQL statements never explicitly include such information.)
In addition, ORM tools are sometimes invasive, in the sense of restricting the implementation of your Model Objects in certain ways, such as:
  • perhaps requiring you to add a no-argument constructor
  • perhaps requiring your class to be non-final
  • perhaps requiring you to add setXXX methods (roughly doubling the number of methods)
  • perhaps requiring you to add annotations
  • perhaps requiring you to implement Serializable (doing this correctly is non-trivial)
These restrictions don't exist for the benefit of your Model Object. Rather, they exist because the implementation of the ORM tool needs them in order to function. That is, they represent "leaks" of the ORM tool into your data model. These restrictions are particularly annoying since they may not allow you to design your own classes as immutable objects. This is a serious defect since immutable objects have so many compelling benefits.

If you choose to use WEB4J's data layer, then these restrictions don't exist. The only restriction for WEB4J Model Objects is that the constructor must throw a ModelCtorException, and that restriction has nothing to do with persistence. Rather, it's related to an important problem each Model Object should solve: the problem of validating state, and communicating related errors to the caller.

WEB4J Uses Plain .sql Text Files

The WEB4J data layer uses regular SQL statements, stored in ordinary .sql text files. Here is an example showing the basic idea. This style has many benefits.

WEB4J Has Minimal Configuration

WEB4J has no .xml configuration files, other than the familiar web.xml file (used for a number of initialization settings). In addition, it requires the application programmer to supply concrete implementations for several interfaces. Default implementations are supplied for most of these items (no reasonable defaults are possible for the others). See BuildImpl for details.

WEB4J Doesn't Impose Thread-Safety Constraints

Some tools force some application classes to be thread-safe. In Struts 1, for example, Action classes must be thread-safe. Forcing such a requirement on an application programmer is inappropriate :
  • implementing thread-safety is not trivial, especially for novice programmers
  • even if the programmer is experienced with the issue of thread-safety, it is still dangerously easy to simply forget to enforce it. Thus, there is the continual danger of introducing thread-related bugs.
WEB4J makes no requirements of thread-safety on the application programmer.

WEB4J Simplifies Multilingual Apps

WEB4J translation tools allow the implementation of a multilingual application to look almost the same as that of an ordinary single language application. All Actions, Model Objects, and DAOs are exactly the same in both cases.

The only differences are in JSPs - and even there, the differences are relatively minor. The markup retains the overall look of a single language application. It remains legible, and appears natural to the eye. This is because the WEB4J translation tags are designed explicitly to be non-invasive. For example,

  • translation of large chunks of markup can be often be implemented by wrapping the 'single language' markup in a TextFlow tag
  • translation of all tool tips (TITLE attributes) can be done by placing a single Tooltips tag in a template JSP

WEB4J Allows Applications To Assist In Their Own Translation

The WEB4J translation mechanism can be backed by a database (recommended), or by any other means, including properties files. If a database is used to store translations, then applications can assist in their own translation.

The general idea is that, during development, all user interface items needing translation can be collected simply by exercising the application. This is done with a Translator implementation that records items having missing translations. Translations for such items can then be added later, through the browser, using screens created for that purpose, just like any other data. (Please see the WEB4J example application for further illustration of this useful technique.)

WEB4J Protects You From Common Hacks

WEB4J has tools to protect you from common hacks :
  • SafeText models free-form user input, and automatically escapes special HTML characters (by default). This protects you against XSS attacks. It also allows you to forget about repeatedly escaping special characters in the view. By default, String cannot be used to model free-from user input. If you need to allow String as a "building block" class, then you must explicit permit it using a setting in web.xml.
  • CsrfFilter protects you against CSRF attacks.
  • ApplicationFirewallImpl checks that all incoming parameters have known names, and that their values satisfy basic sanity checks.
  • SQL Injection attacks are very unlikely when using the WEB4J data layer. When using an SQL statement defined in an .sql file, such attacks are impossible. When creating a dynamic WHERE clause in code, such attacks are very unlikely because WEB4J validates the WHERE clause, ensuring that '?' placeholders are being used instead of literal values.
  • UntrustedProxyForUserId and FetchIdentifierOwner cooperate to help you avoid Insecure Direct Object Reference problems.
  • SpamDetector helps you prevent spam from entering your database.

WEB4J Has Example Applications

WEB4J has 3 example applications :
  • a minimal tutorial application, which gives you a brief overview of the tool.
  • an intermediate-sized example application called Predictions, built in the style of many public web applications, with access control based on user, not on role.
  • a full-sized example application called Fish & Chips Club, built in the style of many intranet applications, with access control based on role. This application exercises almost all of the WEB4J API, and could be considered an informal "reference implementation".
The Fish & Chips Club has these modules, typical for a business application :
  • a main business domain
  • access control - adding users, changing roles, resetting passwords
  • user preferences - changing language, changing passwords
  • webmaster tools - diagnostics, logging config, performance stats
  • translation - adding and editing translations of text appearing in the user interface

The Fish & Chips Club example application is provided as both a starting point and as a guide. It is recommended, though not required, that your applications be created by starting with the example, and changing it gradually. If any items are undesired, then they are simply removed by deleting directories (and any links from menus). This is only possible because of the package-by-feature style recommended by WEB4J. (See the User Guide for more information.)

This approach is consistent with the following :

  • destroying things is easiest of all
  • next, changing something that already exists is usually easier than starting with nothing
  • finally, starting with nothing usually takes the most time

In any case, the classes in the example applications are always effective guides.

Other WEB4J Features

  • action classes are usually automatically mapped to URIs, without any manual configuration (see RequestParserImpl)
  • several abstract base classes are provided as templates for common action classes (see the subclasses of ActionImpl)
  • Report helps you build reports quickly
  • ModelUtil helps you implement equals, hashCode, toString, and compareTo in your Model Objects
  • Check and Validator implement many common validations, and can be extended with validations particular to your application
  • ModelFromRequest and Db allow rapid creation of Model Objects from incoming requests and ResultSets, respectively.
  • messages to the user can survive a redirect, allowing the application to inform the user of successful edits to the database
  • settings in web.xml are used to establish application-wide default formats for dates and currencies
  • the Db class is the main tool for implementing DAO methods
  • applications can easily use multiple databases, when required
  • upon startup, WEB4J can optionally perform a test precompilation of all SQL statements. This is highly beneficial since it detects errors at startup-time instead of at run-time. (Not supported by all database drivers.)
  • if the database is down when the container starts, your app will attempt to recover with each incoming request. As soon as the database is up, your web app will start functioning normally.
  • the webmaster is emailed if an error occurs, or if your application's response time exceeds a configured number of seconds. In the case of an error, the email includes extensive diagnostic information, including a stack trace
  • upon startup, WEB4J will scan your Model Objects for possible Cross-Site Scripting vulnerabilities
  • and other features as well...

WEB4J Has Drawbacks

All tools have drawbacks and trade-offs.

How many times have you become disillusioned with a tool, but only after you have invested a lot of time and effort in it? The purpose of this section is to make sure that doesn't happen to you with WEB4J, by listing items you should know about.

Tools which don't clearly state their own drawbacks don't have your best interests in mind.

WEB4J's philosophy is one of deep minimalism. Thus, WEB4J may not include things which you might feel should be there:

  • it has no library of fancy user interface widgets. It's likely not appropriate to use WEB4J for building Rich Internet Apps - although you may still like its data layer.
  • it has no items related to Ajax, Web Services, Messaging, or Dependency Injection.
  • it doesn't generate JavaScript.
  • it doesn't have a CAPTCHA mechanism.
  • it has no components, events, listeners, and so on (as in desktop programming).
  • it uses JSP/JSTL, and alternative tools such as Velocity aren't supported.
  • it uses HTML, not XHTML.
  • its form population mechanism doesn't include a way of changing the appearance of controls containing erroneous user input, nor for associating specific error messages with specific controls.
  • for spreadsheet-style forms, no parsing of request parameter names to extract numeric row identifiers is performed.
  • its data layer is most suited to simple domain models, where 1..N relations between classes are not explicitly hard-coded. When needed, such relations can always be implemented implicitly in a feature's Action, as opposed to explicitly in the domain model. Of course, if you choose some other persistence tool, then this drawback may not apply.
  • when displaying an existing Model Object (built from an SQL statement) in a form, the data is formatted by the <w:populate> tag using application-wide format settings defined in web.xml, with no override. Some may find this pleasing, while others may find it an onerous constraint.

You May Need Third Party Tools

WEB4J doesn't depend on any third party tools or jars other than those published by Sun and expected in a servlet environment (Servlet API, JSP/JSTL). Thus, adding third party tools to your WEB4J application may well be necessary. Examples of tools you might have to add:

TaskExample Tool
Unit TestingJUnit
Feature TestingHttpUnit
Build Scripts Apache Ant
File Upload Commons FileUpload
Charting JFreeChart, Google Charts
PDF Generation iText
Microsoft File Formats Apache POI

The toString, equals, and hashCode Methods Have Some Repetition

WEB4J provides good tools for implementing toString, equals, and hashCode. For each Model Object, the implementations of these methods vary in details, but their general technique or style is always the same. It would be very satisfying if these "general techniques" could be defined in one place.

There doesn't seem to be a satisfactory way of doing this with standard techniques of object programming. You may want to try and remove that repetition by using aspect programming tools such as AspectJ. Using JDK 5 annotations may be another option.

Backwards Compatibility Issues

We apologize for making occasional changes that are not backwards compatible. Such changes occur only when deemed necessary for the long term quality of the tool, in the direction of increasing elegance and simplicity. Such changes are never large scale, but it doesn't take much to break backwards compatibility. If you need to update an existing WEB4J app to a new version of web4j.jar, you may need to perform some 'migrations' to the new way of doing things, using the Version History to find items that may affect you.

You should evaluate the recent Version History to see if you are comfortable with the size and frequency of such changes.

It's true that there isn't much positive to say about such changes, except for this: it allows the tool to remain aggressively minimalistic, and increases its overall elegance.

"There's a natural law in programming language and API design : as backwards compatibility increases, elegance decreases."
- Bill Venners, Artima.com
Given the minimalist philosophy of WEB4J, it seems appropriate to trade some backwards compatibility problems for increased elegance and simplicity. Some will not be comfortable with this.