whateverblog.
Introducing the xcc web framework
Wednesday, February 05, 2003 12:21 PM
OK, so I've been sitting on this thing long enough.

After a few years in web development I became frustrated with the cruftiness of front-end web development. It was especially tough for me in n-tier environments like J2EE, because the potental elegance of the business logic classes contrasts so starkly with the hackishness of JSP.

It's hard to explain what I mean when I say "cruftiness" and "hackishness". It's not just about code reuse. I think there is something fundamental about the way web front-ends need to run wide and shallow--many different code paths (i.e. pages or form targets), each of which is usually very short and uninteresting--as opposed to business logic, which often (not always) tends to run narrow and deep.

I've long since given up on coming up with a clean presentation layer development model.

Instead, my goal is to come up with a model that discourages the sprawling web/JSP/presentation layer from corrupting the abstract/Java/business logic layer. Let's start by examining some fundamental tasks your typical web app must perform (not an exhaustive list):

The idea behind xcc is that all of these "up-for-grabs" items need to be handled in a way that recognizes the sprawling nature of presentation layers while protecting the biz-logic layer from that sprawl. There are three fundamental tenets:

The first tenet is that the classes at the business logic layer should be completely divorced from the concept of HTTP, stateless requests, etc. Not only does this mean that you'd never pass HttpServletRequest (or HttpAnything, for that matter) into a business logic method; it means your business logic objects should not have to implement any presentation-level interfaces or extend any presentation-level classes, period. (This is specifically in response to the idea of using Struts Action classes to house your business logic--yuck.) This also implies that there should never be a one-to-one correspondence between web forms and business logic classes, unless it happens incidentally.

The second tenet is that many jobs are best expressed declaratively (including the above-mentioned parsing, validating, security, exception handling) but the most important job--actually invoking the business logic--needs to be expressed imperatively.

The third tenet is that to the extent possible, "compile-time" checking should be used to determine whether any errors have been introduced.

Lesser tenets: The system should be easily extensible. It should be easy to use. It should treat developer productivity as a high priority.

So, enough theory. In practice, xcc can be thought of as a layer of XML that serves as the glue and the fence between your JSP pages and your Java objects. It bears a little superficial resemblance to Struts' struts-config.xml, but the purpose and implementation are miles apart. Whereas the goal of struts-config is to do just enough work to hand off the request to an Action class, the goal of xcc is to get all of the dirty work out of the way and then invoke your business logic directly.

For example, if you have the following business logic classes...

public class User {
    public User(String firstName, String lastName, java.util.Date birthDate);
    ...
}

public class UserManager {
    public static void createUser(User user);
}

...and the following form...

<form action="/registerNewUser" method="POST">
    <input type="text" name="firstName">
    <input type="text" name="lastName">
    <input type="int" name="age">
</form>

...then you might have the following chunk of xcc XML:

<target path="/registerNewUser">

    <!-- Parse some request parameters and convert
        them to strongly typed xcc/Java variables, and
        also do some validation -->
    <params>
        String firstName : required
        String lastName : required
        int age : required, min=1, max=130
    </params>

    <java import="java.util.*,com.joecheng.user.*">
        // use a calendar to use age to calculate approx. birthdate
        Calendar cal = new Calendar();
        cal.add(Calendar.YEAR, age * -1);
        
        // just do it
        User user = new User(firstName, lastName, cal.getTime());
        UserManager.createNewUser(user);
        
        // save it on the HttpSession for later
        session.setAttribute("user", user);
    </java>
    
    <forward page="/registerThanks.jsp"/>

</target>

The actual XML vocabulary that xcc understands is not only not finalized, but completely user-definable. I'll demonstrate how in a future post, but for now, recognize that you can define your own custom XML tags to do whatever the heck you want, and in the meantime you have the ability to write inline Java code. To a reasonable extent, all of this is statically checked (note that the compiler in this case is not javac, but an xcc tool); so using the example above, if you changed the <params> chunk such that firstName was no longer a String, then the call to User's constructor would cause a compile-time error.

The end result is that your Java code stays clean, the ugly/repetitive tasks are at least somewhat cleaner (because they're declaratively defined in XML), and you can have a certain degree of confidence that at least the XML and your Java code is in sync. (Note that there is NO compile-time protection against the actual HTML forms changing. If you have any ideas on how that could work, let me know.)

I actually have this all working, but not yet packaged in such a way that I'm comfortable releasing it. If you're interested, contact me and stay tuned.