Friday, 26 July 2013


Ok, I might as well unveil this thing in case people start wondering what the hell I was talking around 9 months ago.


What was (is) mapguide4j?

mapguide4j was an experiment of mine to dogfood the MapGuide Java wrapper API and test the feasibility of the following things:

1. The feasibility of the Java wrapper to the MapGuide API

The MapGuide Java wrapper is a bit of an unknown quantity. All we knew is that Java ranked the least popular of the 3 development environments in that poll some time ago. Nobody I know has actually showcased a MapGuide application built with the Java wrapper API. So why would this be the case?

  • Was Java just not popular enough?
  • Was the Java wrapper un-reliable?
  • Was the environment setup just too cumbersome?

Despite my reservations about the Java language (which are still true when building this thing), the Java platform is still a major player in the server/enterprise space. The fact that some of the most popular geospatial software written in Java is proof the language and platform are not dying anytime soon.

Could it be the reliability? Possibly. We knew that before the 2.4 release of MapGuide Open Source, this wrapper was leaking memory like a bursting dam. If every "new MgClassName()" statement causes an irrecoverable memory-leak, then it would be no surprise that application reliability/stability would go down the drain

Could it be the cumbersome environment setup? Most likely. The current documentation doesn't really tell you how to actually develop a MapGuide application in Java. Hey, I'd improve this part of the documentation if I myself actually knew but I don't so I am just as clueless as you lot :). Other development environments are easy and well-defined:

  • .net: Start Visual Studio. Make a new application, reference your MapGuide assemblies (or pull them down with nuget) and away you go.
  • PHP: Make a new folder under your www directory, start creating/editing your PHP files with your favourite text editor and away you go.
  • Java: ???

What if you're using Eclipse? Netbeans? IntelliJ IDEA? What do you do? I have no idea!

So yeah, building a MapGuide application in Java is fraught with many question marks about development workflow and reliability, something that we hoped to answer (at least partially) with the mapguide4j project.

2. The feasibility of building a MapGuide Web Tier in a high-level language free of Apache / IIS / Tomcat

Though mapguide4j's focus is on the MapGuide Java wrapper API, the question equally applies to .net and PHP. The default Web Tier ties into Apache or IIS and thus any MapGuide applications you build has to tie into Apache or IIS as well. This default setup can hamper some types of MapGuide applications you want to build, which mapguide4j turned out to be one of these special cases.

3. A truly portable Web Tier in a high-level language

If our fully managed Web Tier was done in .net then you're realistically only gonna be able to run it only on Windows which is not what we want. We wanted the ability to have this Web Tier work on both Windows and Linux in a high level language, so it was either PHP or Java. PHP had the Apache dependency, whereas Java does not (depending on the choice of framework we want to use).

4. Getting re-acquainted with Java

My Java skills were rusty. So mapguide4j was also a convenient exercise in getting re-acquainted with this language (and everything about the language that absolutely annoys me :))

mapguide4j overview

Ok, so I didn't really answer the "what" about mapguide4j (more like the "why"). So I'll answer that here.

mapguide4j, from a high level view can be thought of as a 100% Java version of the MapGuide Web Tier, which currently consists of:
  • The mapagent http interface.
  • The AJAX viewer
  • A REST interface to the MapGuide API
mapguide4j was a testbed for exploring ways to improve one of my perceived shortcomings of MapGuide: The ability to be a powerful geospatial web service platform. Sure we could've done this in C++ like GeoREST, but we get things done much quicker in a higher-level language like Java.

mapguide4j was built on top of the Play Framework (v2.0.4) which was chosen as the Java web application framework of choice for the following reasons:
  • It was easy to pick up and play (pun intended). The only required knowledge was Java. No need to understand Servlets, EJBs, JSPs, and every other Java technology/framework with a 3 letter acronym.
  • Simple installation and deployment.
  • Play uses its own fully self-contained high performance http web server, enabling us to have a fully portable and self-contained Web Tier in 100% Java, provided we had the ability to fully replicate the functionality of the mapagent http interface, which turned out to be true. No need to integrate with Apache or IIS, our Play-based mapguide4j can stand on its own with near zero configuration.
  • Play supports hosting within Apache/Tomcat if we need to use Apache/Tomcat as the front-end server.
mapguide4j is basically the current MapGuide Web Tier + lots of extra web services. Or so that was the plan.

So let's cover the various bits of the mapguide4j Web Tier.

mapagent/AJAX Viewer

This was the most crucial piece of the Web Tier. We needed a mapagent-compatible http interface so that client applications like Maestro can operate against mapguide4j with no modifications, and the quickest way to verify that we have a working mapagent is to bring across the AJAX viewer as well.

The first attempt at replicating the mapagent was to painstakingly map each http operation to its respective implementation (as I pictured it in my mind) using what's available in the MapGuide API. Of course, we then hit the problem of some key viewer operations that cannot be implemented this way. This was when I discovered the true purpose of MgHttpRequest and MgHttpResponse which then lit the proverbial light-bulb and made replicating the http mapagent dead simple.

The AJAX viewer was a simple transplant of the JSP code in the existing Java AJAX viewer to fit within the MVC paradigm of the Play Framework. It does 90% of what the existing AJAX viewer does (the missing 10% is esoteric commands and functionality that's not really used or not implemented, which anyone interested will have to fill in the blanks later on).

The end result is we have a 90% functional AJAX viewer within the Play Framework with a fully-compatible mapagent that can serve requests from existing http client applications like Maestro with little/no compatibility problems.

REST interface

This is where the bulk of the what's unique about mapguide4j lies in. The REST-ful interface is modeled on previous discussions about a theoretical REST-ful web service for MapGuide. If you're wondering if we're duplicating functionality that already exists in GeoREST, we're not actually.

GeoREST is about REST-ification of individual MapGuide Feature Sources and FDO connections. mapguide4j's REST interface is about the REST-ificiation of the mapagent endpoint itself, to be able to tap into a similar set of operations and services in a REST-ful manner through clean, well-defined URLs, where standard HTTP verbs (POST, GET, PUT, DELETE) conceptually map to creation/reading/updating/deletion of associated repository and feature data.

So to illustrate how this works we'll illustrate with the Sheboygan dataset. Here's the resource structure for reference

The mapguide4j REST interface resides under the URL of http://localhost:9000/mapguide/rest

All REST-ful URLs are relative to this base URL. All URL access require a session id parameter passed in or passing standard http authentication

The mapguide4j REST interface has several base URLs under the main base URL:
  • Site Repository access: http://localhost:9000/mapguide/rest/library
  • FDO Provider Registry: http://localhost:9000/mapguide/rest/providers
  • Coordinate System Catalog: http://localhost:9000/mapguide/rest/coordsys
  • Site Admin: http://localhost:9000/mapguide/rest/site
Example REST URLs

MapGuide resource ids already follow a pseudo URI syntax, so the restful URL to a given resource is simply tacking on the path component of the resource and then tacking on various suffixes depending on the desired representation we want back.

So for example, if we wanted a resource listing for a folder, we tack on a /list suffix which will return an XML response by default. For example, if we wanted to list the resources under the root directory, the request would be like this

GET http://localhost:9000/mapguide/rest/library/list

We can tack on specific file extensions for specific representations, so the above request can also be represented as

GET http://localhost:9000/mapguide/rest/library/list.xml

For JSON the request would be:

GET http://localhost:9000/mapguide/rest/library/list.json

List representations are also available in HTML

GET http://localhost:9000/mapguide/rest/library/list.html

It is through the HTML representation that allows us to have a basic rudimentary repository browser to navigate through the repository in the web browser

The HTML representation is also a convenient way to "explore" the other various representations as they are all conveniently hyperlinked for you.

For accessing individual resource content, we tack on a /content suffix. For example if we wanted the resource content of Library://Samples/Sheboygan/Data/Parcels.FeatureSource the request would look like

GET http://localhost:9000/mapguide/rest/library/Samples/Sheboygan/Data/Parcels.FeatureSource/content

Again, we can plug in the desired file extension for certain representations

GET http://localhost:9000/mapguide/rest/library/Samples/Sheboygan/Data/Parcels.FeatureSource/content.xml

GET http://localhost:9000/mapguide/rest/library/Samples/Sheboygan/Data/Parcels.FeatureSource/content.json

We'll stop right here because going through all the possible URLs would take forever. But hopefully this gives you the idea of what can be done through this REST interface. You can see example URLs through this link or through exploring the HTML representation list views that provides hyperlinked URLs to all the various supported representations.

Basically most resource and feature service APIs can be accessed via the REST interface

... and that's when everything stopped and ground to a halt.

I haven't actually touched this project in months, so rather than leave this project languishing into nothingness, I'm decided to re-purpose mapguide4j as a giant piece of sample code that should hopefully give you some ideas as to what you can do with the MapGuide API in Java.

You can check out mapguide4j at my GitHub. Unlike my other open source handiwork, I've picked the most liberal OSS license (MIT) I won't be doing anything more with this code. Feel free to fork/clone/hack it to your heart's content.

For me, I achieved what I wanted to know with mapguide4j. It proved to me that it was indeed possible to build some powerful web services on top of the MapGuide API and more importantly, to do it all in Java.


Jody Garnett said...

Thanks for the excellent integration work.

GeoTools does support a light-weight community plugin space. You may be able to set up a module to cover integration between GeoTools and mapguidej

Jackie Ng said...

Nothing's actually integrated with GeoTools. That's a void someone interested can fill in.