Over a million developers have joined DZone.

Interview: John O'Hanley, Author of WEB4J Framework

DZone's Guide to

Interview: John O'Hanley, Author of WEB4J Framework

· Java Zone
Free Resource

Bitbucket is for the code that takes us to Mars, decodes the human genome, or drives your next car. What will your code do? Get started with Bitbucket today, it's free.

"WEB4J has been built slowly over several years. Lately, it has reached a maturity which makes it 'ready for prime time', and worthy of wide consideration." These words, written by WEB4J framework author John O'Hanley recently in a TSS article, unleashed a storm of reactions. Below, we find out more in an interview with John, about his framework, its purpose, and plans for the future.

  • First of all, can you give some background about yourself?

    I'm John O'Hanley and I have been programming for 10 years. I have specialized in Java web applications for 6 of those 10 years. I am the author of javapractices.com, and have operated the site since 2002. I have a bachelor's degree in Physics. I have also worked for a number of years in the back office of an investment dealer, where I became interested in computing for simplifying business operations. I live in Prince Edward Island, Canada.

  • John, you've created "yet another web framework"! Why, oh why?

    In a word? Pain. The existing tools I see out there don't seem to be focused on taking away the pain of the average programmer. Nor does there seem to be any minimal, full stack tool for building a simple browser front end to a relational database. It seems very worthwhile to have such a tool. And its intent is not to 'take over the world'. Its intent is to fill a small 'niche', to satisfy people who would like to do things in a particular way.

    I do sympathize with people's frustration with having so many tools to choose from, however. But at least its better than having too few!

  • In a nutshell, can you specify three reasons why I would use WEB4J?

    I would say these are the core reasons for considering WEB4J:

    • you are in pain
    • you are looking for a simpler way of doing things
    • you are not looking for an Ajax or RIA style of implementation

    If those criteria don't speak to you, then you shouldn't consider WEB4J. If they do speak to you, then you should look into it. And you should be a bit careful here: since WEB4J is a minimalist framework, you may find that some of its policies are not to your liking. I go to some lengths on web4j.com to make the drawbacks of the tool clear to people from the start. I do this because I think people appreciate the candour, and because I don't want them to become disappointed with it after it's too late (which is not in anyone's interest).

  • Do other frameworks not provide these features?

    As far as I know (and I may be dead wrong here), there are no other frameworks that:

    • let you use plain text .sql files
    • let you implement Model Objects as immutable objects, instead of JavaBeans
    • encourage you to place validation in Model Objects
    • encourage you to place all items related to a feature/screen in a single directory/package - JSP, Action, Model Object, DAO, and .sql file.

    Here is an illustration of what is meant by a plain text .sql file. It contains all the SQL statements used by a single feature/screen, and is placed in the same directory as the DAO that uses it:

    SELECT Id, Name, IsActive, DispositionFK
    FROM Member WHERE Id=?

    SELECT Id, Name, IsActive, DispositionFK
    FROM Member ORDER BY Name

    INSERT INTO Member(Name, IsActive, DispositionFK)
    VALUES (?,?,?)

    UPDATE Member SET Name=?, IsActive=?, DispositionFK=?
    WHERE Id=?


    SELECT COUNT(*) FROM Member WHERE IsActive=1

    Each SQL statement is placed in a block, and associated with an identifier, such as MEMBER_FETCH. Those identifiers are referenced in code, and act as a bridge between .sql files and code. To find typing errors related to such String identifiers, WEB4J will perform an extensive validation upon startup, to ensure that there is no mismatch between these identifiers and corresponding references in your code. Your app will not run if any mismatch in these identifiers is found. This protects you from hard-to-find runtime errors, by replacing them with 'startup-time' errors. In practice, this is almost as good as having compile time checking.

    Here is an illustration of a typical Model Object. Note that it is an immutable object, not a JavaBean. Also note that it is responsible for its own validation (see the validateState method).

    package hirondelle.fish.main.member;

    import hirondelle.web4j.model.ModelCtorException;
    import hirondelle.web4j.model.ModelUtil;
    import hirondelle.web4j.model.Check;
    import hirondelle.web4j.model.Id;
    import hirondelle.web4j.security.SafeText;
    import hirondelle.web4j.util.Util;
    import hirondelle.web4j.model.Code;
    import hirondelle.fish.main.codes.CodeTable;
    import static hirondelle.web4j.util.Consts.FAILS;

    /** Member of the Fish and Chips Club. */
    public final class Member {

    * Constructor.
    * @param aId internal database id, 1..50 characters, optional
    * @param aMemberName full name of member, 2..50 characters, required
    * @param aIsActive true if the member is usually a Fish
    * and Chips participant, false if the member is no longer
    * active; inactive members are no longer included on the RSVP list. Required.
    public Member (Id aId, SafeText aMemberName, Boolean aIsActive, Id aDisposition)
    throws ModelCtorException {
    fId = aId;
    fName = aMemberName;
    fIsActive = Util.nullMeansFalse(aIsActive);
    fDisposition = CodeTable.codeFor(aDisposition, CodeTable.DISPOSITIONS);

    public Id getId() { return fId; }
    public Boolean getIsActive() { return fIsActive; }
    public SafeText getName() { return fName; }
    public Code getDisposition(){ return fDisposition; }

    /** Intended for debugging only. */
    @Override public String toString() {
    return ModelUtil.toStringFor(this);

    @Override public boolean equals( Object aThat ) {
    Boolean result = ModelUtil.quickEquals(this, aThat);
    if ( result == null ){
    Member that = (Member) aThat;
    result = ModelUtil.equalsFor(this.getSignificantFields(), that.getSignificantFields());
    return result;

    @Override public int hashCode() {
    if ( fHashCode == 0 ) {
    fHashCode = ModelUtil.hashCodeFor(getSignificantFields());
    return fHashCode;

    // PRIVATE //
    private final Id fId;
    private final SafeText fName;
    private final Boolean fIsActive;
    private final Code fDisposition;
    private int fHashCode;

    private void validateState() throws ModelCtorException {
    ModelCtorException ex = new ModelCtorException();

    if ( FAILS == Check.optional(fId, Check.range(1,50)) ) {
    ex.add("Id is optional, 1..50 chars.");
    if ( FAILS == Check.required(fName, Check.range(2,50))) {
    ex.add("Name is required, 2..50 chars.");
    if ( FAILS == Check.required(fIsActive) ) {
    ex.add("Is Active is required. Inactive Members will not be RSVPed.");
    if ( FAILS == Check.required(fDisposition) ) {
    ex.add("Disposition is required.");
    if ( ! ex.isEmpty() ) throw ex;

    private Object[] getSignificantFields(){
    return new Object[]{fName, fIsActive, fDisposition};

    There are other items that are available in other frameworks. However, the combination of features for web4j is likely attractive to a number of developers:

    • full stack tool
    • small 'surface area' (only 82 classes)
    • no custom XML files (only web.xml is used)
    • no annotations
    • no object-relational mapping
    • lets you place translations in the database, and avoid the problems associated with properties files
    • helps protect you from common hacks (CSS, CSRF, Sql Injection)
    • forms implemented in plain HTML
    • ...and so on

  • Can you run us through a step-by-step quick start?

    I have created a Getting Started Guide. It covers the mechanics of getting the example application up and running. It was created for a Tomcat and MySQL environment. The example application is called Fish & Chips Club. Here is a typical screenshot (click for a full image):

    If you don't feel like downloading it, you can still examine the source code, on the web. The javadoc for the example app has links to underlying source code, JSPs, and .sql files. For example, this Action class links to its implementation (click on the class name, or a method name). It also links to its view.jsp and statements.sql files.

    As an example, you can look at all elements of this particular feature (a 'Resto' is a slang term for a restaurant):

    The idea here is that, initially, what's most important for the application developer isn't the API per se, but rather what their application is basically going to look like. A developer can get an excellent idea of the overall feeling of a tool, just by looking at an application that uses it.

    Going throught the FAQ is also of interest for beginners, since it helps you quickly evaluate the tool. It also includes links to example Actions, Model Objects, DAOs, and JSPs.

    Once the example app is up and running, the next step is to read the User Guide. Again, the example application is almost always a good illustrator of the API. So, you can scan its source code to view realistic use cases for almost all methods.

    The next step is to build something for yourself. For your first web4j app, it's highly recommended that you start with its example app, and gradually change it to your needs. It's always easier to start with something that is already working, instead of building from scratch.

    If features in the example app need to be removed, you can do so simply by deleting a single directory. This is possible only because the example app is implemented using package-by-feature, where all items related to a feature/screen are placed in a single package/directory - JSP, classes, and .sql file.

    It's also recommended that you create your own version of the example app, which better suits your needs. For example, you may want to use just a single database, not three. Or you may not care too much about multilingual apps. Once you create your own version of the example app, you can use it as a template for new applications, more closely customised to your needs.

  • Can you compare & contrast WEB4J with the following alternatives -- JSF, Struts, GWT, Wicket.

    That's a big question! It's also a dangerous one. I've built apps with Struts, but not with JSF/GWT/Wicket. (Some might take that as evidence of incompetence. In my defense, although I have not built any apps using JSF/GWT/Wicket, I have of course read their documentation, and have gotten an overall feel for what they are about.)

    Off the top of my rapidly balding head, I guess the most important aspects are :

    • is it full stack?
    • is it plain vanilla, or RIA/Ajax?
    • is it more about request/response, or about components?

    I believe this is accurate (please correct if false or misleading) :

    JSF Struts1 GWT Wicket WEB4J
    Full stack? No No No No Yes
    RIA-Ajax? Yes No Yes Yes No
    Components? Yes No Yes Yes No

    For those wishing a more detailed comparison, they might use the FAQ created for WEB4J, and attempt to answer the same questions for other tools. For those already familiar with another tool, this will provide a quick comparison.

  • Why is it named WEB4J?

    Simply out of imitation of other tools, such as log4j, oc4j, and so on.

  • When and how did you start working on this framework?

    I started it in 2002. I first began it because I felt that Struts was mediocre, and I was frustrated. I couldn't find a tool that came close to satisfying me. The first version was built in about 6 weeks. That version had some interesting things about it, but it was mediocre. I have worked on it steadily since then, slowly improving it. I took my time with its design, and I had the luxury of changing it constantly over a number of years, removing extraneous items, and always trying to simplify things from the point of view of the programmer. Only recently has it really become ready for wide consideration.

    It may sound silly and pretentious, but I would say that how I built it was influenced more by esthetics than by technical issues. When I think of good books I might recommend to those interested in API design, the first two books that come to mind are The Classical Theory of Fields by Landau and Lifshitz (electrodynamics and relativity), and The Nature of Order by Christopher Alexander (architecture). These books have absolutely nothing to do with coding, but everything to do with elegance, beauty, and simplicity.

    This might seem flaky to some people, but I think it's at the core of what WEB4J is about: it's not about the implementation details, it's about compassion for the experience of the application programmer. Other tools seem to almost always first presume a particular implementation style, and thus become locked into it.

    For example, object-relational mapping grows out of the desire to, in a sense, replace SQL with object graph navigation. Some front end frameworks are based on the idea that desktop style of programming is superior to plain request/response. And so on. Fundamentally, those kinds of tools are based on ideas, not feelings. In building WEB4J, I never first made any assumptions about implementation ideas. Rather, I listened to the code, looked for the pain points, and tried to remove the pain points in such a way that the application programmer would have a deep feeling of simplicity, clarity, and elegance.

  • Are there others involved in the project?

    I am the sole developer. There are 82 classes in the public API, which doesn't seem excessively large for a single person.

  • What's the timeline for upcoming releases and what do you expect them to provide?

    Currently, small updates are released about every 5 weeks. The focus of releases is not to focus on new features, but on fixes and improvements. Since it is a minimalist framework, I need to be a bit...paranoid about adding things. When considering adding something new, I always repeatedly ask myself the question "does this really need to be in the core?" This is similar to Joshua Bloch's dictum "When in doubt, leave it out".

    In addition, I can sometimes improve the example application, without altering web4j itself.

    Some ideas I'm currently considering:

    • loosen the coupling between the data layer and the servlet environment, such that a standalone unit tests can be written for DAOs. (This is a priority issue.)
    • the example app uses a login filter, which places user info into session scope upon login. Should that be in the web4j core?
    • Data ownership restrictions per user - this is easy to implement, using WHERE ownerid=? kinds of clauses in SQL. Can web4j make that easier somehow?
    • Model Objects in the example app have a private getSignificantFields() method, used by equals and hashCode. Is it better to just use a private field instead?
    • Should primary key fields should be included in equals and hashCode? Does it matter?
    • for Model Objects, is it ever acceptable to not override equals and hashCode?

Bitbucket is the Git solution for professional teams who code with a purpose, not just as a hobby. Get started today, it's free.


Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}