Monday, February 1, 2010

ActiveRecord in Java == ActiveJDBC

As a Java developer, I spent a a couple of years working in a mixed environment where Java and Ruby intermixed. Working side by side with Ruby developers made me aware of things outside the Java world. To some extend, this was my own fault for ignoring the Ruby world. I clearly remember beng at the SD West conference in 2005 when the Ruby frenzy began. I looked at what RoR can do and was unimpressed by it mostly because the presentations at the conference focused on generating an application from scratch using scaffolding. Having to implement web app generators for Hibernate/Tiles/Struts-Layout two years prior, this looked boring and I put my interest to Ruby on the back burner. I was wrong. A couple of years later, working in a mixed environment (Java/Ruby) I learned a whole a lot more about Ruby and Rails, and was pleasantly surprised by the level of innovation. Over the years I have developed somewhat a disgust for big frameworks and "architectures" using them. The biggest offender IMHO is Spring. I really, really, REALLY do not understand what value it provides. The Spring context files multiply like rabbits, making it extremely difficult to debug the application. As you can imagine, in a mixed environment, there were many heated discussions on the merits of different languages, and I tended to protect Java, stating that the Java environment was poisoned by large useless frameworks as well as a large number of corporate developer-drones, and really there is nothing wrong with the language. The argument that the Ruby folks had was that Ruby is more elegant, dynamic and powerful and therefore attracts a more sophisticated crowd. My arguments that there are plenty examples of outstanding software created in whatever language (including Java) were just brushed aside.  On the flip side, when Ruby becomes as successful and as prominent as Java, it too will be flooded by corporate bonehead developers. I think that some of the Ruby folks behave as Ruby were a cult, not another tool at developers' disposal. So, to make the story short, the desire to prove that it is totally possible to create a lightweight persistence layer in Java similar to ActiveRecord, and make it even simpler to use in some regard, as well as desire to roll up my sleeves and just do some coding (I have done too much architecture and management over the past few years), drove me to create another ORM framework in Java, named ActiveJDBC.
The idea is to model the behavior and feel similar that of ActiveRecord, but make it for the Java developer. It is amazing how little Java developers know of Ruby. RoR has some great features, and despite the fact that there is no method_missing in Java, many ideas are possible to borrow and implement in Java.
The ActiveJDBC is already used on one commercial project, and according to developers who are used to Hibernate, they "do not even notice it, it just works".
My design goals were:
  • Should infer all metadata from DB (like ActiveRecord)
  • Should be very easy to work with
  • Should reduce amount of code to a minimum
  • No configuration, just conventions
  • Some conventions are overridable in code by simply calling methods (this will be aided by IDEs)
  • No need to learn another language
  • No need to learn another QL - SQL is sufficient
  • Code must be lightweight and intuitive, should read like English
  • No sessions, no "attaching, re-attaching" 
  • No persistence managers. 
  • No classes outside your own models.
  • Models are lightweight, no transient fields
  • No proxying. What you write is what you get (WYWIWYG :))
  • Should have the least possible resistance to startup a project
  • No useless getters and setters (they just pollute code). You can still write them if you like.
  • No DAOs and DTOs  - this mostly junk code anyway
Well, enough suspense, I can say that I started development on my free time around September, and at the end of October I had something I could use in a real system.
Let's look at code examples.
Here is an example of a model:

public class Person extends Model {}

Despite the fact that there is no code in it, it is fully functional and will map to a table called PEOPLE automatically. Here is how to use it:

List<Person> people = Person.find("name = 'John'");
Person aJohn =  people.get(0);
String johnsLastName = aJohn.get("last_name");

As you can see, the amount of code is reduced to a level when it is actually readable.
Finder methods can also be parametrized like this:

List<Person> teenagers = Person.find("age > ? and age < ?", 10, 20);

ActiveJDBC supports many features and is great for building web applications as well. It has a nice validation mechanism similar that of ActiveRecord, automatic support of many to one and many to many relationships, batch deletes and updates (conditional too), etc. Too many to list. I hope this wets your appetite. Any feedback and suggestions are welcome.