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.
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.
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

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.
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

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.
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.
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.
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
| Iteration | Previous | Current | Return value |
|---|---|---|---|
| 0 | "" | "" | |
| 1 | "" | photos[0] | photos[0].toHtml() |
| 2 | photos[0].toHtml() | photos[1] | photos[0].toHtml() + photos[1].toHtml() |
| 3 | photos[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.
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.
| Description | Name | Size | Download method |
|---|---|---|---|
| The Jaxer application | FlickrSearch.zip | 2KB | HTTP |
Information about download methods
Learn
- E4X: JavaScript on steroids (Grace Walker, developerWorks, July 2008): Explore the many things you can do with E4, including simple and easy parsing, calculating, editing, and related activities on XML data.
- Ajax and scripting Web services with E4X (Paul Fremantle and Anthony Elder, developerWorks, April 2005): See how useful E4X is in Ajax applications and how this extension to JavaScript makes XML scripting very simple.
- Using functional programming techniques to write elegant JavaScript (Shantanu Bhattacharya, developerWorks, June 2006): JavaScript is at its heart a functional programming language. See what you can achieve when you keep this in mind.
- Charming Python: Functional programming in Python (David Mertz, developerWorks, March 2001): Explore how many of JavaScript's advanced features are similar to Python.
- The Jaxer Guide: Find complete information on Jaxer and how to execute JavaScript on the server.
- Processing
XML with E4X: If you run into any questions about E4X, consult this Mozilla page.
- Can Your Programming Language Do This? (Joel Spolsky, August 01, 2006): Take a fun and thought-provoking look at the power of JavaScript.
- Build an Ajax-enabled application using the Google Web Toolkit and Apache Geronimo (Michael Galpin, developerWorks, May 2007): Combine Geronimo with the Google Web Toolkit and rapidly build sophisticated Ajax Web applications.
- IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.
- XML technical library: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.
- Web development zone: Visit the developerWorks Web development zone for a wide range of technical articles and tips, tutorials, and standards.
- developerWorks technical events and webcasts: Stay current with technology in these sessions.
- developerWorks
podcasts: Listen to interesting interviews and discussions for software developers.
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
- XML zone discussion forums: Participate in any of several XML-related discussions.
- developerWorks blogs: Check out these blogs and get involved in the developerWorks community.






