Monday, September 22, 2008

Adding HTTP Basic Authorization to GroovyHTTP

A while back, I discovered a great little Groovy utility by Tony Landis called GroovyHTTP which allows you to generate web requests in Groovy. I've used it with great success on a number of projects.

Lately, I've been playing with a neat GTD web app named Tracks, which has a nice RESTful API for adding tasks, etc. To interact with the application via the API, though, you need to be able to authenticate via HTTP Basic authentication, and GroovyHTTP doesn't seem to support that. Since I really want to interact with Tracks on my internal network with Groovy, I've taken a stab at adding HTTP Basic authentication to GroovyHTTP. Of course, I realize that HTTP Basic is not the most secure authentication method (that's an understatement!), but when you need it, you need it.

It really boils down to adding one method to set the user and login on the GroovyHTTP object, then adding a Base64-encoded authorization string to the HTTP request headers. The extra header line ends up looking like this (for the user/password "Aladdin/open sesame"):

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==


To use the modified GroovyHTTP class to access a URL protected by Basic authentication, you can do something like this:

def h = new GroovyHTTP(protectedUrl)
h.setMethod('POST')
h.setAuthorization(login, password)
h.setParam('p1', p1)
h.setParam('p2', p2)


Since I can't find any contact information for Tony Landis on his site, I figured I'd post the Groovy code here since he's released it under the BSD license. The Groovy class is available here: GroovyHTTP with HTTP Basic Authentication. NOTE: It looks like Google Docs has messed up the formatting in the Groovy class. When I get some time, I'll try to neaten it up.

Friday, September 12, 2008

Rendering complex collections as JSON in Grails

So I have a set of somewhat complex objects I need to render as JSON in Grails for some AJAX calls. Let's say I have an array of "Foo" objects, each of which contains a name and an array of "Bar" objects, each of which have a name and a location.

I want the JSON to look something like this (granted, there are a number of ways I could probably use simpler data structures with more frequent AJAX calls, but I'm trying to make as few trips to the server as possible) :

{"foos":
[
{
"fooName":"fooOne",
"bars":[
{"barName":"barOne","location":"here"},
{"barName":"barTwo","location":"there"},
{"barName":"barThree","location":"everywhere"}
]
},
{
"fooName":"fooTwo",
"bars":[
{"barName":"barFour","location":"Istanbul"},
{"barName":"barFive","location":"Constantiople"},
{"barName":"barSix","location":"Nobody's Business"}
]
}
]
}

I tried for a while to get this to render using Grails JSONBuilder, but to no avail: the secondary arrays kept being built outside the Foo objects. Eventually, I came across this really helpful post: Mini-Guide to rendering JSON with Grails that pretty much described the things I had tried and the problems I encountered. The post suggested trying the JSON converter that's bundled with Grails and gave a fairly simple example of how to use it.

The JSON I wanted to build was a bit more complex than the example, though, so I went searching for more examples of how to use the JSON converter. In the examples I found, most of the structures didn't go as deeply as the one I wanted; most of them just included a list at the top level of the structure, using the Grails "list" method (e.g. Books.list(params), which would get you the listing of books with the param IDs). I needed to go one step deeper, so I thought I'd see if Grails would automatically recurse the Lists in my objects. No such luck: when I tried rendering like this "render foos as JSON", the first-level items rendered correctly, but the array of Bars was empty.

Finally, I just decided to try constructing the data structures myself since maybe the JSON converter had trouble navigating object graphs but not basic collections. Since Javascript doesn't really differentiate between Objects and Maps (which is basically how JSON works), I created a Map for each Bar, put them into an array which then went into a Foo Map containing the attributes for the Foo. Finally, I created an array of the Foo Maps, which I then rendered using the JSON converter.

That actually worked! The downside, though, is that this is pretty fragile: if the data I want to return from the Foo or Bar objects changes, I have to change how the containers are rendered.

I don't know how much of what I encountered in JSONBuilder or the JSON converter is by design (maybe trying to force less complex data structures), but it certainly would be helpful to be able to create these kinds of arbitrarily complex structures based on the objects themselves rather than having to create our own containers. I'll have to see if anyone is already working on that.

Here's the final code I ended up with (it's probably not idiomatic Groovy, but I'm more familiar with Java, so it was quick):

import grails.converters.JSON
. . .
def getJson = {
def fooList = new ArrayList()
data.foos.each { foo ->

def fooMap = new HashMap()
fooMap.put("fooName", foo.fooName)

// see what bars this foo has
def bars = new ArrayList()
foo.bars.each { bar ->
def barMap = new HashMap()
barMap.put("barName", bar.barName)
barMap.put("location", bar.location)
bars.add(barMap)
}
fooMap.put("bars", bars)

fooList.add(fooMap)
}

def output = [
foos: fooList
]

render output as JSON
}

Wednesday, September 10, 2008

Rich Web Experience 2008: the Nate Schutta Sessions

Thinking back on the RWE 2008 last week, I realized there were a number of sessions that really stood out as being well presented and extremely informative. In particular, the sessions by Nate Schutta (check out his blog at http://ntschutta/jat) were among some of the best I've seen. They were all clear, well-thought out, in-depth, and engaging. A number of his presentations were introductions to various popular Javascript libraries like Prototype, YUI, and Dojo. These were particularly good because he showed not only why the libraries were useful but also how to use them. He didn't leave it at theory or sales pitch, though; in each of his script library presentations, he coded a number of examples using the libraries in question. And here's the best part: in each presentation, he built the same type of applications (a simple PIM app, showing how to use a date picker, etc) but using the library under discussion. It made for a good comparison of the strengths and APIs of each library. Also, he showed in his examples how the different libraries could actually work together, building on the strengths of each. All in all, the content of his presentations was excellent.

In addition to the excellent content, though, his method of presentation was right up my alley. He did what I consider the best thing to do in using slide presentations: he used the slides to initiate discussion rather than regurgitating the points from the slides. Some presenters tend to read their slides and that's their presentation. That gets old really quickly. As well, I remember one time when I was in the Army and giving a briefing to a warrant officer being told that people can either read your slides or listen to you, not do both at the same time. Nate kept his slides clean and simple, usually just a few words or phrases per slide, which allowed him to emphasize his points and guide his discussion of the topic without the listeners getting distracted by a lot of visual noise on the screen. He actually did something really interesting, too, for his final presentation of the weekend (A Software Engineer's Guide to Usability): he had two different slide decks. The first contained his simple slides described above, and the other had more content grouped in bullet points and images. I guess people had complained that the slides didn't make good take-aways (which is probably true, unless you're an extremely thorough note taker) since they were more for guiding the discussion than posting information. I think it was a good tactic. in fact, I actually found myself referring to his "note slides" earlier today when writing up some notes for some of my colleagues.

I know some people don't like this form of presentation. In environments like this weekend, I tend to be a more audio learner, so Nate's presentation style really worked for me. But for people who are more visually oriented and who want to get their information mainly from the screen, that "simple" form of presentation might cause problems. But overall, I'd say his presentations, from my point of view, were among the best there, and actually were among the best I've seen in attending other NFJS events, too.

Monday, September 8, 2008

Tracking visitor statistics on a Blogger blog

So I wanted to track various statistics on who's visiting my blog, and it didn't appear that there was any sort of tool available via Blogger.  So what I ended up doing is hooking my blog into Google Analytics.

First, I had to sign up for a free Google Analytics account.  When it asked for the URL of my site, I put in the URL to this blog (http://agileice.blogspot.com) and gave the new account a name.  After putting in my contact information and agreeing to the terms of service, Google gave me some tracking code that I needed to add to my blog site.

To add that code to my blog, I logged into my blog and clicked the "Customize" link at the top of the page.  From the "Layout" tag, I clicked the "Edit HTML" link which brings up the actual HTML template for the blog page.  I scrolled down to the bottom of the HTML, and inserted the code from the Analytics page right above the closing </body> tag.  That's really all there was to it.  NOTE: the code *has* to go at the bottom of your page.

Once the code was installed, I logged in to my Google Analytics account.  In the stats table for my blog, the cell at the far right was a different color and said "Tracking Unknown": Google Analytics hadn't yet communicated with the site.  I clicked the "Check Status" link and the cell changed to read "Tracking Installed".  That's pretty much all there is to it.

Now I can easily check the visitor statistics for my blog just by logging in to my Google Analytics account.  I can get reports on how many visitors I've had, where they're from, how many hits I've gotten over time, and all sorts of other data views.  There are even tools that I can install on the blog that will show the stats updated hourly (though I think I'd rather just keep it on the Analytics site).

Sunday, September 7, 2008

Registering a domain using Google Apps, but hosting "www" yourself

So I registered a new domain today: agileice.com. In the past, I've registered a few domains (eriksontech.net and eriksonweb.com) with a couple other companies (one with a hosting package that expired a couple years ago and one with Yahoo!). They weren't bad experiences, but I decided to go with Google's partners this time, partly because of Google Apps. I like the idea of not having to mess with email at the domain and being able to use GMail's familiar interface for the mail that goes to that address. Initially, though, they registered the "www" alias back to the "start" pages they set up for me, which meant that the address in the address bar of the browser went from the simple "http://www.agileice.com" through what appeared to be a couple forwards to end up as "http://partnerpage.google.com/agileice.com". If I do end up doing business on this domain, I don't want potential customers going to an address like that. I also wanted to be able to control a number of other services and things behind www.agileice.com (SSH, in particular).

Here's what I ended up doing: Once you log into the domain you registered with Google Apps (by going to https://www.google.com/a/[domain name here]), you can go to the "Domain Settings" then the "Domain Names" section. Once you're there, you can get to the actual domain registrar's site (Google partners with a couple other companies to register the domain name; it doesn't register the name itself) by clicking the "Advanced DNS Settings" link. In my case, I registered the address with eNom, who has a fairly straightforward interface for managing the various parts of the DNS entries. In my case, I needed to edit the "Host Records" section where wanted to forward the "www" host to my actual IP address.

In the "Host Records" section, there are actually a few types of entries; the two types that really mattered in this case are "A" and "CNAME". An "A" entry stands for an actual IP address; a "CNAME" entry is more of an alias, forwarding the host to the "named" address in the entry. When I registered with Google Apps, eNom automatically filled in a number of entries for me, setting a few "A" entries to what I assume are Google's IP addresses, and then aliasing a number of other services (Mail, Calendar, etc) to the Google services address "ghs.google.com". All I ended up doing was changing the "www" entry (which Google had set as a "CNAME" entry) to an "A" entry pointing at the static IP address I have through my ISP.

It took a little while for the changes to propagate through the net, but now when someone goes to www.agileice.com, they'll actually get the pages I'm hosting here rather than being forwarded to the Google pages (or they will once I actually start hosting some pages here ;)). And things like Google Mail for agileice.com still work.

Saturday, September 6, 2008

Thoughts from RWE 2008 final keynote

Just got finished up with a Rich Web Experience conference today, where the final *scheduled* keynote speaker--Jared Richardson--made some very good points about getting your ideas out there both for earning some name recognition and for being able to get to them yourself some time in the future when you may need them. He suggested blogging (and I wonder just how many blogs are getting started up right now :)) as a great way to start pushing your information out there.

One of the things he suggested is blogging anything that's taken you more than 10 or 15 minutes to figure out. The idea is that if it took you some time to figure out, it'll take someone else some time to figure out, and by posting it on your blog, you'll have access in to it in the future and, if people find it useful, then you'll be getting some exposure. Enough exposure, and it might lead to other things.

He also suggested getting involved in open source projects, not just in starting them up or becoming a leader or main contributor from the get go, but starting small. Pick a bug and fix it. Or, even better, do something no one else wants to do, like write documentation. It's a good way to get involved and to start getting your name out there.

The other interesting thing he mentioned is starting a personal Wiki. Basically, it becomes a repository of ideas that you have, that eventually you can go back and flesh out. When you get an idea for an article (or anything else), you can basically just create a post with a title in it. Then you can go back and fill in the content as you get the time and inclination.

A few other really good points he made:
  • if a goal doesn't effect your behavior today, it's not a good goal (my interpretation: do something today to move yourself forward.)
  • if you want to write a book, a book is made of chapters, a chapter is made of sections, a section is pretty much an article, and what's an article but a glorified blog post?
  • get out there and teach/speak to really learn something (and get more exposure)
  • write and post short tutorials as you learn to do things. Those short tutorials also become good entry points for people learning to do something and get you some more exposure.
All in all, it was a great talk, probably the best of the keynote speeches, and worth sticking around after lunch for :).