Wednesday, April 05, 2006

Embedding Databases, Web Servers, App Servers in the Browser

At ApacheCon 2005 an exciting demonstration was given by Francois Orsini (see also Francois' blog) showing how the Apache Derby database could be embedded into the Firefox browser. After reading David Van Couvering's blog entry on the subject I have previously postulated on what this could mean, without actually knowing any of the specific details. Sun has it's own variant of Apache Derby it calls Java DB. As a demonstration of Java DB the code of the ApacheCon 2005 demonstration can now be publicly accessed here. Full install instructions are available to make sure you have the right Java plug-ins installed for the demo to work. Plugins permitting you can also access the demo directly here.

The demo initially presents a login screen, once you login (with any username/password combination) and you can then edit some data in a simple form and save that data. Exit the browser and you can access the same data again!

When the demo begins the browser presents you with a "Warning - Security" pop-up window at which point you must agree to trust the demo for the demo to proceed.

What is really great about this demo is that you can download it and dissect it to see how it works. It turns out to be really quite simple. All the pages of the demo application are actually a single web page, whose various sections are exposed and hidden using the usual DHTML and AJAX techniques. So why is it important that this is a single page web application you may ask? Well the whole thing is powered by an applet. It has been a long while since I had anything to do with applets (I've never really been that impressed beyond minesweeper and space invaders). This applet is responsible for starting and shutting down the backend database and responding with appropriate XML to all the user requests, it provides services to the JavaScript rather then rendering any visible GUI. The process of communication with the locally installed Derby database via the applet is what Francois Orsini refers to as LAJAX (Local AJAX)! Cool! Does anybody notice the resemblance to how DWR works?

There is nothing particularly Java DB/Apache Derby specific about the LAJAX applet technique, it could have just as easily have been an installation of some other embedded 100% Java database like HSQLDB or H2 at the backend. In the source of the demo's index.html it mentions you could even embed a Jetty web server using this technique, something that I couldn't resist trying out for myself!

Things to note: I haven't written an applet for about 6 years and even then I didn't do anything clever with it, I'm new to Jetty, I know very little about Java Web start and other applet related technologies etc. If you can see how the following techniques can be further improved, add a comment (I'd be very interested)!

Embedded HTTP Server in a Browser

Jetty is relatively simple to get started with. The key to embedding it in the browser is applet signing. When you accept the "Security" popup warning you are trusting the applet, as you did with the security pop-up in the Derby demo, you are allowing the applet read and write access to you computer's filesystems. This is how the Derby demo was able to recall data from a previous database session because it had actually written it to your local hard disk! Most of the jar files that come with Jetty need to be signed in order to function correctly when they are invoked by the applet.

For this example I created a self-signed certificate to use for signing the applets.


keytool -genkey -keystore my.store -alias mycert
keytool -export -keystore my.store -alias mycert -file my.cer
jarsigner -keystore my.store bristol.jar mycert

The hypertext documents, images etc. that are going to be accessed by the embedded web server also need to be stored inside a JAR archive in order for the applet to be able to access them. In my first experiment I concentrated on embedding a web server containing static content. In the next experiment I embedded an application server, this can contain dynamic resources (such as JSPs and Servlets).

You can access the applet source code for the embedded web server here. It runs a web server on your machine on port 9090. Try this (at your own risk!) here, it might be a good idea to keep an eye on the Java console to see what is happening as the Jetty server will publish its messages here. This is the HTML code that invokes the applet.

<applet code="bristol.MyApplet.class"
codebase="."
width="1"
height="1"
name="Test"
archive="bristol.jar, files.jar, org.mortbay.jetty.jar, commons-logging.jar, javax.servlet.jar">
</applet>

This applet is responsible for starting and stopping the web server. Once started the content on the embedded web server can be accessed from another browser window (or tab) as long as the original page containing the applet stays open (and therefore the web server continues running).

I had to do a little experimentation in order to establish how to access the static resources from the applet (remember my applet experience is limited) but once I'd got that working it was simply a process of jarring it up and signing the necessary jar files. I didn't write any AJAX style access to the embedded web server content, although you can see how this could easily be done.

With a very simple applet you can start and shutdown an embedded web server but the real potential comes when your able to access more dynamic content.

Embedding Web Application server in a Browser

Again, Jetty provides a relatively simple way to do this. Having already solved the applet resource access problems I'm pretty much home free...or so I thought! I have to admit that I'm a big fan writing JSPs rather than servlets. Jetty supports JSPs but in order for a JSP to run, they must first be compiled. The applet cannot expect to know anything about the system onto which it is being installed and even if it has a Java compiler installed, in fact it is highly likely the target system will only contain a Java Runtime environment.

So I needed to pre-compile my JSP pages before jarring them up and signing them. Fortunately, I found that Ben E. Cline ( a.k.a. Benjy) had used Jetty and precompiled JSP pages for a CD installer. This is incidentally a really cool idea! How easy it would be to running a Jetty powered application server with a search engine like Lucene to provide search facilities for a CD.

So I precompiled the JSPs. I created a directory and copied all my JSP files to it. I then ran JspC in the directory:


java org.apache.jasper.JspC -d . -l -s -uriroot . -compile -webxml webfrag.xml *.jsp

Once JspC had successfully, I copied the "org" subdirectory to my WEB-INF/classes directory in my web app and inserted the lines in the webfrag.xml file into an appropriate web.xml file. I jarred the web application files in my resource file (files.jar). So files.jar now contained:


/index.html
/WebApplication1/index.jsp
/WebApplication1/WEB-INF/web.xml
/WebApplication1/classes/org/apache/jsp/index_jsp.class

I then used the jarsigner to sign this archive and the additional jar files that the web application server needs.

You can access the applet source code for the embedded application server here. Again, this runs on port 9090. Try it (at your own risk!) here. My applet HTML now looks like this:

<applet code="bristol.MyApplet_1.class"
codebase="."
width="1"
height="1"
name="Test"
archive="bristol.jar, files.jar, org.mortbay.jetty.jar, commons-logging.jar, javax.servlet.jar, jasper-runtime.jar, jasper-compiler.jar, commons-el.jar">
</applet>

I have not done anything fancy with the content but you can see how you could install useful servlets and JSP web applications on a local server. Although if you're anything like me you'd soon end up with quite a large collection of related jar files to sign and for the applet to download (but we all have broadband nowadays!)

I've also noticed that if you try one embedded demo followed by another it doesn't always work, you seen the console complaining about ThreadDeath. If you want to see both examples working, it is probably best to close the browser in between.

3 comments:

Mark McLaren said...

Hi Mark,



Very nice blog and good to see you tested it with Jetty...I had done it myself with ACME tiny java web server...



Just a minor correction to the URL for the Java DB demo - it should be:

http://developers.sun.com/prodtech/javadb/overview/product_tour/readme.jsp



to access the readme page content and links...



Cheers,
Note: Comment imported. Original by Francois Orsini website: http://blogs.sun.com/roller/page/FrancoisOrsini at 2006-05-09 18:17

Mark McLaren said...

I created a framework/server called Junction that allows one to run a miniature JavaScript web-app 'server' in the browser (and, on the server, too).



Here's one page that describes the client-side app server runtime.



There's also an todo-list sample app called Next Action that uses Junction and Google Gears.


Note: Comment imported. Original by Steve Yen website: http://trimpath.com at 2007-08-15 16:45

Mark McLaren said...

Really interesting post and discussion! Will add to favourites and look through your archives!
Note: Comment imported. Original by Werbegeschenke website: http://www.werbegeschenke-2008.de/ at 2010-02-01 11:14