Monday, May 28, 2007

RESTful web services - the book

Few days ago I've received a copy of the RESTful web services book. As far as I understand, this is the very first comprehensive text on the subject matter. Since REST seems to be the "hot" topic these days, the book immediately drew my attention. I bought it, so I could learn in-depth about this topic.

I just started reading it and all I could say that the book is excellent (IMO). Authors give "no bullshit" explanations about the "architecture of the world wide web", what are the advantages of using simple, yet powerful and ubiquitous architecture of HTTP to deliver lightweight services. They also define some architectural patterns (they call it ROA for Resource Oriented Architecture), show the comparison between "The big web services" (WS-*) and give plenty of examples (in Ruby, which is actually fine with me, since Ruby is a very easy to read and understand language). The examples include real world RESTful services from Amazon (S3 storage service), the various incarnations of the Atom Publishing Protocol, Google Maps, and del.icio.us.

I like the foreword by DHH:

"A renaissance of HTTP appreciation is building and, under the banner of REST, shows a credible alternative to what the merchants of complexity are trying to ram down everyone's throats; a simple set of principles that every day developers can use to connect applications in a style native to the Web... Every developer working with the Web needs to read this book"

As I learn more about RESTful principles, I start to appreciate it more and more and favor it over the "Big web services".

Later...

Sunday, May 20, 2007

Could it be any easier?

Well here I am again, on the second week of development of my Grails based 'addictive time waster' web2.0 site (I'm not rushing and spend may be an hour a day on it). As I described in the previous post, I was having a blast with Grails custom codecs feature which enables adding various 'encoding/transformation' features to any arbitrary Java types with ease! Well, I'm continuing "abusing" custom codecs with a great level of success and most importantly with a lot of fun.

As I noticed on almost all of those user generated content web2.0 style sites, there are some kind of a 'Submitted by: user234 x days ago type of a piece of info. So, I've decided to add 'time ago' type of a stat to my web app. I'll continue to show the 'Submission' class for the examples, representing user's submission of any kind. So in order to track when Submissions are created, I've added a 'createdOn' property:


class Submission {

...
Date createdOn = new Date()
...
}


That will take care of recording the date of submission. Now, when retrieving and showing the the submissions, there would need to be some kind of a calculation to show the 'x minutes/hours/days/weeks/months/years ago' info. So, I've decided to "abuse" the codecs feature and "attach" the "encoding" of the date type into the 'time ago' string to the java.util.Date type. Thanks to the "richness" of the Joda time library, I was able to do that easily and put the code into the custom codec:


import org.joda.time.*

class TimeAgoStringCodec {

static encode = { date ->
def start = new DateTime(date)
def end = new DateTime(new Date())
def ago = Minutes.minutesBetween(start, end).getMinutes()
if(ago == 0) {
return 'less then 1 minute ago'
}
else if(ago < 60) {
return "$ago minute" + (ago > 1 ? "s ago" : " ago")
}

ago = Hours.hoursBetween(start, end).getHours()
if(ago < 24) {
return "$ago hour" + (ago > 1 ? "s ago" : " ago")
}
ago = Days.daysBetween(start, end).getDays()
if(ago < 7) {
return "$ago day" + (ago > 1 ? "s ago" : " ago")
}
ago = Weeks.weeksBetween(start, end).getWeeks()
if(ago < 4) {
return "$ago week" + (ago > 1 ? "s ago" : " ago")
}
ago = Months.monthsBetween(start, end).getMonths()
if(ago < 12) {
return "$ago month" + (ago > 1 ? "s ago" : " ago")
}
ago = Years.yearsBetween(start, end).getYears()
return "$ago year" + (ago > 1 ? "s ago" : " ago")
}
}


And equipped with this codec, I am then able to call: submission.createdOn.encodeAsTimeAgoString() and viola, I have the proper 'time ago' for any Date type application-wide!

Here I could conclude that adding 'codecs' to any arbitrary Java type application-wide is piece of cake in Grails, and also here is a great example of the advantage of Groovy's seamless integration with "raw Java" where I was able to make use of an existing Java library (Joda time) with zero integration overhead.

Later...

Sunday, May 13, 2007

Permalink codec

So, for about a week I've been working on my fun little "social" Grails web application and I've been having a lot of fun.

Yesterday, while jyting I've been taking a note of its URL structure. Let's say you have a claim, and then in order to see it, the URL to it is not something like http://jyte.com/claim/show/12345 , but rather more readable, like http://jyte.com/cl/dima767.myopenid.com-is-the-only-grails-hacker-on-jyte

That's called "permalink" (for permanent link) and is done by converting the text of the claim (or any user submition for that matter) into permalink string (removing all the special characters e.g. \W, and replacing them with '-'). Then permalink essentially becomes a searchable attribute of the submission, so instead of doing something like Claim.get(1234) you do Claim.findByPermalink(params.permalink). It's just a way of creating "user friendlier" interfaces.

Thanks to Grails and its nice custom URL mapping, and custom codecs facility, I was able to implement "permalink" functionality very easily!

Lets' say I have a domain class "Submission":


class Submission {
String title

//permalink property here is for nicer URLs
String permalink

}


So then I simply create "PermalinkCodec" utility class and place it in grails-app/utils so the Grails "ExpandoMetaClass" machinery could "weave" this functionality into all Strings!


class PermalinkCodec {

static encode = { str ->
str.toLowerCase().replaceAll(/\W/,'-')
}
}


Then in my "SubmissionController's" "save" action I do something like this:


...
def save = {
def s = new Submission()
s.properties = params
s.permalink = params.title.encodeAsPermalink()
s.save()
...
}


And finally, i define the custom mapping:


class MyAppUrlMappings {
static mappings = {
...
"/s/$permalink" {
controller = 'submission'
action = 'show'
}
...
}
}


So this will give users nice URLs like http://myapp/s/my-shiny-and-the-best-in-the-world-submission instead of http://myapp/submission/show/1234

I think it's a little thing, but nice, nevertheless.

Later...

Monday, May 7, 2007

Groovy actors

I've been reading up yesterday about an interesting concept called groovy actors:

IMO, this is a very interesting and powerful programming model. Now, my brain is working hard, trying to figure out some interesting ideas that could be implemented with 'actors'.

How about a "loosely-coupled demand/supply engine" where some people submit their "needs" and others submit their "offers" and the system does the matching and bring the parties together. Kinda like craigslist, but without people actually manually searching through the classifieds. Instead, they just express their needs and the system does the rest...

Another one, could be the automated "matchmaking engine", etc.

Does something like this exist already?

Later...