28 April 2009

Grails and PartyTime Training in China


We've just returned from a trip to Guangzhou where we spent two days working with our partners, Well United, on Groovy, Grails, and PartyTime. It turned out to be a larger group than expected but the more the merrier!

It was a lot to cover in two days but even though the time allotted for the training session was rather short, it went very well and the Well United team picked everything up quickly.  The C#, PHP, and Java developers seemed enthusiastic about Grails and we hope to be working together on projects sometime soon.

Many thanks to our gracious hosts in Guangzhou and Hong Kong. We enjoyed the Macanese and Cantonese food and hope to be back soon!


18 April 2009

Install Groovy 1.6.1 on Windows -- A guide for the non-Java developer

* This is a quick guide on installing the latest Groovy 1.6.1 in Windows for non-Java developers.

1. Download and install Java SDK 1.6.x. Get the latest installer from Sun here. If this is your first time downloading Java, you are going to be confused with the various JDK 6 Updates packages -- JDK 6 Update with JavaFX SDK, JDK Update with Java EE, JDK Update with NetBeans 6.5.x. If unsure just look for the package without any of those extras -- Java 6 Update 13.

2. Download Groovy 1.6.1 installer from Groovy site. We will just use the Windows installer.

3. Double click on the Groovy installer and follow the wizard steps.


4. Use the defaults settings -- create GROOVY_HOME, add to PATH and add to System environment.


5. Make sure you have set JAVA_HOME environment. Right click on "My Computer", select "Properties". Click on the "Advance" tab and then click on the "Environment Variables" at the bottom of the window.



6. Add JAVA_HOME to User Variables. Click "Add" and enter the name as JAVA_HOME and value set to the full path to your Java JDK directory, e.g., C:\Program Files\Java\jdk1.6.0_13.


7. Continue with the Groovy installation wizard -- click next and use the defaults settings for native launcher and use all the Additional Modules.

8. Once finished, you should be able to see a new Groovy menu in Program list.


9. Lets give it a try. Select "Start GroovyConsole" to run GroovyConsole. If all goes well, you should be able to see the GroovyConsole up.

10. There are 2 useful keyboard shortcuts to know for GroovyConsole:
  • Cntrl+Enter = Run the groovy code
  • Ctrl+w = Clear console output

20 March 2009

Grails and Rails: Domain Classes and Web Services

Let's take a brief look at the differences between Grails and Rails in term of persisting domain classes and creating web services. Both Grails and Rails are MVC frameworks and are very similar in terms of code syntax.

1. Domain Class Persistence

In Grails:


class Person {
String firstName
String lastName
String email
Date birthDate
Address address

static constraint = {
firstName(blank:false)
lastName(blank:false)
email(blank:false, email:true) // check if it's really e-mail
}
}

class Address {
String street
String city
String country
Person person

static belongsTo = Person
}



In Rails, attributes can be inferred from the database table's structure:

class Person <>
# Expects database schema to have a table "person"
# with columns first_name, last_name, email, birth_date

validates_presence_of :first_name, :last_name, :email
end

class Address <> has_one :address
belongs_to :person
end


2. Making a service class available as a web service

In Grails, inside a controller closure:


def listAllPeople = {
def pplList = Person.list() // or by query Person.findByLastName("Hewitts")
render pplList as XML
// render pplList as JSON
}



In Rails, inside a controller block:


def listAllPeople
@pplList = Person.all # or by query Person.find_by_last_name("Hewitts")
render :xml => @pplList
# render :json => pplList
end


Note:
1. Grails will auto-generate the database schema and update the schema when more domain fields are added to the class. It's also possible to go in the reverse direction if you prefer starting with an existing schema.
2. Rails expects the database schema to be pre-created and to conform to camel case naming conventions.
3. Grails has the notion of service classes which are commonly used for business logic and can be use in a controller as a web service end point.

18 March 2009

VMware ESXi For Cheapskates

I've finally had it with Xen. We've been using it for QA and infrastructure hosts for a couple of years now (after a brief, bizarre detour with Solaris containers) with pretty good results. But after discovering Xen support had been dropped from the latest version of Ubuntu, I tried out KVM only to discover that its client tools are currently dribbly pieces of poo. I'm sure there's a clever way to compile your own kernel with the Xen patches to create some sort of frankenstein hypervisor, but really all I want is just the thinnest layer possible on top of bare metal in order to run some Linux VMs. Not really all that much to ask for.

Most of the software we use at Favorite Medium is open source so I, too, was surprised when my search led me to VMware. They recently made ESXi, the smaller and somewhat crippled cousin of ESX, free so I decided to try installing it on a $600 machine that formerly ran Xen in another life. This host is known around our office as 'pike' and is named after Rob Pike for no particular reason.

After burning the ISO image to a disk and booting up pike, I immediately ran into problems. First it was the ethernet card. Apparently ESXi has a fairly limited HCL and our crappy D-Link NIC was not on it. A quick trip to the local IT graveyard and I was back in the office with two replacements: an Intel PRO/100, and a Broadcom gigabit something or other. $12 each.

The Broadcom NIC worked perfectly but then the installer complained about the disk controller. Our super cheap Gigabyte motherboard (G31M-SL2, if you must know) uses a cruddy SATA controller that, again, isn't on the ESXi HCL. Note that if you're trying this on consumer-grade hardware you'll likely run into the same problem as well. Now the installer probably ought to handle the condition more gracefully but instead it just stops cold with an ominous "The installation has encountered a fatal error" message. Not to worry, a quick one line edit of a Python script fixed the problem. Check out the detailed procedure here.

Never thought I'd say this but...VMware, lovin' it!


17 March 2009

Delegation for iphone-google-maps-component

The iphone-google-maps-component is a way for you to use Google Maps on the iPhone through the use of an extended UIWebView and an html file on a server somewhere that does the map loading.

The present code overrides the default delegate UIWebViewDelegate with its own, MapWebViewDelegate. You cannot use the setCenterWithLatLng to establish the starting location until the view has finished loading. With the override, the webViewDidFinishLoad delegate method is unavailable.

Going by this post, the following code changes will allow the use of both delegates.

MapWebView.h
1) Change protocol definition.
@protocol MapWebViewDelegate < UIWebViewDelegate >

MapWebView.m
2) Remove the synthesize line.
//@synthesize delegate;

3) Replace with own methods, to hook into super.delegate.

- (id ) delegate {
return (id )super.delegate;
}

- (void) setDelegate :(id ) delegate {
super.delegate = delegate;
}


webViewDidFinishLoad should be accessible, as well as the other methods in the UIWebViewDelegate.

Another way of setting the starting location is through the loadMap method in MapWebView.h. The URL string can accept two more variables, latitude and longitude.

Change this:
NSString *urlStr = [NSString stringWithFormat:
@"http://www.wenear.com/iphone-test?width=%d&height=%d&zoom=%d",
width, height, DEFAULT_ZOOM_LEVEL];


To this:

NSString *urlStr = [NSString stringWithFormat:
@"http://www.wenear.com/iphone-test?width=%d&height=%d&latitude=%f&longitude=%f&zoom=%d",
width, height, location.coordinate.latitude, location.coordinate.longitude, DEFAULT_ZOOM_LEVEL];


Here, location is a CLLocation, part of the CoreLocation framework. The loadMap method is publicly defined in the interface and it accepts location as its variable. The call in didMoveToSuperview should be properly handled.

The latitude and longitude are doubles and can be hardcoded instead.

18 February 2009

Hello Android

Found this very insightful diagram of how Android SDK churns out Dalvik .dex files from Android java files here.

09 February 2009

XML and the Copyright symbol, ©

For anyone parsing an XML file and wondering what in the world an org.xml.sax.SAXParseException: Invalid byte 1 of 1-byte UTF-8 sequence error message is, check to see whether the XML file has any special characters like the copyright symbol, ©. The default encoding of UTF-8 will choke on these.

Solved my woes by changing the encoding to <?xml version="1.0" encoding="iso-8859-1"?> to get the character to display correctly. You can also filter it out or replace the symbol with its character reference.