Barcamp Hyderabad Three: Eclectic Java

Just a quick note (will expand later, hopefully) to let you know that Barcamp Hyderabad 3 happened and I was there 🙂 ‘Twas a fun event, and a good two days away from work.

A request to unconference organizers tho: no wifi sucks big time.

I’ve stopped working on JRuby, but I’m keeping an active RSS eye on the project. It seems very promising. Meanwhile, my slides are up on SlideShare.

Java + Ruby

I’m going to write a bit about Ruby in Java land. Much of this post stems from the Sun stall at FOSS.in: to put it mildly, it was perhaps the most enthusiastic stall I’ve seen at a conference ever. The energy of the guys there was incredible and their enthusiasm to show things off (and Sun does have a lot of nice things to show off: dtrace, ZFS, glassfish) really made me give a second glance to the entire Java + Ruby thing: JRuby, or a Ruby implementation in Java, and Rails deployment via the Java Enterprise stack. I’ve been playing around with it for a day, and I’ve got just one thing to say. It’s cool 🙂

A bit of a background: I’m not a Java guy. Repeat, not a Java guy. So when people say that the Java toolset is amazing, I’ve always not understood what they meant. Who needs toolsets, widgets, a GUI, an administrative console; when you’ve got SSH & shell scripting? The last four months developing SlideShare however, have been a bit of a revelation: managing servers is a tough job. Our current stack includes a lighttpd->pound->mongrel chain, and monit to watch these processes and start them off if something goes wrong. Lots of glue code, and solutions that seem hacks now (a separate uploader mongrel, anyone?). Anyways, the role of a sysadmin sucks: big time, and the toolsets to manage a traditional *nix environment requires too much of manual work. [Stuff such as Puppet might negate this, but I digress…]. So it was kinda really nice to switch on Glassfish, drop a .war into an autodeploy directory and watch the application come alive. And have an actual GUI console to manage all this stuff, read up on the logs, configure routes & services, etc.

I’ve not done much: just installed Glassfish, played around with asadmin start-domain domain1 and the console, and then installing Jruby and the easy Java + Ruby integration. Look at this code, for e.g.:

#!/usr/bin/env jruby

require 'java'

set = java.util.TreeSet.new
set.add "foo"
set.add "Bar"
set.add "baz"
set.each do |v|
  puts "value: #{v}"
end

string = java.lang.String.new
string = "Vishnu"
puts string

Sweet ain’t it? One of Ruby’s selling points has always been that it’s easier to drop into a low level language (C) and write extensions for expensive functionality, thus negating Ruby’s slow performance. But stuff like the code sample above should make it pure nirvana for expensive operations. I haven’t compared speeds yet: I’ll do that soon using a simple Web framework like Camping & then a simple Rails app (i.e. Camping/WebBrick on Ruby and JRuby and Camping/Mongrel vs Camping/Glassfish: if I can get it running). JRuby isn’t perfect yet: Rails applications aren’t officially supported, but I hope to get a useful app deployed on localhost soon, and if there’s interest, deploy it to my slice. It’s an upward slope though for me, since the whole Java deployment scene [making a WAR] seems so bloody complicated (why, oh why?) but a good indicator for good Ruby/Rails deployment on JRuby would be to just type in rake deploy and have your code get into the whole Glassfish stack.

Ruby Magic: Metaprogramming

Rails, if you’ve used it, has a rather elegant way of manipulating time. Stuff like 1.hours and 2.minutes.from_now just work. Let’s see how Ruby modules can be extended really really easily:

#! /usr/bin/env ruby

class Integer
  def seconds
    self
  end

  def minutes
    seconds * 60
  end

  def hours
    minutes * 60
  end

  def days
    hours * 24
  end

  def months
    days * 30
  end

  def years
    months * 12
  end

  def from_now
    Time.now + self
  end

  def before
    Time.now - self
  end
end

class String
  def palindrome?
    self == self.reverse
  end
end

class Time
  def leap_year?
    (year % 4).zero? and ((not (year % 100).zero?) or (year % 1000).zero?)
  end
end

class TrueClass
  def say
    "is"
  end
end

class FalseClass
  def say
    "is not"
  end
end

#2 is an Integer
puts 2.minutes.from_now

#"vishnu" is a String
puts "vishnu".palindrome?
puts "malayalam".palindrome?

puts 2.years.from_now.leap_year?

#Check if n years before is a leap year
puts "How many years before?"
year = Integer(readline)
puts "#{Time.now.year - year} #{year.years.before.leap_year?.say} a leap year."

The interesting thing about Ruby is not that metaprogramming is possible, but Ruby makes it really easy to do it.

Ruby Magic: Blocks

I’ve been using Ruby a lot lately, and recently had to implement a “related” objects feature in Rails. You know, “Related Videos”, “Related Pages”, etc. I decided to sort them by objects that have the most common tags. Try this one-liner:

  #Inside video.rb Model, Related videos
  def related(count=5)
    tags.collect { |tag| tag.videos }.flatten.uniq.sort_by { |video| (video.tags & tags).length }.delete_if { |video| self == video }.reverse[0..count-1]
  end

Let’s try dissecting that:

tags.collect { |tag| tag.videos }

Collects all videos associated with the current object’s tags into an array of arrays (each array representing the slideshows for a particular tag).

.flatten.uniq

Flatten that array (make it a single dimensional array, preserving logical order) and then eliminate duplicates

.sort_by { |video| (video.tags & tags).length }

sort_by sorts the arrays by a particular attribute. So for each video in the array, video.tags & tags gives the intersection of tags for the video under consideration, and the current object’s tags. Because of .length, the sort_by function sorts by the number of such intersecting tags.

.delete_if { |video| self == video }

And, remove self references.

.reverse

Sorting is by default ascending, so reverse the array, and:

[0..count-1]

return only the first n elements.

So, you’d call it by something like video = Video.find(1) and @related_videos = video.related.

The interesting thing is that, I never ever was a programmer given to verbose lengths of code like this. Doing this in any other language would feel so clunky. But in Ruby, it somehow feels natural. Like you can read through the code in your head and have it make perfect sense.