Sunday, December 30, 2007

10 Reasons to Switch from Rails to Grails

After spending a few years really enjoying Rails it was difficult to bring myself to even try groovy and grails. But my latest contract forced me to look for alternatives, and I'm glad I did. Here are some reasons that you may want to switch...
  1. GORM with hibernate/spring and jpa is much better than ActiveRecord
  2. No distribution problems; runs in many production ready containers
  3. Internationalization out of the box (not specifically ignored as DHH does)
  4. Transactions actually work, and they include save-points.
  5. Not only dynamic finders and counters, but dynamic listOrderBy
  6. No green threads (although this may be fixed in Ruby 2.0, around 2010?)
  7. Ability to use pessimistic locking out of the box
  8. Real-live prepared statements and .withCriteria method
  9. Production level test reporting with built in Mocking and Stubbing
  10. Search operations are based on Lucene (with a plugin)
All of these don't make sense for a non-java coder. And my startup time for grails would have be much longer without my prior experience with Rails and Ruby.

One thing I thought I might be giving up was the endless list of valuable gems that make developing in Rails a real pleasure. But after re-reviewing the list of open source products from apache, java source, spring, hibernate, and even Sun (glassfish), I can't think of any gems that I will miss.

Grails Application Development Notes

I started a grails application for Sun using the latest version of groovy (1.5) and grails (1.0-RC3). Things went fairly smooth but I was glad to be under 'git' control to rollback branches as the project developed. My first problem with with mixed case characters in domain and controllers...

I originally created an IBBUser domain model. Ok, I should probably re-name it IbbUser but old habits die hard. Anyway, the model generation went fine, but when I went to create the controller using generate-all, that's when things fell apart.

I'm not sure why (yet) but 'generate-all' created my views in an IBBUser folder. This was a problem when I ran the app, so I scrapped the project and re-generated with the domain name of 'user'. I probably could have used 'ibbuser' in lower case, but oh well...

Working with generated code in grails or rails can get out of hand quickly--so many files and folders to track. So I set up branches--one for domains, the other for controllers. Before generating code, I quickly go to the appropriate branch, generate and test the code, do multiple commits then merge it to the master branch when I'm sure things are working as they should. If not, it's easy to revert or even delete the entire branch and start over.

Database Configuration: Out of the box grails configures the application for hypersonic. To configure MySQL requires three steps: 1) create the development, test, and production databases and login permissions, 2) modify the conf/DataSource.groovy configuration, and 3) drop the MySQL connector/j jar into the project's lib folder. When this is complete simply do a 'grails run-app' and you will see the new tables appear in the database.

The project at this point has only a single domain class, User so a single table is created called 'user'. All columns were created including an 'id' and 'version' column. Without any constraints, all columns default to 'not null'.

I prefer the rails convention of plurals and lock_version, but I'll leave that for now.

Constraints: Adding constraints was very straight forward. I watched the server restart and the database re-build with each change. Lots of magic going on in the background. I tested the constraints through the UI. The next step is to create unit and integration tests. More on that in a later post...

Tuesday, December 11, 2007

Upgrading to Groovy 1.5

I upgraded to the latest 1.5.0 version of groovy today. I was a bit of a pain, but after writing an install script (sandbox/groovy/install-groovy.sh) I was able to update all of my servers. Some of the new features include:
  • enums
  • annotations
  • generics
  • groovy interactive shell
  • updates to the groovy console
You can read about additional upgrade specifics and view code snippet examples here. Quoting from the article...
Groovy is Java, and Groovy makes Java groovier. Compared with other languages, Groovy is certainly the language that provides the flattest learning curve to Java developers, thanks to a very similar syntax.
I would add that ex-java programmers that have moved to ruby will love groovy. Closures, interactive shell, access to all your current java libraries, built in ORM, and lots of other goodies.

Here is a sample of how I use groovy to read job logs. Jobs run nightly on Sun production servers...
import groovy.sql.Sql
import database.*

oracle = new Oracle()
today = oracle.timestamp(new Date() - 1)

db = oracle.getStarsProd()


sql = "select * from job_log where start_time > ? order by job_id" db.eachRow(sql, [ today ]) {job ->
print "$job.job_id $job.start_time
$job.end_time"
println "\t$job.row_count\t$job.error_count\t$job.job_name"
}

This simple script dumps jobs run in the current day. The database package is a collection of groovy scripts that contain oracle specific connections and utilities. More on the specifics of what's in that package in another post...

Monday, December 10, 2007

Git for Flex Projects

I have been using subversion for Flex2 projects since it was released in 2006. I use the full version because I had problems getting the eclipse plugin to work. But I had other problems with the full Flex2 IDE as well. One problem was there is no facility to exclude files from the build path. So, all of my .svn files get copied from the src folder to bin. Permission problems also don't allow me to do a "clean" through the Flex2 IDE. Bad. Very bad.

So, I have converted all my Flex2 and action script 3 projects to use git rather than subversion. Simple to do, I just exported my adobe subversion branch and ran git init. I added a single .gitignore at the project root to ignore files in all the bin folders. Then I used Flex2 to recompile all the projects and ran git status to verify the ignores. It's all good...

Note: this would have been a bit easier to just use git-svn clone but my mac is missing the perl bindings required for git-svn.

The Git Server
: Next was to create a --bare copy and transfer it to my git server at slicehost. First the clone.
git clone --bare ~/work/adobe adobe.git
touch adobe.git/git-daemon-export-ok
scp -r adobe.git dpw@raincity.slice.com:

Then on the server, simply move this to the git directory and fix the permissions.
cd /public/git/
sudo mv ~/adobe.git .
sudo chown -R git:git adobe.git
And test on the client side with the following
and the new project is loaded to the client.
git clone ssh://git@raincity.slice.com/public/git/adobe.git adobe
After getting used to git I plan to move all projects there. If I can find the perl hooks, I'll probably use git-svn at least the the older (Sun) projects.


Saturday, December 8, 2007

Rails 2.0

I spent some time today to convert all my on-going projects to Rails 2.0. Not a huge effort, but here are my notes.

My first problem was getting "gem install rails" to upgrade smoothly. It appears that the rails team noticed the problem and quickly put up version 2.0.1, but it also failed. A quick google search pointed me to a Polish site that had what looked like a solution. A few modifications and I was ready to go. The highlights are...
svn co http://dev.rubyonrails.org/svn/rails/tags/rel_2-0-1/ rails-2.0.1

cd rails-2.0.1

for f in *
do
[ -d $f/pkg ] && { cd $f ; rake package ; cd .. }
done

for f in */pkg/*.gem

do
sudo gem install $f --local
done

With the six gems now freshly compiled I put them into a tarball and moved them to a distribution point. Then I wrote a short script to untar and install locally (sandbox/rails/gem-install.sh). That made it easy to update all of my machines, including slicehost. (I did have a problem on one of my older machines. I had to modify the script to load the gems one at a time).

Next were the tests. I was able to get all projects to test without errors. I created a small demo project to make sure that was working as well.

Happy rails 2.0.1!

Friday, December 7, 2007

Replacing Subversion with Git for version control

I downloaded git on one of my fedora machines (fedora 7) to get a feeling for how it works vs subversion. I used yum to get the latest version (1.5.3.3) with this command:
sudo yum install git
Before getting started with git, first thing is to establish some global configurations. The standard configs are saved in ~/.gitconfig (currently in config/common). There is also a ~/.gitk config file that should be modified for the mac (put in config/osx/sedona) to set the font to Monaco 12 rather than Helvetica 9.

Using Git: There are tutorials for using git on the main site and one for subversion users. After the installation, I used the tutorial to establish tracking to some basic accounting files, time sheets, check register, etc. It started like this.
cd accounting
git init
git add .
git commit
Now the accounting directory is under source control. Another great resource for git is from peepcode.

Remote Repository: The next step is to get a remote repository established. I played around with the git socket protocol on slice.host, but found it a bit too confusing. So after reviewing the peepcode git session, I decided to use ssh and a restricted shell for the remote repository. I followed these steps:
  • login to the remote machine (raincity.slice.com)
  • create a new 'git' user: useradd --shell /usr/bin/git-shell git
  • copy to the server: scp -r accounting dpw@raincity.slice.com:accounting
  • create a /public/git folder and move the accounting to it
  • set owner to git:git
So it wasn't too difficult. After running clone, I did a few push and pulls from different machines and watched the changes on the remote repository. Works good...

Wednesday, December 5, 2007

Sprouts for Flex Application Generation

A second generation refactoring of AsProject for creating Flex projects is being created by Luke Bayes and Ali Mills at assertTrue. The project has great promise, and since it is based on ruby, gems, yaml and rake it has instant credibility with me. The project is in alpha stage, so there is lots of work to be completed, but here are some thoughts about my first experiences with sprouts...

First, I installed the gem on both OSX (10.4) and Fedora (7) with:

sudo gem install sprout

Then I created my first project on both machines.

sprout -s mxml MyProject

Since this is the first application in this project, there are a bunch of dependency files that need to be downloaded. Sprout gives a good visual indication of what it's doing, so it was not a problem. Once the basic projects were created, it was time for the initial test.

cd MyProject/project ; rake

If you don't have a mm.cfg at your home directory you'll be prompted (pestered?) to create one. This is more of a flex thing rather than sprouts, and I have lots of issues with how flex handles the debug thing, but for now, I just answered yes...

My results on linux were as expected. The project compiled and ran just fine. No so on my mac. It compiled ok, but the runner failed. I was able to access the compiled swf on my browser so I'm assuming that my mac's flex installation is messing up the runner. (After perusing the project issues I see that this is a known problem. I also looked at a post from LeakyMmembrain to help smooth out some issues (but rake still hangs)...)

So now that I have a project framework, next is to see how it works with the Flex/Eclipse IDE (flex 2 on my mac only). This wasn't as I hoped. The generated structure doesn't play nice with Flex's vision of projects, i.e., there is a single level project where src, test, assets, css, and lib reside. but, on the same level are script, rakefile.rb and bin. What flex tries to do is grab all the files and copy them to the bin folder--not good.

Sprout Wish List:

Here is a short list of things I would like to see in sprouts:
  • a rake plugin similar to 'lib/tasks' in rails
  • rake file named Rakefile (ok, that's a nit)
  • better Flex IDE integration, at least for mxml projects
So, I'm hoping that future versions, or possibly a custom template configuration will solve the Flex IDE problem. In any case I'm looking forward to following the progress of the sprouts.

Programming for the Haxe Compiler

Haxe is a programming environment and compiler for javascript and action script like files. It will compile to flash swf files so it's great for web application development.

I downloaded and installed the linux version (fedora 7) and tried out a few of the examples. The first was a classic hello world app. Simple, fast compiler, but with Flex/Flash now open source, I don't think there is a compelling reason to use haxe.

But, I left the files in my sandbox. You never know...

Monday, December 3, 2007

Geo Coding with Google KML

The google map API is easy to use either from javascript or directly through curl, or ruby. A recent post by assay depot on replacing or foregoing the heavy weight Cartographer plugin for a lighter approach has inspired me to produce a stand-alone ruby library to grab coordinates and address info using google, or any other service (geocoder.us comes to mind). So, here's my attempt.

First off is to get registered with google to get an access key. Second was to place this in a secure location so that it can be used, but not seen by others. So I created a simple google.rb script to house this and other login creds. It's stored in the home directory of what ever server I'm currently on, so easy to get to but out of view from the web space.

The next step was to create a simple value object that holds physical address information. I tried to make the object as generic as possible by cross referencing google KML (keyhole markeup language) schema and the commercial geocoder.us attributes as well as the TIGER/Line data provided by the US Census Bureau . Lots of attributes, but what I need is basic address and coordinates so the attributes are:
  • street (or thoroughfare)
  • city
  • state code
  • postal code
  • country
  • latitude
  • longitude
  • accuracy
Next was to create a query request object. The query request is used to launch queries to any geo source, parse the results and return a populated value object. A typical query would be:
include Geocode
source = GoogleMapSource.new(Google.access_key)
request = Query.new(source)

info = request.search('1211 13th St, Boulder')
The result value object (info) returned from the search would show:
street => 1211 13th St  
city =>
Boulder
state => CO
postal_code => 80302
country => USA
latitude => 40.008704 longitude => -105.276221
accuracy => 8
The search results from google is in XML format, so populating the address object with the correct values requires parsing the results. For this I created a KmlParser class. The KML schema supports multiple addresses, county, altitude, and other attributes. Here is the google output response to the previous query.

The QueryObject returns the first address found, but subsequent addresses are available (query.addresses). Also the status code for the query is available along with a boolean status_ok method, so a safer call would be:
request.search('1211 13th St, Boulder')
info = request.addresses.first if request.status_ok
You can download the classes including address info, parser, google access, etc here. (Note: You will have to provide your own access code to use.)

Saturday, December 1, 2007

OpenID with Flex and Rails

Standard Applications...

We actively support OpenID for our open source products that require login authentication. Most applications don't require rigorous authentication, so presenting a simple dialog with only open id uri works fine.


The dialog above allows the user to access an open id application or register for a new open id account. The registration process takes the user to an open id provider, such as MyOpenID. The backend, rails in this case uses the access uri to discover the provider and confirm the authentication, i.e., log the user in.

Additional Security...

Using open id for your applications means that you don't have to store, or protect the user's password. It also lets the user access many applications with a single password. But sometimes an application, or a specific process within an application requires further authentication. That's where the authentication dialog comes in.


The dialog above presents an input and set of images. The input accepts the user's challenge code and the images are part of a group configured by the user. Only one of the images is the correct one, so if the user enters the correct challenge code and clicks on the correct image, access is granted. Look ma, no passwords!

Challenge Code...

So where does this challenge code come from? Well, during the registration process the user selects the method of delivery for the challenge code. The options are sms, email, pager, or a discrete application. The challenge code itself is a random set of characters with a minimum of ten characters (all numeric for pagers). For email a complex uuid is used so copy/paste is usually required.

You can access a non-working demo here. We hope to have a working demo soon...