AJAX is a bunch of cryptic JavaScript snippets on the client side together with some advanced web services, written in another, and more powerful, language. Right? Not necessarily. I here give a brief comparison of three ways to create AJAX applications with only one language, running on both client and server.
The three unilinguistic approaches to AJAX treated in this post are:
- Ruby on Rails - all Ruby, with a continuation library postponing execution of JavaScript
- Google Web Toolkit - all Java, with both emulation of browser and compilation into JavaScript
- HaXe - a new, "EcmaScript++", language implemented in both JavaScript (and Flash...) and with its own abstract machine, for server side execution
There are admittedly other such integral approaches, where ASP.NET was among the first, but what sets these three apart from those older attempts is that they give the developer an (almost) full access to the JavaScript toolbox, without leaving the comfort of one's server-side language.
Ok, let us start looking at these frameworks, from an AJAX point of view.
Ruby on Rails
For an introduction to Ruby on Rails, see the RoR home page. Assuming you now know how to create an RoR app, how do you add AJAX? From version 1.1 of RoR, there is a new template system, called RJS, so the developer can now create a file ending with .rjs for the action and the Ruby code inside that template will be executed on the server-side, obviously, since there is no Ruby interpreter available in a browser - as far as I know
So, how can that Ruby code on the server side possibly do anything on the client side? Are we here encountering quantum-physical entanglement of logic? No, but almost. The Ruby code contained in these RJS templates build up an internal structure that is subsequently output via a JavaScriptGenerator, and inserted - behind the scenes - in a script element. The generated JavaScript output builds on the Prototype and script.aculo.us JavaScript libraries, which assist with browser compatibilities, visual effects and better collection handling.
This style of postponed execution can be viewed as continuation style.
A simple example is an RoR application dealing with orders, and where you want to get the current orders - AJAX style - by clicking on a link. We assume there already is an order controller and a proper action for getting all orders, much like
-
def show_all
-
@orders = Order.find_all
-
end
together with the following show_all.rhtml template
Then you can render this list of orders from another RHTML page, as in
If you want this list to be retrieved from the server-side on-the-fly from the web page, you use the following RJS template show_all_now
-
page.replace_html 'the_orders', :partial=>"show_all"
and just make sure to have a link on the web page to trigger that remote action (via AJAX), which is done by
-
<p>Click <%= link_to_remote "here",
-
:url => { :action=> "show_all_now" } %> to get
-
the list of orders
-
</p>
There is even current work on providing RJS scaffolding, which allows for auto-creation of a lot RJS templates. As if RJS was too tricky
If you want more information about RJS and RoR, either go to Cody Fauser's blog, or wait for future posts herein
Google Web Toolkit
Google Web Toolkit, or GWT, is a framework that lets you stay in the good old Java world, completely. They manage this by providing
- a Java library that conceptually wraps most of the common JavaScript functionality
- a remoting library, different from RMI
- providing an emulated browser, having access to the aforementioned Java libraries, allowing the developer to debug the AJAX application entirely within a JVM, using one of those nifty Java IDEs out there
- compilation these libraries, , including emulation of the most core Java packages (part of java.lang and java.util), and user-provided Java code, into JavaScript
As is understood by anyone having attempted writing abstract machines or compilers, this is a major feat. Being inside of Java feels comfortable, to the degree of over-protecting. In fact, I have had a lot of problems just setting up GWT properly to get the same behavior emulated as compiled. One of the problems, that is fixed in the very recent 1.1 release, was that they included the javax.servlet code in their JARs, which forced the developers to remove those classes before deploying, since web apps having such classes are rejected by any standards-conformant servlet container!
Let us look at a simple example.
We start off by downloading GWT and running
applicationCreator com.davber.client.TestApp
That will create the skeleton, after which we can run the TestApp-shell script, which was generated for us as well. That will start both the server side code - in a mini-installation of Tomcat - and the client code - emulated in a GWT browser. The latter form of emulation is called hosted mode.
Go into the src/com/davber directory, and you should see
TestApp.gwt.xml
client
public
The XML file directs the hosted mode client app to the server-side services and of the client-side entry point (the "main"...)
Since all is Java in GWT, the convention is to put all client-side code in a sub namespace client and all server-side code in a sub namespace server. As we can see, the initial skeleton contains no server-side logic. Let us change that!
Creating an interface for a "greeting" service is as simple as
To implement this interface, we create a class in the server package:
As always in RPC scenarios, we need the triplet interface, implementation and service binding. So let us turn to that last phase, which is achieved by altering the XML file generated for us, TestApp.gwt.xml, to
-
<module>
-
-
<!-- Inherit the core Web Toolkit stuff. -->
-
<inherits name='com.google.gwt.user.User'/>
-
-
<!-- Specify the app entry point class. -->
-
<entry-point class='com.davber.client.TestApp'/>
-
-
<!-- Bind our greeter to the /greetings path -->
-
<servlet path="/greetings"
-
class="com.davber.server.GreetingServiceImpl" />
-
</module>
One last step to solidify the service: since AJAX is asynchronous (the "A", remember?), we cannot use the GreetinService interface as is, but need to provide an alternative interface providing callback options when the request is completed. This looks like
-
package com.davber.server;
-
-
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
-
import com.davber.client.GreetingService;
-
-
public class GreetingServiceImpl extends
-
RemoteServiceServlet implements GreetingService {
-
return "Greeting, " + name +
-
", do you want to play a game?";
-
}
-
}
Ugh, what happened to our return value, the actual greeting?! Relax... since the request is asynchronous, you will not get the result back immediately, but it will instead be provided to the registered callback in client code.
Now we can use this service from a client (i.e., from a web page), by changing the class com.davber.client.TestApp to instead of just setting a label's text to "Hello World!" it invokes the service. This is done by
-
public void onClick(Widget sender) {
-
GreetingServiceAsync serv =
-
(GreetingServiceAsync)GWT.
-
create(GreetingService.class);
-
((ServiceDefTarget)serv).
-
setServiceEntryPoint("/greetings");
-
AsyncCallback cb = new AsyncCallback() {
-
}
-
label.setText("Oops: " +
-
ex.getMessage());
-
}
-
};
-
-
// Finally call the service...
-
-
try {
-
serv.greetMe("David", cb);
-
}
-
label.setText("Internal error: " +
-
ex.getMessage());
-
}
-
}
Test the application, in hosted mode, by
TestApp-shell
and click on the button in the web page. You will be greeted by
Greetings, David, want to play a game?
One important part of GWT is its transparent serialization between Java and JavaScript, where you only need to implement a specific interface to mark the class as "GWT-serializable", analogous to using the Serializable. This makes using complex objects a breeze.
You can even use JSON for your RPC needs, if you want to stay compatible with existing code (such as an Erlang-based service or legacy JavaScript code.)
HaXe
What can not be said about HaXe? It is one of the most ambitious framework projects in recent years. Not for its size, because it is not that heavy nor wide, but for its conceptual scope. Just look at sub title: web oriented universal language. I love this guy!
He decided that Web 2.0 is not only JavaScript but indeed good old Flash. I think he is right.
So, he needed a framework that targeted both JavaScript and Flash.
He also understood that Web 2.0 involves server side code. Not a huge suprise
What is a surprise is that he decided that one should use one language for all these three loci. And, since there was no such language, he created one...
That language is called HaXe and is a strongly typed (if you want) language - that means that you can find simple bugs earlier - and supports generics. In short, it is like EcmaScript++.
He handles JavaScript and Flash by compiling HaXe code to those languages, directly. Since he did not want to rely on a specific server-side language, such as Java nor its JVM, for the server-side logic, he chose not to compile it into another language but instead to create a light-weight abstract machine suitable for his HaXe language. That abstract machine is called neko.
HaXe has its own remoting protocol, which is started to be implemented by some other server-side environments, such as Yariv's eminent HaXe RPC implementation for Erlang.
I will leave HaXe's RPC mechanism and instead create a simple alternative client running against the RoR Order controller above.
static function showOrders(id) {
var req = new haxe.Http("/order/show_all");
req.onError = js.Lib.alert;
req.onData = function(allOrders){
var elem = js.Lib.document.getElementById(id);
elem.innerHTML = allOrders;
}
req.request(false);
}
}
and corresponding web page
And then compile the hx file by creating a "configuration" file for HaXe and run
haxe OrderProxy
Then open the web page, and click on the link. You should see all the orders provided by the RoR back end.
If you want to be on the bleeding edge of Web 2.0, and support ambitious projects and individuals, this is for you.
I will talk more about HaXe later. Till then, happy AJAX!
AJAX ecmascript google gwt haxe Java javascript Language Reviews ror Ruby Tools Reviews