(picture)

July 07, 2004

Minimal App-Launcher (part one)

Here's a first, minimal example of the "app-launcher" extension mechanism for Groove V3. As I hinted earlier, this is a straightforward framework that lets developers build applications integrating really nicely with the Groove launchbar and with Groove's decentralized platform -- consistent, secure, shared data models; awareness, presence, instant messaging -- without requiring the application to "live in Groove".

In fact, it's possible to have a single version of your app which "knows" when it's being run from a Groove context, by having Groove launch it with a special set of commandline parameters, and use that to switch on whatever collaborative features might be important (without preventing its use as a standalone app).

The standard commandline, though, is what gives your app its context. Remember, in this application model your program "has" a Groove workspace "underneath" it, and can use that workspace to share with other instances of the program running at other users' machines. Each member of the workspace (ie. anyone you invited, just as with any Groove space) has a synchronized copy of the data in the space. But when they open the workspace, instead of the Groove user interface, your application is launched.

So the two basic commandline parameters are: the "IdentityURL" of the current user, and the URI of the current workspace. [There's a third -- the verb with which the application was launched -- but in my minimal sample I've no need to use that]. The URI is the Groove Web Services address of the workspace: the space can be accessed by POSTing SOAP messages to that identifier.

So, here's my sample code. I've called it "Minimal". There's not even any compiled code there; the application is an HTA (DHTML and JavaScript). If you download the zip and look at the .HTA file with a text editor, you'll see how the application works. (More on that below the fold here).

The app has its own icon in launchbar:

although maybe the user interface of my application could use some work:

Still to come in the next instalment: some words about the half-dozen support files other than the HTA. They're fairly intricate, but not scary. (I made mine almost entirely by search-and-replace from the AppLauncher sample which ships with the v3 Groove developer kit).

The app

When the HTA loads, it looks at its commandline, to find the two parameters given it by Groove: these are held in global variables "g_sSpaceURI" and "g_sIdentityURL".

Pressing the "Space information" button calls a function ShowSpaceInfo(), which sends a SOAP packet to Groove. The packet's body is a regular SOAP envelope, with some Groove stuff in the header, and in the body an empty ReadSpace element. The packet is sent to http://localhost:9080/xxx, where xxx is the URI of the space (which we were given on the commandline).


POST /GWS/Groove/2.0/Spaces/grooveTelespace/r7vj56b9syzk6rjuucfk5usdzv8esrw85vfxu5i HTTP/1.1
Accept: */*
Accept-Language: en-us
Content-Type: text/xml
Accept-Encoding: gzip, deflate
Host: localhost:9080
Content-Length: 601
Connection: Keep-Alive
Cache-Control: no-cache

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Header>
<GrooveRequestHeader xmlns="http://webservices.groove.net/Groove/2.0/Core/">
<GrooveIdentityURL>grooveIdentity://fswbv2ws5visbxuzvfwf4hhmfi37y5fe@</GrooveIdentityURL>
<GrooveRequestKey>ze5pd93wpiehvg6pycxmby734ffayrukruq7pys</GrooveRequestKey>
</GrooveRequestHeader>
</soap:Header>
<soap:Body><ReadSpace xmlns="http://webservices.groove.net/Groove/2.0/Spaces"/></soap:Body>
</soap:Envelope>

Groove returns an XML fragment with information about the space: its name, and so on.

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 1426

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Header>
<GrooveResponseHeader xmlns="http://webservices.groove.net/Groove/2.0/Core/">
<GrooveResponseKey>cy2kmmbcyqv8h7d92ecate47e6swqc774r7trui</GrooveResponseKey>
</GrooveResponseHeader>
</soap:Header>
<soap:Body>
<ReadSpaceResponse xmlns="http://webservices.groove.net/Groove/2.0/Spaces">
<ReadSpaceResult>
<URI>/GWS/Groove/2.0/Spaces/grooveTelespace/r7vj56b9syzk6rjuucfk5usdzv8esrw85vfxu5i</URI>
<Name>Minimal space</Name>
<Description>
</Description>
<Created>2004-07-07T21:32:32.551-05:00</Created>
<Modified>2004-07-07T21:32:43.737-05:00</Modified>
<Local>true</Local>
<IdentityURL>grooveIdentity://fswbv2ws5visbxuzvfwf4hhmfi37y5fe@</IdentityURL>
<Tools>/GWS/Groove/2.0/Tools/grooveTelespace/r7vj56b9syzk6rjuucfk5usdzv8esrw85vfxu5i</Tools>
<Members>/GWS/Groove/2.0/Members/grooveTelespace/r7vj56b9syzk6rjuucfk5usdzv8esrw85vfxu5i</Members>
<Unread>0</Unread>
<Type>urn:cabezal.com:TelespaceTypes.Minimal</Type>
<LocalURI>/GWS/Groove/2.0/Local/grooveTelespace/r7vj56b9syzk6rjuucfk5usdzv8esrw85vfxu5i</LocalURI>
<Version>
<Major>15</Major>
<Minor>-1</Minor>
<Custom>-1</Custom>
<Sequence>-1</Sequence>
</Version>
</ReadSpaceResult>
</ReadSpaceResponse>
</soap:Body>
</soap:Envelope>

Of course, if we wanted this sample to do anything really interesting, then building SOAP packets by hand would be a really stupid approach. It does let you see exactly what's happening, though.

For a larger application, you should point your favourite development environment at the Groove-supplied WSDL and have it build you some handy proxy classes to make these calls. We're assuming that .NET is the way most people will want to do this, although the Groove dev kit comes with some perl samples, and I'd hope to see some examples using Python and Java sometime too.