oreilly.comSafari Books Online.Conferences.


Introducing TrimPath Junction

by Jack Herrington and Steve Yen

The arrival of technologies like Google's Gears and Adobe's AIR marks a shift in how we view the relationship between the web browser and the web server. Now we can develop complete applications in JavaScript on the client, hold the data on the client, and then synchronize the data, and even the code, later with the server as needed.

To match this changing landscape, we need a fresh new look at the toolset we are using. Steven Yen has done that with his amazing TrimPath Junction framework. Junction is an all JavaScript framework that closely models the Ruby on Rails model-view-controller design pattern and implementation. And with the help of the Helma JavaScript web server, it runs the same code both on the client and on the server. Exactly the same code, in fact.

The framework not only handles the basics of rendering pages (using JavaScript templating), but it also handles data and code synchronization with the server, local client caching using Google Gears, model versioning, and much more. It's an amazingly complete solution for an entirely new model of web development.


To show it off, we are going to build a simple contact maintenance application. And to get started with the development, we first need to download the example code, which includes the TrimPath Junction framework, and install that somewhere locally.

Then, depending on the operating system, you can start the Helma web server using the start.bat batch file (on Windows), or the shell script on Linux or Macintosh OS X.

You may need to do some tweaking of the Helma configuration file to get it properly working on your system, depending on what web servers you may already have running. The Helma configuration file is called helma.conf and is located in the scripts directory.

Running the Contact Application

Once the Helma process is up and running, we can run the contact application. On my machine, this meant going to http://localhost:8080/engines/100/apps/contactApp. But your URL may vary depending on the settings in the helma.conf file. The above URL executes the contact application within the Helma server. So, each click I make in the contactApp sends a normal, full HTTP request to the Helma server, and the browser renders the returned HTML page as you'd expect.

Instead, if I wanted to run the contact application completely within my web browser, I would use the URL of http://localhost:8080/engines/100/apps/contactApp;start. That lets the application execute against my browser-local Gears RDBMS, or against a browser-local, memory-only database, if I don't have Gears installed. Since the contact application is all JavaScript, it runs just fine completely within the web browser.

In either case, when I use either URL, I would see the page as shown in Figure 1, if everything is installed properly.

The empty contact list page
Figure 1. The empty contact list page

This page shows the list of contacts in the database. It's empty now because there are no contacts in the database. But there is a handy link to get us to the page on which we can create.

If you are familiar with Rails, then this is the equivalent of the index page from the scaffolding. In fact, as we will soon see, it's the Junction version of the scaffolding that we will be working with.

The Schema

But let's backtrack for a second and look at the application. The contact application starts with a model. This model is a migration, as shown in Listing 1.

    { up: function() {
          column('first_name',     'varchar(100)'),
          column('last_name',      'varchar(100)'),
          column('address',        'varchar(300)'),
          column('phone',          'varchar(100)')
      down: function() {

Just like Rails, there is a function for migrating up to this version, which creates a new table with the fields for each row. And there is a down function, which in this case just deletes the table.

Besides the variable types, which in this case are really standard, there is nothing vendor- or database-specific about the schema--which is great because this way Junction can take this schema and use it on the server side to hold it in a SQLite database, or on the client side in Google Gears' SQLite database.

The Home Controller

With the schema in hand, it's time to create the home controller. This is the landing page for the application. But in this case the home controller only has to forward us onto the index page of the contact controller. This home controller is shown in Listing 2.

    HomeController = function() {}

    HomeController.prototype.start = function(req, res) {
        res.redirectTo('contact', 'index');

A controller, in Junction parlance, is just another object. It responds to many different messages--in this case, the start message. And the start message redirects the client to the index method on the contact controller.

The TrimPath Junction download comes with its own autogenerated documentation that you can use to aid you in developing applications for it.

The Contacts Controller

Amazingly, there is even less to the contacts controller than there was to the home controller. In fact, there is almost no code at all--just an invocation of the scaffold function, which sets up the basic create, read, update, and delete (CRUD) set of pages.

The contacts controller code is shown in Listing 3.

    ContactController = function() {}

    scaffold(ContactController, 'Contact');

Pretty crazy, huh? Well, there is a little more. Since this is just the controller, there also has to be a model and a view to go along with it.

The model is pretty simple, too. It's defined in the contact.js file shown in Listing 4.

    Contact = function() {}

    with (modelFor('Contact')) {

In this case, Steven has ensured that the first and last names are present when the user adds or updates the contact record. Still going along the lines of Ruby on Rails, the validatesPresenceOf function names are identical (with the exception of the capitalization) to their Ruby counterparts.

Well, now we have our controller and our model--the next thing is the view. The view comes in several pieces. The first is the list of contacts, or the index page. That's defined in the index.est file.


    <%= linkToLocal('Create A New Contact', 'contact', 'newInstance') %>

      <% for (var i = 0; i < contacts.length; i++) { %>
        <li><%= linkToLocal(contacts[i].last_name + ', ' + contacts[i].first_name,
            'contact', 'show', contacts[i].id) %></li>
      <% } %>

While it certainly looks like an ERb template from Rails, it is in fact an EcmaScript Template (EST) that uses Erik Arvidsson's EcmaScript Template engine syntax. You can also use the alternative JavaScript Template (JST) syntax, if you prefer, for a syntax that looks more like Velocity or FreeMarker markup.

Looking back at the template, we can see at the top an invocation to linkToLocal, which sets up an anchor to the page newInstance action on the contacts controller, as well as a for loop, which loops through the contacts already in the database to display them.

Of course, since the database is empty we currently don't see them. So, let's fix that.

Pages: 1, 2

Next Pagearrow

Sponsored by: