Imagine ripping off the visual rendering part of Firefox and replacing it with a hook to Apache instead – roughly speaking that’s what Jaxer is.
Jaxer is a strange new hybrid application coming from the folks at Aptana (the makers of the quite-excellent web IDE). Literally, they took the Mozilla platform (which powers Firefox, Camino, etc.) and built a stateful platform on top of it.
You can imagine it as a browser that’s able to render pages, modify them dynamically with JavaScript and the DOM, and even use JavaScript libraries with great ease – with the exception that it’s living as a standalone server-side process, un-associated with the typical browsing experience.
Aptana has implemented something that’s greatly interested me ever since I started playing with JavaScript on the server-side (via Rhino). My friends over at AppJet even took a step towards making this concept easy, hosted, and free. The difference here is the severe amount of power and leverage that you’re gaining with this platform: file I/O, network connectivity, database access, and even email access.
Let’s back up a bit and look at an example of a simple, but representative, Jaxer application. This simple application is a textarea which, when submitted, quietly saves the results to a text file on the server. What you see below is the entire application – there is no other server-side language being used save for JavaScript.
<html> <head> <script src="http://code.jquery.com/jquery.js" runat="both"></script> <script> jQuery(function($){ $("form").submit(function(){ save( $("textarea").val() ); return false; }); }); </script> <script runat="server"> function save( text ){ Jaxer.File.write("tmp.txt", text); } save.proxy = true; function load(){ $("textarea").val( Jaxer.File.exists("tmp.txt") ? Jaxer.File.read("tmp.txt") : ""); } </script> </head> <body onserverload="load()"> <form action="" method="post"> <textarea></textarea> <input type="submit"/> </form> </body> </html>
There’s a bunch of key points here that we need to take a look at in order to understand what’s going on here, however it’s most important to note that this application looks just like a normal HTML/JavaScript/DOM web app – there are no significant differences in syntax or style. Let’s dig in and see what all there is at play here.
runat="both"
andrunat="server"
– These script blocks are just like normal script blocks, but with an important exception: They both are capable of running on the server, rather than on the client. It’s important to remember that since a Jaxer server is just like a headless Firefox, thus it’s able to handle the same JavaScript that Firefox can. In this case that’s both the whole jQuery library and a couple of helper functions. Therunat="both"
declaration, additionally, states that the script block should be executed on both the client and the server (in this demo we’re using jQuery in both places).Jaxer.File
– These set of methods are part of the Jaxer API. It’s important to note that these functions can only be run on the server-side, thus they should only be called in a server-capable script block. The methods do what you would expect them to: They allow you to do simple interactions with text files.save.proxy = true;
– The save() function must exist on the server-side (since it contains calls to server-side functionality) however we want to be able to call it from the client-side whenever the user hits the submit button to save their textarea changes. We can do this by making it a proxy function (adding an extra proxy property to the function). This actually creates a stub function on the client-side, to allow the code to continue working as it would expect, while obscuring the actual functionality behind an Ajax request. It’s all completely seamless and works as you would expect it to, which is impressive. You can also make functions proxy functions by using arunat="proxy"
on a script block.onserverload="load()"
– This attribute gives a simple mechanism for running a piece of server-side functionality on DOM ready. In this case we’re loading the contents of the saved text file and injecting it into the textarea, using jQuery.
There’s also one thing that I want to mention: I built the above mini app after only a cursory glance through the examples and it worked 100% perfectly out of the box, with no errors whatsoever. This is really hard to do and even more so with the first release of a project – I’m quite impressed. Even taking nothing else into account it’s pretty obvious that Jaxer is easily the most exciting piece of JavaScript technology to arrive in a long time.
Disclaimer: I’m a proud member of Aptana’s advisory board. I’ve been greatly impressed with their work and I’m glad they asked me to join them.
Dr Nic (January 23, 2008 at 3:40 am)
You giving it the thumbs up pushes “investigate Jaxer” high up onto my “immediate things I should do today” list. Thanks for giving a run through of Jaxer as soon as it was published.
Chris Zumbrunn (January 23, 2008 at 6:30 am)
Coincidence has it that I also have something new to report today from the server-side javascript front: “Jhino”, a new soft-coding scaffold for the Helma javascript server-side.
I’ve been experimenting for some days with the JOMP patch for Rhino [1] and using additional filename conventions to map hard-coded files with soft-coded properties in Helma [2]. What I came up with is basically a lean application scaffold with CRUD type functionality and access control, adding a bunch of coding conventions to the ones already provided by Helma.
Jhino has a strong emphasize on separating markup (views) and js (controls) from each other, splitting things out into separate files. Mixing it together like in the above Jaxer code example is currently only possible to the extent supported by E4X (since Jhino uses E4X for it’s server-side templates). Enabling the controls to use jQuery in order to modify the views will make sense for sure. Any chance jQuery could work directly on E4X objects soon, without the need to first convert them?
I’m not sure how often it will really make sense to run the code on both the client and server side. I hope we will come up with some interesting use cases for this, because the idea is intriguing!
For those who want to give Jhino a whirl:
http://code.google.com/p/e4xd/downloads
More info about in the Helma wiki:
http://dev.helma.org/wiki/e4xd+and+jhino+-+experimental+soft-coding+scaffold+using+JOMP/
[1] http://dev.helma.org/wiki/Comparison+of+JSAdapter+and+JOMP/
[2] http://dev.helma.org/static/files/2302/helma.txt
bard (January 23, 2008 at 8:04 am)
John,
AFAIK AppJet is based on Helma, which Chris mentions above, and while it’s true that AppJet makes it “easy, hosted, and free”, it’s also true that Helma itself provides “file I/O, network connectivity, database access, email access”, and the gazillion more libraries available to the JVM, which it runs upon. I’m not very fond of the Java language, but when talking about power and leverage, it’s hard to discount those of the Java platform. :-)
pd (January 23, 2008 at 8:25 am)
so standards support really did end today?
Mark Finkle (January 23, 2008 at 9:26 am)
@pd – Not sure what you mean here. If you’re referring to the use of “Jaxer.File”, this only happens on the server. It is in the HTML source just like PHP, Python or ASP code is intermixed on the server. I am fairly sure that the script blocks marked as runat=”server” are stripped out before sending to the client.
John Resig (January 23, 2008 at 11:17 am)
@Chris: That new Jhino stuff looks real cool, I’ll be sure to check it out!
@bard: Absolutely – Helma is great stuff. It’s important to note that its structure is quite different from Jaxer. (Jaxer builds on the existing client-side development model whereas Helma has more of a broad framework for development.)
Just want to emphasize that one isn’t “right” and one isn’t “wrong” – they’re both highly interesting and undisputedly the best resources for doing server-side JavaScript web app development, at the moment.
zob (January 23, 2008 at 12:36 pm)
Similar to what Links coul do, given time…
http://groups.inf.ed.ac.uk/links/quick-help.html#located_code_and_remote_procedure_calls
h3 (January 23, 2008 at 1:31 pm)
Pretty neat ! but I have some questions :)
1. When the save method is called, does the page reload ?
2. Does the script blocks marked as *runat=”server”* shows up in the served HTML ?
And a final one not really related to Jaxer itself but to Server side JavaScript:
How would you rate the performances and scalability ?
Writing in the same language client and server side is a very seductive idea, beside that I love JavaScript. I tried a while ago but
I have an intolerance for Java so I did not play with Rhino very much.
Cheers
John Resig (January 23, 2008 at 1:44 pm)
@h3: 1) No, it’s done completely seamlessly via Ajax.
2) No – however a new script block is created which holds the save proxy method (which isn’t the same as the original method but, instead, an Ajax call).
I haven’t analyzed the performance yet – I suspect that we’ll see a lot more analysis on that front in the upcoming weeks.
mike (January 23, 2008 at 2:34 pm)
I love the idea of basically collapsing the skill set down to HTML/JavaScript, and possibly SQL (which is to say that I find this a lot more interesting without the inclusion of PHP or RoR). But, I’m not sure how you would get things like layouts, partials, database connection pooling, etc…. Am I hoping for too much?
Morgan (January 23, 2008 at 3:23 pm)
This looks really cool, I cannot wait for the Linux release. I had been playing with your Rhino browser environment, but due too the requirement of well formed XML, did not meet my needs. Another worth mentioning is Harmony, it uses Rhino and Jetty together for server-side JavaScript.
Mario Valente (January 23, 2008 at 7:45 pm)
I’ve been harping about the importance of serverside Javascript for some time now, so I’m glad to see another project representative of how I see web development going forward.
Unfortunately I dont think that Jaxer is the right way to do it. I’d much rather see improvements on things like mod_js, jsext, jsdb or jslibs. Preferably a merging of the best parts of each….
http://www.modjs.org/
http://www.jsext.net/
http://www.jsdb.org/
http://code.google.com/p/jslibs/
— MV
davey (January 23, 2008 at 8:30 pm)
Great to see a bunch of discussion on this topic. I really really need to make some time to check helma/jhino which look really cool.
@mario, most of those links are just JS libraries which i’m sure could ported to jaxer with a little work. utlimately we expect/hope to see 3rd party libraries built to do the serverside work in the way that makes most sense.
@pd, we really have only 2 things outside the standards, a server side directive like an SSI. and the runat attribute which as it is only an attr is debatable whether that is outwith any standard. everything else is basically just javascript from framework.js library we built (includes a fair whack of jslib functionality) but most of the low level stuff is really only XPCOM access via firefox wrapped in javascript, which BTW is the exact same skillset that firefox plugin developers use. In fact i am hoping to be able to leverage John and Mark’s FUEL library (via extension) in the future.
@Morgan http://forums.aptana.com/viewtopic.php?t=4543 for linux early adopters. basically if you sign up you’ll get an early version and we get some useful QA
cheers
davey
Christer (January 23, 2008 at 9:37 pm)
I’m not overly thrilled. While it looks useful at a first glance, it really imposes bad coding habits – inline javascript all over the place. I predict an application written this way will be a real mess once it grows. It seems to be useful for small pieces, though.
Havvy (January 24, 2008 at 1:42 am)
When I decide to actually learn to type javascript to build a webpage, I won’t need to learn PHP, RoR, or ASP (as if I’d do the last one). This looks great.
I wonder if somebody could create a free host with that as the serverside, with PHP on also. With paid being supported of course.
Asbjørn Ulsberg (January 24, 2008 at 8:18 am)
It looks interesting, but only if it helps relief the burden it is to write both client- and server-side hooks for all events, such as form posts. Since you’re using JQuery to post the form, what happens if JavaScript is disabled? How does Jaxer deal with such situations? If you use JavaScript to validate user input and JS is disabled in a browser, will the client be able to post the unvalidated input to the server without the validation happening on the server as well?
It would be wonderful to write almost 50% less code (minus the things that will only work on server, like the File object), but if you’d still have to write the same amount of code to provide the server-side functionality required for situations where JavaScript is turned off, filtered away or right out not supported (like on many mobile browsers for example), we’re basically at square one again.
Plus, is it possible to not assign events with the archaic on* HTML attributes, but instead use JQuery’s $(function() { … }); and such instead? How does client side JavaScript libraries like JQuery, YUI, etc., behave when used server-side?
Asbjørn Ulsberg (January 24, 2008 at 8:21 am)
I also wonder how Jaxer is hosted on the server? Is it an Apache module, an F/CGI interface, or what? How easy would it be to get Jaxer to run on a shared web host environment like DreamHost, where you’re not able to compile Apache yourself?
Richard Marr (January 24, 2008 at 9:07 am)
This was done a couple of years ago in the form of Zimki, the one difference being that Zimki got canned before the source got opened. Still, I think those guys deserve a mention for pushing the idea.
Kris Zyp (January 24, 2008 at 10:21 am)
I am skeptical of taking the slow, awkward DOM APIs of the client and bringing it to the server. Do you have any idea what type of performance impact doing parsing and DOM generation for each HTML file will cause? Spidermonkey is not a terribly fast VM either. It is one thing for this hit to be incurred on the browser, but when every server request must incur the hit, isn’t there some serious scalability issues awaiting Jaxer?
I am totally in favor client and server JavaScript that can transparently coexist, but IMHO the view level is just simply the wrong place, I think we really need at the model level (which is of course the direction I have taken with Persevere for server side JavaScript).
Scott Trudeau (January 24, 2008 at 10:24 am)
@Asbjørn that was my biggest open question when I saw the Jaxer announcement — how does it degrade? One of the more frustrating aspects of writing complex web UIs (especially with non-trivial form inputs) is doing user input validation twice. Once on the client (to give immediate feedback to users with JS enabled) and again on the server (for users without JS enabled AND to make sure the server is getting sane input). This generally means you end up writing a lot input validation code twice, which sucks, especially if your validation is not extremely trivial.
My friend George recently took the approach (using php and js) of writing code that is both valid javascript and php and then eval’ing it in php to do the validation:
http://george.hotelling.net/90percent/geekery/dryer_than_thou.php
@Kris that was my second concern. How efficient is this thing and how easily can it scale. Right now according to the docs it can’t even be deployed on Linux (just Windows/Mac) which keeps it in the “toy” category for me for quite some time.
Matjaž (January 24, 2008 at 3:24 pm)
Hi all!
I noticed two problems which I think are pretty annoying:
1. runat=”both” reads external file (with src attr) and displays it’s content instead of leave src attr.
2. from save() function I can’t access jQuery or global vars:
var txtFileName = "content.txt";
function save(text) {
Jaxer.File.write(txtFileName, text);
jQuery("textarea").val(""); // error
}
So we can’t manipulate DOM from AJAX calls.
First problem I fixed with separate includes.
For the second problem I didn’t find any solution.
Suggestions are welcome!
Regards,
Matjaž
John Resig (January 24, 2008 at 4:40 pm)
@Matjaž: That’s because you’re trying to update a page, on the server-side, during an Ajax request. Instead, you should call that particular jQuery line in the form submit function (which takes place on the client-side).
Matjaž (January 24, 2008 at 5:18 pm)
John, thanks for your reply.
I know that, but wouldn’t it be cool if you could just update document from an AJAX call.
Here is a example file:
http://shrani.si/f/2f/4Y/2FJn9cHX/text.htm
If you look at it, you’ll first notice duplication of
var txtFileName = “content.txt”;
that’s because as far as I figured it out there is no support for closures in AJAX invoked functions.
Second thing I wish it would be cool to manipulate DOM from this AJAXed functions.
So there should be only one
if (text === “del”)
I know this is technically complicated but it can be achieved by monitoring DOM changes during AJAX call.
In example I also moved onserverload from HTML because I love clean and tidy markup. :)
Comments are appreciated.
Greets!
Goncalo Fonseca (January 25, 2008 at 9:36 am)
JavaScript as a “one language does it all”
… and HTML5, CSS3 and SQL(?). Yes!
I already see a JOR framework as the next big thing ;)
Jose M. Arranz (February 23, 2008 at 3:41 am)
Jaxer is not the first one introducing the server-side DOM approach.
Some moths ago ItsNat, Natural AJAX, was released with a similar approach but using the power of Java with no special infrastructure, only one servlet.
But one competitive advantage of ItsNat over Jaxer is client-server automatic sync: you can change any piece of server DOM on load time and in an AJAX request too, the client DOM is changed accordingly.
ItsNat simulates a Universal W3C Java browser including events (in ItsNat are Java W3C DOM Events).
Roman Gritsulyak (February 28, 2008 at 4:19 pm)
I am interesting in this technology.
In my opinion, it can provide more robust way to code web client server applications.
Due to the same language on both sides and no need for the switching from one programming language to another, it can be much less bugs in the code.
Is it possible to have database connection from application, or execute the command on server side with this web server?
What is the main difference from mod_apache in this implementation of SSJS?
Roman Gritsulyak (February 28, 2008 at 4:23 pm)
Oh, sorry.
Of cause, I mean mod_js under apache, not mod_apache in my previous post.
Pierre Lasante (April 13, 2008 at 4:13 pm)
Good introductory tutorial. Thanks a lot.
Stefano Cutello (May 22, 2008 at 6:39 pm)
Matjaž I think that the solution to “manipulate DOM from this AJAXed functions” is to use the
Jaxer.Callback.invokeFunctionAsync(Object callback, String functionName, Object args)
‘callback’ is the client-side function that receives as argument what the remote function returned from the server
‘functionName’ is the remote function
‘arg’ are the arguments for the remote function
John, can you confirm this? ;-)
thank you
bye