Using Groovy to import XML into MongoDB

This year I've been demonstrating how easy it is to create modern web apps using AngularJS, Java and MongoDB. I also use Groovy during this demo to do the sorts of things Groovy is really good at - writing descriptive tests, and creating scripts.

Due to the time pressures in the demo, I never really get a chance to go into the details of the script I use, so the aim of this long-overdue blog post is to go over this Groovy script in a bit more detail.

Firstly I want to clarify that this is not my original work - I stole borrowed most of the ideas for the demo from my colleague Ross Lawley. In this blog post he goes into detail of how he built up an application that finds the most popular pub names in the UK. There's a section in there where he talks about downloading the open street map data and using python to convert the XML into something more MongoDB-friendly - it's this process that I basically stole, re-worked for coffee shops, and re-wrote for the JVM.

I'm assuming if you've worked with Java for any period of time, there has come a moment where you needed to use it to parse XML. Since my demo is supposed to be all about how easy it is to work with Java, I did not want to do this. When I wrote the demo I wasn't really all that familiar with Groovy, but what I did know was that it has built in support for parsing and manipulating XML, which is exactly what I wanted to do. In addition, creating Maps (the data structures, not the geographical ones) with Groovy is really easy, and this is effectively what we need to insert into MongoDB.

Goal of the Script

  • Parse an XML file containing open street map data of all coffee shops.
  • Extract latitude and longitude XML attributes and transform into MongoDB GeoJSON.
  • Perform some basic validation on the coffee shop data from the XML.
  • Insert into MongoDB.
  • Make sure MongoDB knows this contains query-able geolocation data.

The script is PopulateDatabase.groovy, that link will take you to the version I presented at JavaOne:

PopulateDatabase.groovy

Firstly, we need data

I used the same service Ross used in his blog post to obtain the XML file containing "all" coffee shops around the world. Now, the open street map data is somewhat... raw and unstructured (which is why MongoDB is such a great tool for storing it), so I'm not sure I really have all the coffee shops, but I obtained enough data for an interesting demo using

http://www.overpass-api.de/api/xapi?*[amenity=cafe][cuisine=coffee_shop]

The resulting XML file is in the github project, but if you try this yourself you might (in fact, probably will) get different results.

Each XML record looks something like:

<node id="178821166" lat="40.4167226" lon="-3.7069112">
    <tag k="amenity" v="cafe"/>
    <tag k="cuisine" v="coffee_shop"/>
    <tag k="name" v="Chocolatería San Ginés"/>
    <tag k="wheelchair" v="limited"/>
    <tag k="wikipedia" v="es:Chocolatería San Ginés"/>
</node>

Each coffee shop has a unique identifier and a latitude and longitude as attributes of a node element. Within this node is a series of tag elements, all with k and v attributes. Each coffee shop has a varying number of these attributes, and they are not consistent from shop to shop (other than amenity and cuisine which we used to select this data).

Initialisation

Script Initialisation

Before doing anything else we want to prepare the database. The assumption of this script is that either the collection we want to store the coffee shops in is empty, or full of stale data. So we're going to use the MongoDB Java Driver to get the collection that we're interested in, and then drop it.

There's two interesting things to note here:

  • This Groovy script is simply using the basic Java driver. Groovy can talk quite happily to vanilla Java, it doesn't need to use a Groovy library. There are Groovy-specific libraries for talking to MongoDB (e.g. the MongoDB GORM Plugin), but the Java driver works perfectly well.
  • You don't need to create databases or collections (collections are a bit like tables, but less structured) explicitly in MongoDB. You simply use the database and collection you're interested in, and if it doesn't already exist, the server will create them for you.

In this example, we're just using the default constructor for the MongoClient, the class that represents the connection to the database server(s). This default is localhost:27017, which is where I happen to be running the database. However you can specify your own address and port - for more details on this see Getting Started With MongoDB and Java.

Turn the XML into something MongoDB-shaped

Parse & Transform XML

So next we're going to use Groovy's XmlSlurper to read the open street map XML data that we talked about earlier. To iterate over every node we use: xmlSlurper.node.each. For those of you who are new to Groovy or new to Java 8, you might notice this is using a closure to define the behaviour to apply for every "node" element in the XML.

Create GeoJSON

Create GeoJSON Since MongoDB documents are effectively just maps of key-value pairs, we're going to create a Map coffeeShop that contains the document structure that represents the coffee shop that we want to save into the database. Firstly, we initialise this map with the attributes of the node. Remember these attributes are something like:

<node id="18464077" lat="-33.8911183" lon="151.1958773">

We're going to save the ID as a value for a new field called openStreetMapId. We need to do something a bit more complicated with the latitude and longitude, since we need to store them as GeoJSON, which looks something like:

{ 'location' : { 'coordinates': [<longitude>, <latitude>],
                 'type'       : 'Point' } }

In lines 12-14 you can see that we create a Map that looks like the GeoJSON, pulling the lat and lon attributes into the appropriate places.

Insert Remaining Fields

Insert Remaining Fields

Validate Field Name

Now for every tag element in the XML, we get the k attribute and check if it's a valid field name for MongoDB (it won't let us insert fields with a dot in, and we don't want to override our carefully constructed location field). If so we simply add this key as the field and its the matching v attribute as the value into the map. This effectively copies the OpenStreetMap key/value data into key/value pairs in the MongoDB document so we don't lose any data, but we also don't do anything particularly interesting to transform it.

Save Into MongoDB

Save Into MongoDB

Finally, once we've created a simple coffeeShop Map representing the document we want to save into MongoDB, we insert it into MongoDB if the map has a field called name. We could have checked this when we were reading the XML and putting it into the map, but it's actually much easier just to use the pretty Groovy syntax to check for a key called name in coffeeShop.

When we want to insert the Map we need to turn this into a BasicDBObject, the Java Driver's document type, but this is easily done by calling the constructor that takes a Map. Alternatively, there's a Groovy syntax which would effectively do the same thing, which you might prefer:

collection.insert(coffeeShop as BasicDBObject)

Tell MongoDB that we want to perform Geo queries on this data

Add Geo Index

Because we're going to do a nearSphere query on this data, we need to add a "2dsphere" index on our location field. We created the location field as GeoJSON, so all we need to do is call createIndex for this field.

Conclusion

So that's it! Groovy is a nice tool for this sort of script-y thing - not only is it a scripting language, but its built-in support for XML, really nice Map syntax and support for closures makes it the perfect tool for iterating over XML data and transforming it into something that can be inserted into a MongoDB collection.

Getting Started with MongoDB and Java

We've been missing an introduction to using MongoDB from Java for a little while now - there's plenty of information in the documentation, but we were lacking a step-by-step guide to getting started as a Java developer.

I sought to rectify this with a couple of blog posts for the MongoDB official blog: the first, an introduction to using MongoDB from Java, including a non-comprehensive list of some of the libraries you can use; the second, an introductory guide to simple CRUD operations using the Java driver:

Continue reading "Getting Started with MongoDB and Java"

Converting Blogger to Markdown

I've been using Blogger happily for three years or so, since I migrated the blog from LiveJournal and decided to actually invest some time writing. I'm happy with it because I just type stuff into Blogger and It Just Works. I'm happy because I can use my Google credentials to sign in. I'm happy because now I can pretend my two Google+ accounts exist for a purpose, by getting Blogger to automatically share my content there.

A couple of things have been problematic for the whole time I've been using it though:

  1. Code looks like crap, no matter what you do.
  2. Pictures are awkwardly jammed in to the prose like a geek mingling at a Marketing event.

The first problem I've tried to solve a number of ways, with custom CSS at a blog- and a post- level. I was super happy when I discovered gist, it gave me lovely content highlighting without all the nasty CSS. It's still not ideal in a blogger world though, as the gist doesn't appear in your WYSIWYG editor, leading you to all sorts of tricks to try not to accidentally delete it. Also I was too lazy to migrate old code over, so now my blog is a mish-mash of code styles, particular where I changed global CSS mulitple times, leaving old code in a big fat mess. There's a lesson to be learned there somewhere.

The second problem, photos, I just gave up on. I decided I would end up wasting too much time trying to make the thing look pretty, and I'd never get around to posting anything. So my photos are always dropped randomly into the blogs - it's better than a whole wall of prose (probably).

But I've been happy overall, the main reason being I don't have to maintain anything, I don't have to worry about my web server going down, I don't have versions of a blog platform to maintain, patch, upgrade; I can Just Write.

But last week my boss and my colleague were both on at me to try Hugo, a site generator created by my boss. I was resistent because I do not want to maintain my own blog platform, but then Christian explained how I can write my posts in markdown, use Hugo to generate the content, and then host it github pages. It sounded relatively painless.

I've been considering a move to something that supports markdown for a while, for the following reasons:

  1. These days I write at least half of my posts on the plane, so I use TextEdit to write the content, and later paste this into blogger and add formatting. It would be better if I could write markdown to begin with.
  2. Although I've always disliked wiki-type syntax for documentation, markdown is actually not despicable, and lets me add simple formatting easily without getting in my way or breaking my flow.

So I spent a few days playing with Hugo to see what it was, how it worked, and whether it was going to help me. I've come up with a
few observations:

Hugo really is lightning fast. If I add a .md file in the appropriate place, and with the Hugo server running on my local machine it will turn this into real HTML in (almost) less time than it takes for me to refresh the browser on the second monitor. Edits to existing files appear almost instantly, so I can write a post and preview it really easily. It beats the hell out of blogger's Preview feature, which I always need to use if I'm doing anything other than posting simple prose.

It's awesome to type my blog in IntelliJ. Do you find yourself trying to use IntelliJ shortcuts in other editors? The two I miss the most when I'm not in IntelliJ are Cmd+Y to delete a line, and Ctrl+Shift+J to bring the next line up. Writing markdown in IntelliJ with my usual shortcuts (and the markdown plugin) is really easy and productive. Plus, of course, you get IntelliJ's ability to paste from any item in the clipboard history. And I don't have to worry about those random intervals when blogger tells me it hasn't saved my content, and I have no idea if I will just lose hours of work.

I now own my own content. It never really occurred to me before that all the effort I've put into three years of regular blogging is out there, on some Google servers somewhere, and I don't have a copy of that material. That's dumb, that doesn't reflect how seriously I take my writing. Now I have that content here, on my laptop, and it's also backed up in Github, both as raw markdown and as generated HTML, and versioned. Massive massive win.

I have more control over how things are rendered, and I can customise the display much more. This has drawbacks though too, as it's exactly this freedom-to-play that I worry will distract me from actual writing.

As with every project that's worth trying, it wasn't completely without pain. I followed the (surprisingly excellent) documentation, as well as these guidelines, but I did run into some fiddly bits:

  1. I couldn't quite get my head around the difference between my Hugo project code and my actual site content to begin with: how to put them into source control and how to get my site on github pages. I've ended up with two projects on github, even though the generated code is technically a subtree of the Hugo project. I think I'm happy with that.
  2. I'm not really sure about the difference between tags, keywords, and topics, if I'm honest. Maybe this is something I'll grow into.
  3. I really need to spend some time on the layout and design, I don't want to simply rip off Steve's original layout. Plus there are things I would like to have on the main page which are missing.
  4. I needed to convert my old content to the new format
  5. Final migration from old to new (incomplete)

To address the last point first, I'm not sure yet if I will take the plunge and do full redirection from Blogger to the new github pages site (and redirect my domains too), for a while I'm going to run both in parallel and see how I feel.

As for the fourth point, I didn't find a tool for migrating Blogger blogs into markdown that didn't require me to install some other tool or language, and there was nothing that was specifically Hugo-shaped, so I surprised myself and did what every programmer would - I wrote my own. Surprising because I'm not normally that sort of person - I like to use tools that other people have written, I like things that Just Work, I spend all my time coding for my job so I can't be bothered to devote extra time to it. But my recent experiences with Groovy had convinced me that I could write a simple Groovy parser that would take my exported blog (in Atom XML format) and turn it into a series of markdown files. And I was right, I could. So I've created a new github project, atom-to-hugo. It's very rough, but a) it works and b) it even has tests. And documentation.

I don't know what's come over me lately, I've been a creative, coding machine.

In summary, I'm pretty happy with the new way of working, but it's going to take me a while to get used to it and decide if it's the way I want to go. At the very least, I now have my Blogger content as something markdown-ish.

But there are a couple of things I miss about Blogger:

  1. I actually like the way it shows the blog archive on the right hand side, split into months and years. I use that to motivate me to blog more if a month looks kinda empty
  2. While Google Analytics is definitely more powerful than the simple blogger analytics, I find them an easier way to get a quick insight into whether people are reading the blog, and which paths they take to find it.

I don't think either of these are showstoppers, I should be able to work around both of them.

In my day…

Web development has changed a lot.

I was aware that there have been many changes in the last few years, and I’ve seen maturity come to web platforms in the form of standardisation and common reusable libraries and frameworks - and I don’t mean reusable in the way we used to “reuse” stuff by nicking it off other people’s websites when we saw something cool.

I used to be a web developer. Sort of. Some times I’ve been on the bleeding edge, and others... I remember using JavaScript to call back-end services with an XML payload before people were using the term AJAX, but I also remember working on an enterprise um... “classic”... JSP application only “recently” - in fact that was probably the last job where I did anything that looked like web development.

So this blog post is going to chart the progress of web development through my own experience. Of course, this doesn’t by any means cover the whole spectrum, but I think my experience has been not unusual for a Java programming working through the noughties.

Over the course of my career I moved further away from the UI, because certainly early on the money and status was in “back end”, whatever that means, and not “front end”. Which is ridiculous, really, especially as back then you couldn’t really follow best practices and clean code and test first and all that awesome stuff when doing front end development because none of the browsers played by the rules and frankly if you got it working at all you were a bloody genius. And that’s not even considering the fact that as a “front end” developer you should be thinking about actual real human beings who use your product, and actual real human beings are messy things and understanding them is not (we’re told) traditionally a domain that we developers are naturally proficient in.

Anyway, I digress. This was supposed to be a history lesson. Or a nostalgia trip. Or possibly Ranty Trish waving her walking stick in the air and shouting “You kids don’t know how good you’ve got it these days”. If nothing else, I hope that it makes other “back end” developers like myself appreciate how much things have moved on.

Let’s go back to the olden days, before I’d even graduated: picture a time before smart phones - before phones were even common (I was horribly mocked at university for being poncy enough to have a mobile), before we knew if all this work we were doing to combat the millennium bug was going to stop the end of the world. I was doing my first summer internship at Ford, and a contractor from Logica (who don't seem to exist any more??) told me that if I was messing around with web pages and HTML (my friends and I had geocities-and-equivalent sites) I should look at this JavaScript thing to make my pages “dynamic”. I didn’t have to just use GIFs to bring my page to life, I could move stuff around on the page. I think I wrote a “you are in a crowded room”-type adventure game, because my background was BASIC and that’s what you do.

Actually I haven’t even mentioned that we were creating these websites to stay in touch with each other. We’d discovered guest books, and used them to write comments and share stories since we’d all moved out of our home town to go to different universities. Man, why didn’t I invent Facebook back then? That’s what we needed.

Anyway.

A year later, I was back at Ford doing my sandwich year-in-industry. The first project I worked during this time was a web-based reporting tool that needed to dynamically display hierarchical data. We chose JavaScript trees to render this data - my year of messing around with my website paid off, and I was able to use my “cutting edge” Javascript skills in a real production environment. Yay? The back end was CGI - I think I was writing in Perl, but don’t tell anyone that. I was learning Java at university, but this was a new language and I don’t think Ford was using it yet.

The next project was a very ambitious one - be the first car manufacturer to sell new cars on the web. Ford was well ahead of their time - the millennium bug had not killed us all, but people were barely buying books online, never mind spending tens of thousands of pounds on a car they’d never driven. But it wasn’t just ahead of its time from a business point of view, technically it was very advanced too - we used lots of “DHTML” (as we were now calling it), a new-fangled technology called ASP, and we were writing modular, reusable COMponents. We used XSLT to parse the XML from the COM objects, and the ASP figured out whether you were Netscape or Internet Explorer (Firefox wasn’t even a gleam in the inventor’s eye, and forget Chrome, I think we using Alta Vista (whaaaat? AltaVista got bought by Yahoo??) not some new-fangled search engine beginning with G) so it could use the right XSLT to turn the XML into HTML that was readable by the browser you were using. My job was to get the DHTML pages rendering and animating correctly in both IE4 and Netscape 4. That was a lot of fun for me, but also very challenging. And imagine my shock when a few months later I tested the site from the university UNIX machines to find that Netscape rendered it completely differently under UNIX. I learnt a lesson about how important it was to test on different platforms.

We had some smart Microsoft people helping us out with this project, and, because it was 2000 and the dot com crash hadn’t happened just yet, we also had a lot of young, overpaid, overconfident contractors who believed anything was possible. I learnt a lot during this time, not just about the technology, but also about different approaches to shaping your IT career. And about how much you could earn before you were 25. I was definitely going to be a programmer when I left university the next year.

Yeah, so... I graduated in 2001. If you were around then, you’ll remember that getting a job was a bit more difficult than I had anticipated, especially as these young, overpaid contractors were now desperately grabbing anything they could find. But that’s a story for another day.

I didn’t go back to Ford straight away, I’d “been there and done that”. I worked on the website for Common Purpose. On the first day, they sat me down with a book on JSP and Servlets, and that was my reading material for the next few weeks. If I’d been fresh out of university where we’d been doing Applets, and where I’d written a Swing app on the side for my Dad’s school, this would have been a big mindset change for me. But having worked on the ASPs it wasn’t such a big shift. I did, however, like how JSPs and servlets made the separation between the view and all-of-the-other-logic-stuff a bit clearer - back in ASP-land we’d settled on a convention of dealing with the form data from the previous page in the first part of the ASP, and rendering the new page in the second part. To this day I still don’t know what we should have been doing instead. But in JSP-land it only took me... I dunno, about 6 months I think, to get the website up and running. The most difficult section was registrations. And yes, I was a graduate, and yes, I was new, but that was a good turnaround for a web application “in those days”.

In my spare time I used what I’d learnt on the blews website. I even had a section where people could log in and comment on photos - we had whole conversations on this website. It was a way for me and my friends to stay in touch. If I’d cracked the photo-uploading instead of it being a manual process for me, I would have invented Facebook. If only I’d known....

The work dried up and there was nothing else for a graduate in the early noughties, so I went back to Ford. My first role back I picked the same technologies we’d been using before - XML, XSLT, only this time we were using JSPs instead of ASP. Our project had a very tight budget and we’d worked out that using open source Java technologies and running the application on one of the many UNIX machines lying around the place was a lot cheaper than the Microsoft solution. I think we were the first team in Ford Europe to pick Java at a time when the recommended approach was Microsoft. We delivered on time and under budget, and Java was the way forward for the department from then on. But on this project I met a guy who would impact my career probably more than he even realises, a guy I’d work with again later. He told me that in Java we no longer used Vector by default, but ArrayList (whaaat? What’s an ArrayList? I had no idea what the differences were between Java 1.1, which we’d learnt at university, and Java 1.2, which was now standard). And questioned my choice of XML/XSL. Although I’d been learning new technologies and growing, he was the one who made it clear to me that I needed to keep myself ahead of the curve with the technologies I was using, or planned to use, if I wanted to stay relevant and make my life easier.

On the next project I worked with a genius guy who was definitely keeping ahead of the curve - he was using JavaScript to send small XML payloads to the server (which was coded in Java), and rendering the response in place on the page instead of reloading the whole thing. Mind. Blown. I didn’t even hear the term Ajax until a year or more later. We were fortunate in that this was once again an internal application, so we controlled the browser. This was back in the days when you wanted your users to be on IE5, as this was the only browser that supported this functionality.

The next few projects/jobs I worked on were all more pedestrian variations on the JSP theme - first I learnt Struts, which at least made us realise there was a model, a view, and a controller. Then at Touch Clarity I learnt about Spring MVC, which actually put the validation errors next to the boxes which cause the error - by default, without you having to mess around. Spring was a revelation too, a framework that really tried not to get in your way. It was also frustrating because you needed to understand its lifecycle, but it did so much heavy lifting for you, it sped up standard CRUD-app web development enormously.

A couple of years passed, during which time I was still working on a web application (for an investment bank) but I can’t for the life of me remember what technologies we used (other than Java). I know it was hard to test and I know the tricky stuff was “back end” not “front end”.

In the next project where I had any control of the technology, I picked Spring since I’d had such a good experience previously. It took 4 developers a couple of months or so to develop an admin application for a trading app. Given the previous timescales I’d worked with, this seemed pretty good. Until a few months later and two other guys on the project produced an admin app for our bank users in a matter of weeks. I can’t remember what they used, maybe Grails? But it was another demonstration of how I really should have been researching the field instead of simply sticking with what I knew, especially when I knew my knowledge was a couple of years out of date.

Fast forward to LMAX, and we were using GWT, pre-2.0 - I think this probably feels natural if you’ve been a Swing or AWT developer, but I’m still not convinced it’s a sound web platform (although I know it has improved). It was great because cross-browser was no longer an issue, but it was bad because it separates you from the underlying HTML, which means you can seriously mess up without realising. It’s also hard to use CSS correctly when you don’t have access to all the HTML components.

So we come to more-or-less the present day, as it should be fairly obvious that during the time I’ve been working on the MongoDB Java Driver I haven’t done a lot of GUI development. I’m lucky because attending lots of conferences means I see a lot more of the current-trending technologies, but up until a couple of weeks ago I hadn’t had a chance to play with any of them.

So now I’ve been trying Angular.js, Bootstrap, and UI Bootstrap. My goodness. It’s a whole 'nother world. I’m seeing at conferences and user groups that developers are increasingly polyglot, so maybe there’s no such thing as “just” a Java developer any more, but if you are “just” a Java developer, I think it could be... interesting... to get your head around some of the techniques. Since we don’t have closures, our callbacks are ugly and we tend not to program that way. Async is not something that comes naturally in a Java environment, I believe, although after working that way at LMAX I’m personally sold on it. Old-world JavaScript developers like I am/was might also find it hard to understand you can have clean, testable JavaScript code which Just Works. It didn’t even occur to me to worry about browser compatibility, and my app not only worked on my phone as well as my laptop, but looked really phone-ish and awesome with very minimal effort.

I’m currently on a plane on the way to QCon London where I’m going to demo this Brave New World of web development (together with a nice Java back end to prove how awesome Java is to work with and, of course, a MongoDB database). So it is not my intention in this post to explore what this new world looks like. But I have seen the Present, and it’s a lot better than the Past. Kids These Days don’t know how good they’ve got it - they’ve never had to struggle, to fight the browser, to hand-craft their JavaScript like we have, or had to work with raw, low-level JSPs and Servlets.

Now things are easier. There are standards, there are libraries, there are best practices and YouTube videos showing you how to create apps in 60 minutes (back in My Day I had to borrow someone else’s browser to use the Internet, and I debated for years the value of spending my own actual money on a Javascript actual paper actual book, which I could not afford). Now, you can get something quite pretty and functionally interesting, working in a lot less time than I realised. But that doesn’t mean the Kids These Days have it easier - it means there is so much more potential. Instead of beating your head against trying to get a specific version of IE to do what you want, instead of having to write separate pages for different browsers (although maybe that still goes on), you can be exploring so much further into the possible, try things that no-one else has done yet. It opens up so many interesting possibilities for apps on all platforms.

Exciting times.

So next time someone asks me “What is the de facto front-end framework for Java?” I’m going to say HTML5, CSS and JavaScript.