An (Almost) CPU-Free MVC Pattern with Ajax Blog

Version 2


    The Web is switching slowly from the mainframe computing paradigm (static HTML pages generated on the server) to a high-performance computing (HPC) paradigm, where the computing power is distributed along the network. This shift gained its momentum with the explosion of Ajax applications.

    Ajax is an exciting technology. However, programming Ajax means hard work, mainly because of the asynchronous programming model and XML parsing between different environments or programming languages. Ajax helped the Web to be faster by reducing the CPU load on the servers for tasks that are mostly cosmetic and have almost no interference in the application business logic.

    A logical next step is to use more of the CPU power of web clients, making the dull web browser into an more powerful fat client. We already share the control logic between the server and the client; how hard would it be to also share the views and even the models?

    The answer is, not that hard! To solve the model sharing, all that is needed is a simple mechanism to get the data from the server into the client in a transparent way (and this is what Ajax is all about). The view problem can be addressed within the web browser itself; today's browsers include an XML Stylesheet Processor (XSLT). XSLT is used on the server side to generate dynamic content; we can relieve the server of that job if we do it on the client side. To control all of this, we need some programming language, and again inside our browsers' JavaScript has been a standard feature for quite a long time.

    It is clear we can do it, but why we should do it is the next question to arise. Everything works fine with the current paradigm, so why make a change? To me, it is clear that this change should be made for the same reasons we started using Ajax in the first place: web applications were slow, suffered from network latency, etc. Ajax brought the data layer to the web browser; now we bring the layout layer to the web browser, too. By doing this, we get a clear separation of code and data, and simplify the code necessary for displaying a view in the browser by using XSLT transformations in a template instead of a big HTML file.

    From here we have less code, easier deployment, and easier maintenance of the application. Surely we will have a win-win scenario. The developer wins by having to code less, saving time and money, and the user wins with faster response times and less network data to transfer.

    The RAJAX Project

    RAJAX is a project that set out to test this idea. At its heart it is a Java library, a tag library, and two JavaScript files. The tag library with the Java library will address the Model problem just described. It works by using runtime reflection to take any class that extends the RAJAX base class and transform it into an Ajaxified JavaScript object. For example, consider the following Java class:

    package demo; import java.sql.*; import java.util.*; import javax.naming.*; import javax.sql.DataSource; import; public class ShoppingItem extends RAJAX { private DataSource ds; /** * Creates a new instance of ShoppingItem */ public ShoppingItem() { try { Context initContext = new InitialContext(); ds = (DataSource) initContext.lookup( "java:/comp/env/jdbc/rajaxDB"); } catch (NamingException ex) { ex.printStackTrace(); } } public Map findById(String id) { try { Connection conn = ds.getConnection(); PreparedStatement pstmt = conn.prepareStatement( "SELECT name, description, price FROM " + "items WHERE id = ?"); pstmt.setString(1, id); ResultSet rs = pstmt.executeQuery(); Map item; if( { item = new HashMap(); item.put("name", rs.getString("name")); item.put("description", rs.getString("description")); item.put("price", rs.getString("price")); } pstmt.close(); rs.close(); conn.close(); return item; } catch (SQLException ex) { ex.printStackTrace(); } return null; } }

    RAJAX will generate the following corresponding JavaScript object:

    function ShoppingItem() { var sU=null; var sP=null; var cN='ShoppingItem'; var oN='/rajax/demo.ShoppingItem.rajax'; this.findById = function(p0) { if(typeof(this.findById_Callback) == 'undefined') this.findById_Callback=XMLHttp.defaultCallback; if(Rajax.isString(p0)) { var u=oN+'?m=findById'; var p='p='+Rajax.toJSON(p0,true); XMLHttp.exec(u,p,false,sU,sP,this.findById_Callback); } else this.testInt_Callback('Bad Request',400); }; }

    There is no need to write configuration files; all the developer needs to do is create a Java class that extends RAJAX, and everypublic method with annotation will be mapped to a method with the same signature in the generated JavaScript object. The original code is a simple POJO; this helps the developer to focus on the problem and avoid other concerns. Also, since we are handling POJOs, testing is easier (usingJUnit for example), since there is no need to deploy the code before testing. Testing can start at the same time we are coding our RAJAX objects.

    Note that the generated JavaScript object makes use of two JavaScript objects: Rajax and XMLHttp. Starting from the end, XMLHttp is a simple abstraction of the XMLHttpRequest object that will make it easier to expand the library to other browsers. At the moment, this object has been tested with success on Microsoft Internet Explorer 6, Microsoft Internet Explorer 7, Mozilla Firefox 2, and Opera 9. With time and other platforms to test, the browser platform is supposed to be expanded. The Rajax object contains some helper functions to cast variables and encode and decode JSON messages back to and from the back-end server.

    These abstractions may seem like re-inventions of the wheel, with other projects like Sarissa, which is about 28K of source code (62K with extras). RAJAX keeps it simple with only the basic features within 12K (21K with the MVC framework).

    One of the goals of the project was to write an Ajax library that would require no configuration. While this is somewhat true, there is one thing that needs to be configured; you need to instruct your JSP/servlet container to handle the RAJAX requests. This is done using a special Servlet in thewebapp. This servlet will be a dispatcher that will map a request to a Java object and if (and only if) that object is an instance of the superclass, it will instantiated and the requested method executed. This is what the web.xml file should look like:

    <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="" xmlns:xsi="" xsi:schemaLocation=""> <servlet> <servlet-name>RajaxDispatcher</servlet-name> <servlet-class></servlet-class> </servlet> <servlet-mapping> <servlet-name>RajaxDispatcher</servlet-name> <url-pattern>*.rajax</url-pattern> </servlet-mapping> ... </web-app>

    Implementing a Model-View-Controller (MVC) Pattern

    The title says this pattern is "almost" CPU-free. "Almost" because RAJAX will implement it entirely on the client browser, so no CPU is used on the server for that computation. There are six classes available to the developer (Figure 1).

    Object Model of the JavaScript MVC Framework
    Figure 1. Object model of the JavaScript MVC framework

    Of these classes, the developer typically only cares about three:

    • Nimble: The main MVC class. It is called "nimble" because it tries to be as simple as possible.
    • NimbleModel: The model representation for the MVC.
    • NimbleView: The view representation for the MVC, with methods to render in the browser and other important functions such as event handling.

    Putting Everything Together

    As with any software program, the application needs an entry point. In the case of RAJAX, it is a HTML page. In the above example, a simple display/edit ShoppingItem is to be implemented. The user enters the application and sees the shopping item in the display view (Figure 2).

    Display view
    Figure 2. Display view

    Once the edit view is clicked, a form will enable its editing (Figure 3).

    Edit view
    Figure 3. Edit view

    When switching back to the display view, the data will reflect the changes (Figure 4).

    Display view with updated content
    Figure 4. Display view with updated content

    The application entry HTML is just a plain JSP page with the inclusion of the MVC tag library:

    <%@page contentType="text/html" pageEncoding="UTF-8"%> <%@ taglib uri="" prefix="rajax" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ""> <html> <head> <title>JSP Page</title> <rajax:object className="demo.ShoppingItem" /> <rajax:mvc controller="/js/controller.js" /> </head> <body onLoad="Rajax.enableThrobber(Rajax.THROBBER_IMG); startUp()"> <h1>RAJAX Nimble MVC</h1> <div id="content"></div> </body> </html>

    The display view is a simple XML stylesheet file:

    <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl=""> <xsl:template match="Item"> <div> <h3><xsl:value-of select="name" /></h3> <p><xsl:value-of select="description" /></p> <p><em>Price: <xsl:value-of select="price" /></em></p> <p><a href="#" id="editLink">edit</a></p> </div> </xsl:template> <xsl:template match="text()" /> </xsl:stylesheet>

    The edit view is another simple XML stylesheet file:

    <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl=""> <xsl:template match="Item"> <form method="post" action="#" class="editForm"> <h3><input id="Item/name" type="text" value="{name}" /></h3> <p><textarea id="Item/description"><xsl:value-of select="description" /></textarea></p> <p><input id="Item/price" type="text" value="{price}" /></p> <p> <a href="#" id="displayLink">display</a> <input type="submit" value="ok" /> </p> </form> </xsl:template> <xsl:template match="text()" /> </xsl:stylesheet>

    Earlier in this article, we defined a model with the RAJAX objects and a view using the XSLT stylesheets. To complete the MVC framework, only the business logic is missing. The controller is a JavaScript file as stated before; if one pays particular attention to the base application HTML, there was an extra JavaScript script,/js/controller.js. This script is where all the business logic is: it will handle all the event handling from the view, execute actions against the model, and finally update the view.

    Before the controller can handle the events, one needs to attach them to the view. To do this, RAJAX uses the Observer pattern, since it is also related to the way browsers handle events on theDocument Object Model. The code for our example is:

    var data,view,edit; function startUp() { // load the XSLT files view = Nimble.loadView('views/display.xsl'); edit = Nimble.loadView('views/edit.xsl'); // RAJAX will get the data from the DB data = (new ShoppingItem()).findById('tomato soup'); // attach the event handlers view.attachEvent('editLink', 'click', function () { edit.render('content', data); }); edit.attachEvent('displayLink', 'click', function () { getData(); }); // render the initial view view.render('content', data); } function getData() { view.updateModel(data); view.render('content', data); }

    The attachEvent function takes three arguments: the first is the DOM element to which the MVC framework will attach the event; the second is the event type, (one of blur,focus, contextmenu, load,resize, scroll, unload,click, dblclick, mousedown,mouseup, mouseenter,mouseleave, mousemove,mouseover, mouseout, change,reset, select, submit,keydown, keypress, keyup, orerror). Of course, not all events can be attached to all DOM elements. For example, the load event can only be attached to Document elements, and thesubmit to Form elements. The last argument is the notify function; since JavaScript has closure support, the API is simplified by not having the need to write a specific Observer object.

    Final Considerations

    In this example, no Ajax-specific code was (manually) created and no CPU is used on the server to render the user interface. The load is distributed between the server and the client, and the client will have all the load for user interface processing.