This post originated from an RSS feed registered with Ruby Buzz
by Obie Fernandez.
Original Post: Migrator: ActiveRecord Migrations in Java
Feed Title: Obie On Rails (Has It Been 9 Years Already?)
Feed URL: http://jroller.com/obie/feed/entries/rss
Feed Description: Obie Fernandez talks about life as a technologist, mostly as ramblings about software development and consulting. Nowadays it's pretty much all about Ruby and Ruby on Rails.
Having to go back to Java programming after doing Rails can be challenging, even painful, but sometimes results in blessings for the Java community. Working day in and day out with Ruby on Rails can give you a perspective on what makes it so special, and the insight necessary to effectively recreate some of it's magic in Java.
My colleague Hari, who worked with me earlier this year has done just that. After having to go back to a Java project, he has created a spot-on version of one of Rails' killer features. His Migrator project, now released in beta, is a beautifully elegant implementation of ActiveRecord-style migrations for Java projects. Martin Fowler explains the underlying concept of database migrations in his seminal article Evolutionary Database Design.
The Migrator project currently has zero documentation (tsk, tsk!), so here is a very quick guide.
Ant Tasks
Migrator includes a couple of Ant tasks, one for creating skeleton migration scripts and the other for migrating to the a particular version of the database. Their use is illustrated in the sample. (Download the src.zip off of the project site to see this code and more.)
It's not the most portable choice (Rails migrations are db-agnostic), but IMHO using SQL is a commendably simple approach which is appropriate for a first release. Running the new migration ant task checks to see what the next version number for the migration should be and creates a file with the right prefix, and @UP and @DOWN placeholders.
@UP
create table users (id integer, name varchar)
@UP
@DOWN
drop table users
@DOWN
Programmatic Use
Integrating Migrator into existing framework code is easy, as illustrated in Migrator's unit tests. (You can tell the project was TDD'd!)
package migrator.tests;
import junit.framework.TestCase;
import migrator.actions.*;
import migrator.core.*;
public class CompleteMigrationTest extends TestCase {
private Database db;
public void setUp() {
db = new Database("jdbc:postgresql://localhost/migrator",
"developer", "password", "org.postgresql.Driver");
}
public void testMigrationFlows() {
db.connect();
Action migration;
migration = new HeadMigration(db);
migration.execute();
assertEquals(new Version(3), db.version());
migration = new ReverseMigration(db, "1");
migration.execute();
assertEquals(new Version(1), db.version());
db.close();
}
}
My Commentary
By the way, about a month ago, Dion made a comment about ActiveRecord Migrations being useful in other technologies. Bruce Tate also alluded to the same idea in January 2006, although he did it in the context of asking for a good implementation of ActiveRecord in Java. So why did it take so long for someone to do what Hari did? I think the answer is that to really understand the magic of Rails, you need to do some serious development work with it. If I remember correctly, Hari was on that Rails project for at least 2-3 months. That's the kind of experience you need to really understand the magic of Ruby and Rails. At minimum, you have to make it through the first few weeks of the learning curve to appreciate the usefulness of the idioms, and the secrets to its productivity.
As Ruby on Rails continues its swift march to mainstream acceptance, I expect more of this type of productive cross-pollination to take place. It's also something to consider for the authors of Rails-wannabe frameworks such as Grails and Trails.