Skip to main content

Using E4X on the server-side with Jaxer

Build a Web application with JavaScript and Jaxer

Michael Galpin (mike.sr@gmail.com), Software architect, eBay
Michael Galpin's photo
Michael Galpin has developed Web applications since the late 1990's. He holds a degree in mathematics from the California Institute of Technology and is an architect at eBay in San Jose, CA.

Summary:  The ECMAScript for XML (E4X) standard gives JavaScript developers a powerful API to work with XML. As it is not supported in Internet Explorer®, you might not get to use it often. That is not an issue if you use JavaScript on the server with Jaxer. In this article, you see how JavaScript and E4X make it easy to work with XML on the server. Combine this key ingredient with Jaxer to create Ajax applications using nothing but JavaScript.

Date:  03 Mar 2009
Level:  Intermediate PDF:  A4 and Letter (117KB | 13 pages)Get Adobe® Reader®
Activity:  45530 views

Introduction

In this article you will build a Web application that uses JavaScript on both the client and server side using Jaxer. Experience with Web development, especially JavaScript, is assumed. You will use JavaScript and, in particular, E4X to work with XML, so some familiarity with XML will be helpful. The application was developed using Aptana Studio™ 1.2.1, but it is possible to develop Jaxer applications without Aptana Studio. Jaxer 1.0.2 is bundled with Aptana Studio, so you do not have to download it separately. See Resources for download links.

Overview of Jaxer

Frequently used acronyms

  • Ajax: Asynchronous JavaScript + XML
  • API: application programming interface
  • DOM: Document Object Model
  • HTML: Hypertext Markup Language
  • IDE: Integrated Development Environment
  • JSON: JavaScript Object Notation
  • PHP: PHP Hypertext Preprocessor
  • URL: Uniform Resource Locator
  • XHTML: Extensible Hypertext Markup Language
  • XML: Extensible Markup Language

Jaxer allows you to use JavaScript as a server-side programming language. You can do everything that you normally do with Java™, PHP, Python, or Ruby™ programming, like accessing a database, reading and writing to files, or communicating with other servers. Jaxer, however, allows you to develop a modern Web application using only one programming language: JavaScript. If you are creating dynamic, interactive Web applications, you are already writing a lot of JavaScript. If you are creating a lot of Ajax, then you probably spend a lot of time translating back and forth between JavaScript and whatever you use on your server. Now you can simplify your development by doing everything in JavaScript. Before you dive into using Jaxer, take a brief look at the Jaxer architecture to better understand how a Jaxer application works.


The Jaxer architecture

Jaxer's use of JavaScript on the server is certainly unusual, but its architecture is quite standard. Jaxer runs on top of the Apache Web server, and it is just another Apache module: mod_jaxer. This is the same architecture you see with PHP, Python, or Ruby on Rails™ (using Phusion Passenger™), or with using Apache in combination with a Java Web container such as Tomcat (using mod_jk). Figure 1 shows a high level view of the architecture.


Figure 1. Jaxer architecture
Jaxer architecture

This is a pretty standard server-side architecture. Jaxer also shares other characteristics with server-side technologies like PHP. It takes a shared nothing approach (though it does automatically store session data to a common database).

So how does Jaxer actually run JavaScript on the server? Jaxer uses Mozilla®'s SpiderMonkey JavaScript Virtual Machine. This is the same JavaScript engine used in Firefox® 3.0. This allows Jaxer to provide very good performance, comparable to PHP. With Jaxer, you get to use any JavaScript supported in Firefox, not just the subset of JavaScript supported in both Firefox and Internet Explorer. As you will see later, this includes some functional programming constructs like Array.map and Array.reduce, and especially E4X for parsing and generating XML. Now that you have an idea how Jaxer works, take a look at what you need to install to get started with Jaxer.


Installing Jaxer

Jaxer is available for most platforms, including Windows®, Mac OS® X, Linux® and Solaris™. Jaxer comes bundled with Apache, so you don't need to download anything else. However, an even easier way to start working with Jaxer is simply download Aptana Studio (see Resources). You might want to do this anyway, as it is a great IDE for JavaScript developers, but it also includes an embedded Apache/Jaxer server. This lets you write your Web application and immediately run it on Jaxer. Aptana Studio is an Eclipse plugin. You can download it as a standalone application, with Eclipse bundled, or as a plugin if you are already using Eclipse.

When you start Aptana Studio, you will want to try out the Jaxer shell. The shell lets you enter JavaScript and execute it directly inside Jaxer. It is a great way to test and debug your code directly on the server. Figure 2 shows an example of exploring some of the Jaxer APIs using the Jaxer shell.


Figure 2. The Jaxer shell
The Jaxer shell

To create an application that uses Jaxer, create a new project and select Aptana Projects > Default Web Projects. In the wizard, you'll see a screen about adding Jaxer Support. Once you create the project, you can right-click on any HTML file and select Run As > JavaScript Web Application. This will deploy your files to Jaxer and bring up the page in your default Web browser. If you use Firefox, Jaxer has a plugin that uses the popular Firebug plugin to debug JavaScript. The Jaxer version will let you debug the real code inside Aptana Studio. Now that you are up and running with Aptana Studio and Jaxer, you can build a sample application to demonstrate Jaxer's support for server-side E4X.


Sample application: Searching Flickr with JavaScript

It's time to create the sample application. To keep it very simple, you'll create an application that searches for photos from the popular photo sharing site Flickr. Your application will use a Flickr Web service to search for all photos with a given tag. Flickr will give you this data in XML, and you will process this XML using E4X on the server. First look at the appearance of this XML and how you will process it using E4X.

Parsing XML with E4X

Flickr's Web services can provide data in a variety of formats, such as XML, JSON, and even serialized PHP. The default format is XML. Listing 1 shows sample output from Flickr's Web service.


Listing 1. Sample XML from Flickr
<?xml version="1.0" encoding="utf-8" ?>
<rsp stat="ok">
<photos page="1" pages="20626" perpage="16" total="330003">
    <photo id="3284086892" owner="49356365@N00" secret="a072efd762" 
server="3294" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
    <photo id="3283258525" owner="49356365@N00" secret="30c9b39aa1" 
server="3409" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
    <photo id="3284079858" owner="49356365@N00" secret="798d6ca888" 
server="3517" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
    <photo id="3284077350" owner="49356365@N00" secret="c27902242e" 
server="3413" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
    <photo id="3283262179" owner="49356365@N00" secret="2b2e36cafd" 
server="3149" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
    <photo id="3284084794" owner="49356365@N00" secret="57afa6f5f8"
server="3294" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
    <photo id="3284081008" owner="49356365@N00" secret="5cd1b5a932" 
server="3435" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
    <photo id="3284085910" owner="49356365@N00" secret="0a51105dcd" 
server="3487" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
    <photo id="3283263823" owner="49356365@N00" secret="944da852f9"
server="3407" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
    <photo id="3284082986" owner="49356365@N00" secret="2d0f3c3755" 
server="3282" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
    <photo id="3283236151" owner="49356365@N00" secret="2299cca4e1" 
server="3146" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
    <photo id="3283249899" owner="49356365@N00" secret="e23d563cef" 
server="3623" farm="4" title="Snow Day" ispublic="1" isfriend="0" isfamily="0" />
</photos>
</rsp>

If you had to parse data like this with server-side Java code or even client-side JavaScript code, you might use DOM APIs. This is straightforward, but can lead to some extremely verbose code. With E4X it is much simpler. Listing 2 shows code for parsing XML from Flickr.


Listing 2. Parsing Flickr XML with E4X
/*
 * Parses XML in the following format:
 *     <photo id="3283249899" owner="49356365@N00" secret="e23d563cef" 
 *   server="3623" farm="4" title="Snow Day" ispublic="1" isfriend="0" 
 *   isfamily="0" />
 */
function FlickrPhoto(xml){
    this.id = xml.@id.toXMLString();
    this.owner = xml.@owner.toXMLString();
    this.secret = xml.@secret.toXMLString();
    this.server = xml.@server.toXMLString();
    this.farm = xml.@farm.toXMLString();
    this.caption = xml.@title.toXMLString();
    this.url = "http://farm"+ this.farm + ".static.flickr.com/"+
    this.server +"/"+ this.id +"_"+ this.secret +".jpg";
    this.toHtml = function(){
        var html = <img src={this.url} alt={this.caption} 
title={this.caption}></img>;
        return html.toXMLString();
    }    
}    

Begin by reading the comment before the code. It shows the type of XML that is expected as an input parameter. This is a single photo element from the sample XML in Listing 1. For each attribute of the photo element, such as id, owner, or the others, you map the value to a similarly named property of a JavaScript class called FlickrPhoto. So, for example, to access the server attribute of the XML, you use xml.@server.toXMLString(). The toXMLString method returns a string representation of the data.

The url property set above simply constructs the URL to the image from the data provided by the Web service. Even more interesting is the toHtml method. Notice that this uses an XML literal. E4X is not just great for accessing data in XML, but for creating XML. Of course, HTML, or more accurately XHTML, is also XML. So you can use E4X to create an HTML expression. In this case it is an image tag. We might construct this as a string, but E4X is more elegant. Notice how you can embed the url and caption properties directly inside the XML expression. So how do you get the XML from Flickr into one of these objects? For that you will need a proxy.

Using a Proxy

Inside the browser, you can make remote calls using XMLHttpRequest, but only if it is from the same domain as your Web page. This rules out calling Flickr directly. You need to call it from our server using a proxy. Jaxer makes this very easy. You simply declare your JavaScript inside a script element, just as you normally would, but you add an extra attribute to let Jaxer know that you want to use this as a proxy. Take a look at Listing 3.


Listing 3. The Flickr search page with proxy
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <title>Flickr Search</title>
    <script type="text/javascript" runat="server-proxy">            
// server side code goes here        
    </script>
    <script type="text/javascript">
        function getData(){
            var tag = document.getElementById("tag").value;
            var response = getFlickr(tag);
            document.getElementById("out").innerHTML = response;
        }
    </script>
    </head>
    <body>
        <div>
            <span>Search:</span>
        <input type="text" id="tag"></input>
            <input type="button" value="Show Photos" onclick="getData()"/>
      </div>
    <div id="out">Output will go here</div>
    </body>
</html>

Notice the first script tag. It has a runat attribute set to server-proxy. This tells Jaxer that any code in this block will run on the server, but should be callable on the client. Jaxer will create proxy objects on the client.

In this example, you have a simple HTML form with a single text input field and a button. When a user clicks on the button, it invokes the getData function. This function takes the data entered in the text field and passes it to the getFlickr function. But where is that function? It is defined on the server. The Jaxer library creates a proxy for it so that it can be invoked by the client code in Listing 3. This function is what will access the Flickr Web service. Now look at how this will work.


Invoking Web services

On the server, you can use anything that you can use on the client. For example, you can use XMLHttpRequest to call a remote Web service. However, the server has fewer restrictions so Jaxer includes APIs to make this easier to do. Listing 4 shows the code for this.


Listing 4. Calling Flickr on the server
function getFlickr(tag){
    const API_KEY = "Your Key Goes here";
    var url = "http://api.flickr.com/services/rest/?method=" +
        "flickr.photos.search&per_page=16&api_key="+ API_KEY + 
        "&tags="+tag;
    var raw = Jaxer.Web.get(url);
    Jaxer.Log.debug("Got data from Flickr=" + raw);
    var rsp = new XML(raw.replace(/<\?(.*?)\?>/,''));
    var photos = [rsp.photos.photo[i] for (i in rsp.photos.photo)];
    photos = photos.map(function(x) new FlickrPhoto(x));
    var html = photos.reduce(function (previous, current){
        return previous + current.toHtml();
    }, "");                
    return html;
}

This is pretty succinct code, but a lot happens in Listing 4. First, you create the URL to the Flickr Web service. You will need an API key to call Flickr. Notice that the API_KEY variable is declared as a const. This is part of JavaScript 1.5, but it is not supported in Internet Explorer. As the name suggests it declares a variable as a read-only constant.

Next, to call the Flickr Web service, you use the Jaxer.Web.get API. This is part of the Jaxer library and lets you make a synchronous call to any remote server, with no restrictions. It is much simpler to use than XMLHttpRequest. You take the result from it and use another Jaxer API, Jaxer.Log.debug, to log the data from Flickr. You can access the Jaxer logs directly from Aptana Studio. You might need to adjust your logging level as, by default, it only logs ERROR level messages.

The data from Flickr is parsed into an XML object. Notice that you first ran a regular expression on it. The regular expression removed the XML declaration (<?xml version="1.0" encoding="utf-8" ?>) as this is not something that E4X expects. Once you have an XML object, you can get to the list of photo elements, with the expression rsp.photos.photo. Notice how this matches the element structure from Listing 1.

The next expression (the one starting with var photos) might be unfamiliar to even experienced JavaScript developers. It is an array comprehension, and it was part of JavaScript 1.7. Again, because of cross browser requirements, you will not see this type of functional programming style in JavaScript too often. It is very similar to listing comprehensions in Python, if you are familiar with Python. In this case, you iterate over the rsp.photos.photo object. This is an XMLList object, that is it is a list where each element corresponds to a photo node from the XML seen in Listing 1. The comprehension creates an array, where each element in the array is an XML element from the XMLList. In other words, you turned the XMLList into an array. Why did you do this? Simply because the Array class has some nicer APIs to work with than XMLList does. Read on.

Once you have the photo XML objects in an array, you can call the map function on the array. This is another functional programming construct. It takes a single parameter, a function, and applies the function to each element in the array. The result is a new array, where the i-th element is the result of applying the function to the i-th element of the original array. It is actually possible to combine these two lines of code, the array comprehension and the map, but they are kept separate here to demonstrate some of the powerful things that you can do with server-side JavaScript.

Finally you use one more advanced JavaScript feature. This is the reduce method on the array. This was introduced in JavaScript 1.8, and like array comprehensions and map, it is very similar to a construct in Python (in many other functional languages, this is known as a fold). It takes in two parameters, a function, and an initial value. The function has two parameters: previous and current. The previous parameter starts off with the initial value, or, in this case an empty string. The current parameter starts off as the first element in the array. The previous parameter is replaced by the result of the function, and this process is repeated with the next element in the array until all of the elements are used. In this case, you start with the empty string and concatenate to it the result of the first element's toHtml method being called. You then concatenate that result to the result of the second element's toHtml method being called, and so on. In the end, you concatenate the result of toHtml being applied to each element in the array. Table 1 demonstrates what occurs:


Table1. The concatenated results as toHtml is applied to each element in the array
IterationPreviousCurrentReturn value
0 """"
1""photos[0]photos[0].toHtml()
2photos[0].toHtml()photos[1]photos[0].toHtml()
+
photos[1].toHtml()
3photos[0].toHtml()
+
photos[1].toHtml()
photos[2]photos[0].toHtml()
+
photos[1].toHtml()
+
photos[2].toHtml()

Thus in the end, the map expression takes each element, applies its toHtml method, and concatenates the values together. Going back to your client code, you see that result of all of this is passed back to the client and used to update the DOM there. Thus it will display all of the images from Flickr.


Summary

You saw how Jaxer allows developers to create powerful Web applications using only JavaScript. Running JavaScript on the server is not some oddity. It is a very modern, powerful programming language. In particular, its E4X features allow you to easily slice and dice XML documents and create XML expressions. JavaScript on the server has many other expressive features. The combination of a powerful language and the ability to use it on the server and the client can be very appealing. Jaxer makes all of this possible, so now you can go out and start using your JavaScript skills in new ways.



Download

DescriptionNameSizeDownload method
The Jaxer applicationFlickrSearch.zip2KB HTTP

Information about download methods


Resources

Learn

Get products and technologies

  • Aptana Studio: Download and try Aptana Studio 1.2.1 as used in this article.

  • Flickr: Visit this online photo management application.

  • Passenger: Compare the architecture of Phusion Passenger (Ruby on Rails) and Jaxer.

  • IBM trial software for product evaluation: Build your next project with trial software available for download directly from developerWorks, including application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.

Discuss

About the author

Michael Galpin's photo

Michael Galpin has developed Web applications since the late 1990's. He holds a degree in mathematics from the California Institute of Technology and is an architect at eBay in San Jose, CA.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Web development, Open source
ArticleID=373234
ArticleTitle=Using E4X on the server-side with Jaxer
publish-date=03032009
author1-email=mike.sr@gmail.com
author1-email-cc=dwxed@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers