Monday, April 24, 2006

Google SSO, GData and X-GOOGLE-TOKEN

The details of Google's Account Authentication Proxy for Web Applications are not yet available but it looks likely that this is the basis of a Google Single Sign-On (SSO) service. Applications using this service will be able to make use of Google's GData enabled applications (calendar, blogger, mail etc). You would expect that in due course there would be third party server applications interested in supporting the GData protocol.

Google has whetted our appetites with the Google Data API with emphasis on the calendar functionality. I hope they remember the open source mantra, release early, release often and don't make us wait too long before the full disclosure of Google's proxy authentication mechanism (expected release date is the end of this month [April 2006]) and the details of the other GData enabled services. Google have been criticised in some quarters for not contributing enough back to the open source community and this represents an excellent opportunity to make amends.

Having had experience with JASIG CAS I know a little about how single sign-on for web applications work. I discovered a very interesting article detailing The Mysteries of X-GOOGLE-TOKEN and why it matters which describes a curious proprietary token-based authentication mechanism that Google Talk uses. It appears to behave exactly as I would expect Google's SSO proxy mechanism to work. It seems like Google SSO may have been in in the wild all along and we just haven't realised it!

I think it is a fairly safe bet that X-GOOGLE-TOKEN will emerge in the proxy authentication part of the GData protocol.

There are some suggestive indications of how the proxy mechanism will work in the GData API, if for example you look at one of the constructors for GoogleService:

GoogleService(java.lang.String serviceName, java.lang.String applicationName, java.lang.String protocol, java.lang.String domainName)
Constructs a GoogleService instance connecting to the service with name serviceName for an application with the name applicationName.

I would expect that I could create a GoogleService instance with my local applicationName and domainName as arguments. This could authenticate against Google's SSO and call my local application back following authentication. Google SSO would send back the details necessary to validate authentication and conduct further proxied authentication making use of the X-GOOGLE-TOKEN, SID and LSID tokens mentioned in the Google Talk article.

Note also how the GData API constant GOOGLE_LOGIN_PATH of /accounts/ClientLogin is exactly the same URL as Google Talk uses for authentication.

Although I feel that there are now lots of clues, my feeling is there are still some missing pieces of the jigsaw. An anonymous source suggested that they thought that the X-GOOGLE-TOKEN mechanism might be enabled via "a piece of copypaste JS code". I would agree with this idea to some extent, however, we now know that the favoured GData client mechanisms are Java and C#. Therefore I would speculate that much like the Google Maps API requires a key, the Google Proxy Authentication Service would make similar demands on would-be SSO application clients.

Friday, April 21, 2006

GData is about more than Google Calendar integration

Hi, I'm Mark and I'm a Google powered shiny baubles addict. Last Thursday (or there abouts) Google launched Google Calendar. It works in a fiendishly clever and impressive way, Google has raised the bar so high that we have come to expect nothing less of their web application offerings (I won't mention the A word but expect it is in there).

A couple of days later and Google have launched the Google Calendar data API. The Google Calendar data API is based upon a new common API model called GData. Impressive as the calendar application is, reading between the lines it is actually GData that looks set to have longer lasting significance (see ZDNet article on GData, Google: Master of Space and (Now) Time [found this via What's Google Calendar Really About ]).

GData is still slightly shrouded in mystery at the moment, the full details are yet to be fully disclosed but there are some really tantalizing glimpses around.

Quoting the Google Code announcement "GData model uses REST principles and Atom or RSS 2.0 syndicated feeds as the base resource model to expose data held by Google services (like Google Calendar)".

The GData protocol is also set to provide an Authentication service, this looks like it might provide a single sign-on solution for web applications.

There are client libraries for GData in Java and C#(.NET) flavours as well as detailed descriptions of the bare GData web service style XML protocol requests (so that scripting languages need not miss out).

This all sounds a bit like the beginnings of a Google powered enterprise portal to me. Integration of Google's own applications is already starting to happen, little chunks of Google Calendar are starting to surface inside Gmail. Fellow portal developers will appreciate that single sign-on is usually the key sticking point for portal integration. Every system I try and integrate with wants to be the "single" gateway, it wants to be the portal. Recent examples I've worked with include Blackboard (don't ask!) and Oracle applications (just try and get Oracle Collaboration Suite applications to integrate without using Oracle Single Sign-On). I'm slightly concerned that there might now be a Google single sign-on service (just how many *single* sign-on services should I be expected to integrate with!)

Controlling the single sign-on gateway is about maintaining power, the ability to access Google's fantastic calendar, mail, blogs, feed readers, web storage and other future services might prove a very seductive draw even if it doesn't play nice with external systems.

Google's decision to place it's efforts behind the Atom format is also starting to make sense to me. Although to be fair the GData protocol supports Atom and RSS 2.0. I must admit I don't know much about the Atom API, as used by Google's blogger.com, but its seems to be about reading and writing information on the web (e.g. content management for blogs). GData's introduction of REST seems to be an attempt to make the whole Atom API approach easier. GData is also extending the Atom API approach to include other common elements information (what Google refer to as "Kinds") such as capturing calendar information.

Great that is all we need, a whole new set of standard formats to integrate with and there I was complaining about Microsoft proprietary RSS extensions! Yahoo's Upcoming.org have already integrated with the new Google Calendar format. I really don't mean to moan; I'm very excited about Google's GData offering and very much look forward to seeing what is coming next.

Thursday, April 06, 2006

Bookmarks Portlet version 0.2 released

I have just released a new version of my bookmarks portlet application.

More details here

Downloads here

Functional Features

  • Add, Edit, Delete bookmarks and folders
  • Simple bookmarks management (moving of bookmarks and folders)
  • Import, Append and Export of the standard bookmarks format (de facto Netscape DTD standard which is used by all leading browsers)
  • Alphabetical bookmarks sort

Technical Details

  • 100% scriptlet free
  • JSR168 compatible portlet
  • Runs as a portlet and as a standalone web application simultaneously (achieved with Struts Bridge)
  • Written in an accessible spirit using unobtrusive DHTML rendering
  • XBEL is used throughout internally to store and manipulate bookmarks
  • XBEL object representation built with Castor used to manipulate bookmarks
  • XSL transformations used in rendering and sorting bookmark trees
  • Tidy utility used to XMLize and clean up bookmark imports
  • MVC architecture implemented with Apache Struts and JSTL
  • Database and resource access enabled with the Spring Framework
  • Includes an example embedded database, simple authentication and optionally a simple portal

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.

Monday, April 03, 2006

My bad, I've started to autowire with Spring

In a web application I have been writing recently I needed a way to initialise an embedded database and additionally setup some other resources.

This is usually ServletContextListener territory but since I am using a Spring Framework enabled database access layer I needed a method that gives me access to Spring's BeanFactory mechanisms. I could create a ServletContextListener that accessed the BeanFactory details from the ServletContext (as set by Spring's ContextLoaderListener) but then the order of the ServletContextListeners in the web.xml would become significant, so I didn't favour that approach.

I created a bean that implemented the Spring Framework's interfaces; ServletContextAware, BeanFactoryAware and InitializingBean. It therefore contains the methods; setServletContext(ServletContext servletContext), setBeanFactory(BeanFactory beanFactory) and afterPropertiesSet().

An InitializingBean is invoked by the BeanFactory immediately after the applicationContext.xml (containing the bean definitions) is finished processing.

So what I end up with is a class that has ready access to the ServletContext and BeanFactory and is invoked immediately after the ContextLoaderListener has finished initialisation.

In essence, this is equivalent to a Spring aware ServletContextListener. Great, this is exactly what I need. However this bean works exclusively by autowiring which is bad apparently! Jason Zhicheng Li in his OnJava.com article Twelve Best Practices For Spring XML Configurations lists autowiring as the number one thing to avoid when using Spring.

The reason this is bad is that my ServletContextListener style bean makes no appearance in the web.xml. The properties of this bean are set by introspection conducted by the application context and not by any explicit reference in the configuration file to the dependencies that get injected.

So to the casual observer it must look like it works by magic! It is argued that autowiring may reduce readability and maintainability. The problem is I'm not actually sure how I could accomplish this without using autowiring.