The important things about WEB4J are :
- it's an open source, full-stack Java web app framework
- it let's you build a browser front-end to a relational database
- it's small, and has a philosophy of deep simplicity and minimalism
- it lets you put SQL in plain .sql text files
- it lets you implement forms with plain old HTML
- it can significantly boost your productivity compared to other tools
- it allows package-by-feature, where closely related items are placed in the same directory
- it protects you from common hacks and helps keep you secure
- it has no custom annotations
- it has no custom .xml files (only web.xml is used)
- it has no object-relational mapping
- it has no dependencies on third party jars
- it requires a minimal toolset
- it can be used with any relational database that has a JDBC driver
- it lets your Model Objects be immutable
- it lets your Model Objects be responsible for their own validation (as they should be)
- it lets your Model Objects avoid the Java Beans anti-pattern
- it has nice building block classes
- it doesn't take you long to learn (and you don't need to buy a big fat book)
- it uses convention over configuration in several important ways
- it makes your application classes simple, and easy to maintain
- it requires minimal configuration
- it doesn't impose thread-safety constraints on your classes
- it lets multilingual apps have almost the same style as a single language app
- it lets your apps assist in their own translation
- it lets you place translations in the database
- it lets you avoid ResourceBundle and its defects
- it allows apps to share a fake system clock with the framework, so they remain in sync
- it starts up quickly
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 PhilosophyWEB4J stands aggressively for the following :
- simplicity and minimalism
- 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 :
- 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 SmallOne measure of complexity is size. Here is a listing of the number of documented classes in various tools :
|Name||Num Classes||Relative Size|
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 14% of the size of Ruby on Rails, which is widely lauded 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 one of the example applications. (Documentation comments are included in the line counts.)
|Item||Avg Lines||Relative Size|
|SQL file (.sql)||25|
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's recommended that those methods be moved into the Action class.)
WEB4J Requires A Minimal ToolsetYou use the following tools when building a WEB4J application :
- JSP 2.0+ and JSTL 1.1+
- some custom tags defined by web4j. These custom tags are minimal, and do not interfere with regular HTML. In particular, your forms still use plain HTML.
- web4j.jar, JDK 1.5+, and Servlets 2.4+
- standard SQL statements, placed in .sql text files (no database mapping of any kind)
WEB4J Uses Convention Over ConfigurationConvention 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. This allows painless construction of Model Objects out of Result Sets. 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?
Model Objects :
WEB4J Has Nice Building Block ClassesYour 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.
- Integer and int
- Long and long
- Boolean and boolean
WEB4J Enables Package-By-FeatureThe 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 HTMLForms 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 :
<form action='MemberEdit.do' method="post"> <w:populate using="member"> <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="IsActive" type="checkbox" value="true"></td> </tr> <tr> <td align="center" colspan=2> <input type="submit" value="Add/Edit"> </td> </tr> </table> </w:populate> </form>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 FilesThe 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 MappingWhen 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, well known SQL with alternate query mechanisms implemented in code (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 clearly 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.)
- ORM tools need to be ported to each new database vendor/version, while tools based on SQL don't have this problem.
- 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)
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 FilesThe 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 ConfigurationWEB4J 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 ConstraintsSome 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's still dangerously easy to simply forget to enforce it. Thus, there is the continual danger of introducing thread-related bugs.
WEB4J Simplifies Multilingual AppsWEB4J 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 TranslationThe 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 HacksWEB4J 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 ApplicationsWEB4J 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 example applications are provided as both a starting point and as a guide. It's recommended, though not required, that your applications be created by starting with an example app, and changing it gradually. If any items are undesired, then they can usually be removed 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 DrawbacksAll 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 has no items related to Ajax, Web Services, Messaging, or Dependency Injection.
- 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 Oracle 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:
|Charting||JFreeChart, Google Charts|
|File Upload||Commons FileUpload|
|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. Such migrations are almost always fairly minor, and there's never been a major rewrite of web4j. Its core ideas have remained intact from the beginning.
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.