Skip to content

An Easier Java ORM Part 3

24
Jul
2007

As a continuation to part 1 and part 2, this article examines a slightly less interesting (though none-the-less important) feature, transactions in ActiveObjects.

I also figured I should give a minor update on the development status. Eelco Hillenius (of the Wicket project) has been contributing some code, fixing up areas where I messed up and cleaning up one of the sample projects (the DogfoodBlog sample, based on Wicket). We’ve also been looking into areas where Wicket and ActiveObjects could be more easily integrated (such as entity-specific models and lists). I’ve been keeping busy trying to stabilize some of other database providers. We now officially support (in the trunk/) the following databases:

  • Derby (standalone and embedded)
  • MySQL
  • PostgreSQL
  • Oracle (with the limitation that @AutoIncrement is only supported on primary keys)

We also have the following (almost untested) providers:

  • Microsoft SQL Server (Microsoft and JTDS providers)
  • HSQLDB (standalone and embedded)

I’m hardly an expert in any of the above databases, so I welcome any and all input on bugs/errors/etc…

Transactions

While I might qualify transactions as comparatively unimportant, anyone who’s written a multi-user web application knows how significant they can be in maintaining data integrity. An ORM which didn’t support transactions would be sorely crippled indeed.

Hibernate solves the problem of transactions by forcing every database action to be wrapped in a transaction and committed at the close. This works well, but the significant downside is that it increases code complexity and forces the developer to remember to explicitly close every transaction. As before, I’ve tried to take some inspiration from ActiveRecord’s implementation of concepts:

p = Person.find(1)
lc = LibraryCard.find(321)
 
transaction do
    p.first_name = 'Daniel'
    p.last_name = 'Spiewak'
    p.save
 
    lc.person_name = 'Daniel Spiewak'
    lc.save
end

As is typical of ActiveRecord, this is an amazingly intuitive syntax. Unfortunately, again in accordance with the ActiveRecord MO, it depends upon a very DSL-like syntax. We might not be able to match the syntax exactly in Java, but we can fairly close:

new Transaction(manager) {
    public void run() {
        Account david = getEntityManager().get(Account.class, 1);
        david.setValue(david.getValue() - 1000);
        david.save();
 
        Account mary = getEntityManager().get(Account.class, 2);
        mary.setValue(mary.getValue() + 1000);
        mary.save();
    }
}.execute();

Obviously, we could potentially have gone with the less verbose:

Transaction t = new Transaction(entityManager);
t.begin();
// blah
t.commit();

However, this syntax doesn’t have the major advantage of the ActiveRecord DSL which is ensuring the transaction is closed. Also, with our anonymous inner-class syntax, we can do something like this:

new Transaction(manager) {
    public void run() {
        // yadda yadda yadda
    }
}.executeConcurrently();

This will execute the transaction in a separate thread, rather than blocking the current one. I haven’t actually seen a proper use-case for this so far, but it’s bound to have some application. :-)

Limitations

The trick with transactions in JDBC is all queries must be run against the same Connection instance. To accommodate this, an internal abstraction class is used by the ActiveObjects interface proxy to ensure that if a transaction is in progress, a single Connection is used, rather than opening a new one from the database provider. This works quite well, but it has its limitations.

Specifically, any custom code executed within the transaction which uses a Connection instance directly will run its SQL statements outside of the transaction boundaries. Any EntityManager method (get, find, findWithSQL, count, etc…) will work within a transaction, but any direct use of a Connection instance will likely cause unexpected behavior. I have a plan to fix this problem, but I haven’t gotten around to implementing it yet. Hopefully in a shortly upcoming release…

An Easier Java ORM Part 2

19
Jul
2007

Well, by popular demand on the first post, I now bring you the second part in my series introducing the new Java ORM, ActiveObjects. In the first post, I gave some very basic examples of how AO could be used to simplify database access in your application. And while trivially interesting, these examples really don’t do justice to the power of AO’s interface model and how it can best be used to serve you. So, I will be devoting this post to SaveableEntity(s) and implementations.

SaveableEntity

SaveableEntity is an interface which extends the Entity super-interface designed to overcome the inherent performance drawbacks in a simple getter/setter model ORM. For example, suppose we have the following trivial Entity interface:

public interface Person extends Entity {
    public String getFirstName();
    public void setFirstName(String firstName);
 
    public String getLastName();
    public void setLastName(String lastName);
}

We could use this entity in the following way:

private void initializePerson(EntityManager em, String name) throws SQLException {
    String[] names = name.split(' ');
 
    Person p = em.create(Person.class);
    p.setFirstName(names[0]);
    p.setLastName(names[1]);
}

This is all well and good, until we look at the actual SQL being executed by this code:

INSERT INTO person (id) VALUES (DEFAULT);
UPDATE person SET firstName = ? WHERE id = ?;
UPDATE person SET lastName = ? WHERE id = ?;

These are executed as separate PreparedStatement(s), under separate connections, totally unconnected. If we didn’t include a pooling library in the classpath, the connections wouldn’t be pooled and we would incur a significant performance hit from this sort of thing.

Enter SaveableEntity. SaveableEntity prevents the setters from immediately executing their respective UPDATE statements. Rather, the UPDATEs are held in reserve until the save() method is invoked. Here’s the above example rewritten to use SaveableEntity:

public interface Person extends SaveableEntity {
    public String getFirstName();
    public void setFirstName(String firstName);
 
    public String getLastName();
    public void setLastName(String lastName);
}
 
private void initializePerson(EntityManager em, String name) throws SQLException {
    String[] names = name.split(' ');
 
    Person p = em.create(Person.class);
    p.setFirstName(names[0]);
    p.setLastName(names[1]);
    p.save();
}

Only one more line of Java code, but it diminishes the SQL executed by 30%:

INSERT INTO person (ID) VALUES (DEFAULT);
UPDATE person SET firstName = ?,lastName = ? WHERE ID = ?;

This might not seem like such a big deal when you’re only working with single and duel fielded entities, but when you get into far more complex models - say, on the order of 30-40 fields - it makes a big difference if UPDATEs are merged where possible.

Implementations

So on a swift turn round another tack, we’re now going to look at defined implementations in ActiveObjects and how they are both a) a major pain you-know-where, and b) incredibly useful.

As was pointed out in a comment on my last post, ActiveObjects as I have presented it so far is just a data wrapping layer. It just allows simple database access. No frills, and no model-specific business logic. This actually poses a bit of a problem in many senarios.

For example, let’s assume you have a basic, user-based authentication system. Each user has a username and a password. However, authentication best practice says not to store the password in clear-text in the database. In fact, it’s best to hash the password when it is stored to prevent anyone from decrypting it. The problem comes in that ActiveObjects doesn’t allow us to do something like that in its current form. You’d have to do all the hashing prior to calling User#setPassword(String), and that would be majorly painful and about as unDRY as it gets. The solution: defined implementations.

@Implementation(UserImpl.class)
public interface User extends SaveableEntity {
    public String getUsername();
    public void setUsername(String username);
 
    public String getPassword();
    public void setPassword(String password);
}
 
public class UserImpl {
    private User user;
 
    public UserImpl(User user) {
        this.user = user;
    }
 
    public void setPassword(String password) {
        user.setPassword(Utilities.md5sum(password));
    }
}
 
// ...
User u = em.create(User.class);
u.setUsername("daniel");
u.setPassword("password");
u.save();
 
System.out.println(u.getPassword());   // prints the MD5 hashed value of "password"

See what I mean about a major pain? It’s not exactly clear what’s going on here so I’ll give you a brief run-down:

  • EntityManager instantiates a dynamic interface proxy for the User interface and returns it (where it assigned to u). It sees the @Implementation annotation and looks in the class for an init() method. Not finding one, it moves on.
  • setUsername(String) is invoked on the dynamic proxy. An @Implementation annotation on the interface is detected and the class in question is instantiated, passing the User instance into the constructor. The proxy looks for a setUsername(String) method within the implementation class and doesn’t find one. The method is invoked normally, caching the String username for future UPDATE into the database.
  • setPassword(String) is invoked. The dynamic proxy once again finds the @Implementation annotation and thus uses the cached UserImpl instance, looking for a setPassword(String) method. This time, it finds one and invokes it.
  • UserImpl#setPassword(String) is invoked by the dynamic proxy. The method calls to a utility class to hash the password, and in turn calls User#setPassword(String) with the resulting value.
  • The dynamic proxy receives the setPassword(String) call, and uses stack tracing to detect that the call originated from a defined implementation. The call is handled normally, caching the result for future UPDATE into the database.

Not so bad, I guess… The trick to remember is that any defined implementation takes an instance of the interface as the only parameter to its constructor. Also, it’s important to remember to only implement the methods that you expressly want to override. By defining a method in the implementation class, you are effectively overriding the dynamic implementation of any method with the same signature in the entity interface. This can lead to weird results if you aren’t careful.

So, we’ve now got SaveableEntity and defined implementations under out collective belts. With these two features, you can unlock a great deal of power and control over the ActiveObjects ORM and the entities it controls.

An Easier Java ORM

18
Jul
2007

There is no doubt that Hibernate is the dominant ORM for Java applications. There are Hibernate conferences and Hibernate user groups. It even has its own shelf at Barnes and Nobel. However, I have always found it suffering from a fatal flaw: it’s incredibly complex. Even accomplishing the simplest of functionality requires hundreds of lines of code, reams of boiler-plate POJO definitions, and a fair share of XML. Granted, it’s probably simpler and more scalable than using JDBC in its raw form, but I still think it makes things harder than they have to be.

This has been a common theme throughout most ORMs in any language. Even various Python ORMs, touted for simplicity and power, still remained burdened with either cryptic syntaxes, or mountains of boiler-plate. This general failing is probably the single most important factor which has contributed to the success of Ruby on Rails.

Rails is nothing without its flagship component, ActiveRecord. AR provides an incredibly simple and powerful database wrapper layer which makes working with almost any schema simple and intuitive. Granted, migrations are a bit weird and it’s performance is far from satisfactory, but the fact remains that it’s much easier, quicker (and thus cheaper, at least in the short term) to develop a database-reliant application using ActiveRecord than it is to build the same application on top of Hibernate or iBatis. This has been carried to such an extreme that developers have taken to using ActiveRecord on top of JDBC through JRuby just to handle the database layer of their Java application. Clearly a better solution is required.

Much of ActiveRecord’s power is drawn from the fact that very little code is required to interact with the database. For example, extracting data from a hypothetical people table in a database is as simple as:

class Person < ActiveRecord::Base
end
 
puts Person.find(1).first_name   # roughly == SELECT first_name FROM people WHERE id = 1

Obviously, the first_name method doesn’t exist in the Person class. This code is using a feature of Ruby which allows for methods to be defined at runtime (or rather, not defined and just handled). It should be apparent how much this could simplify database access, and how unfortunately inapplicable it is to Java.

Fortunately, the principles of ActiveRecord are not entirely irrelevant. The Java reflection API contains a little-known feature called interface proxies. It allows code to define a dynamic implementation of a given interface which handles method invocations in a single, dynamic location. It’s not quite dynamic method definitions, but it is dynamic method handling and it eliminates a lot of boiler-plate.

So what good does this do us? Enter ActiveObjects!

ActiveObjects is a Java ORM based on the concept of interface proxies. The whole idea behind it is that you shouldn’t have to write any more code than absolutely necessary. In fact, ActiveObjects was designed from the ground up to be dead-easy to use. Here’s a rough approximation of the previous ActiveRecord example, translated into Java using the ActiveObjects ORM:

public interface Person extends Entity {
    public String getFirstName();
    public void setFirstName(String firstName);
}
 
EntityManager em = new EntityManager(jdbcURI, username, password);
 
Person p = em.get(1);
System.out.println(p.getFirstName());    // executes "SELECT firstName FROM person WHERE id = 1"

Isn’t that refreshingly simple? With the exception of placing the appropriate JDBC driver in the classpath, that’s all there is to using ActiveObjects. AO automatically detects the database type from the JDBC URI and loads the appropriate driver. If you have placed a pooling library on the classpath, it will be used to pool the database connections. You’ll notice the Person implementation is created by the EntityManager instance corresponding to the (presumably existing) database row, and the SQL is automatically generated and executed, typing the result and returning it from the method. AO even uses PreparedStatement(s) for maximum performance (currently unsupported by ActiveRecord). And if we were to call the setFirstName(String) method, an SQL UPDATE statement would be automatically executed based on the data specified.

Of course, simple CRUD operations do not an ORM make. For one thing, it’d be really nice to be able to automatically generate database-specific DDL statements, ala Hibernate and ActiveRecord. Coolly enough, ActiveObjects allows for this too:

System.out.println(Generator.generate("../classes", "jdbc:mysql://localhost/db", "test.package.Person"));

This would output:

CREATE TABLE person (
    ID INTEGER AUTO_INCREMENT,
    firstName VARCHAR(45),
    PRIMARY KEY(ID)
);

With a different JDBC URI, the DDL would be different. ActiveObjects completely insulates the developer from any database inconsistencies. In fact, the only steps needed to switch to a different database are to place the appropriate driver on the classpath, and to change the URI.

To round up our little tour of ActiveObjects, it’s worth looking at relations a bit. In ActiveRecord, relations are specified using the has_many and belongs_to methods. Hibernate uses annotations/custom javadoc syntax to accomplish roughly the same thing. In ActiveObjects, things are nice and clean:

public interface Person extends Entity {
    public String getFirstName();
    public void setFirstName(String firstName);
 
    public House getHouse();
    public void setHouse(House house);
}
 
public interface House extends Entity {
    public String getAddress();
    public void setAddress(String address);
 
    @OneToMany
    public Person[] getPeople();
}

With just the above entity definitions, calls can be made to instances of Person, passing the House instance to store. Likewise, House#getPeople() can be called, which will return an array of all Person instances associated with that House. Obviously, the Java instance itself isn’t being stored in the database, but rather the houseID INTEGER value is persisted, through the restriction of the appropriate foreign key.

It almost seems magical when you first start using it. :-) I’ve written two test applications (not downloadable, but included within the ActiveObjects SVN) which illustrate the framework’s potential more fully. Also, I’ve been using ActiveObjects as the basis for a reasonably complex Wicket application deployed in the “real world”, and I must say it’s performed beautifully.

Now here comes a moment of bad news: it’s not fully documented yet. Since it’s only on its 0.3 release, I’ve been more interested in squashing bugs and adding features than writing javadoc, though I assure you it is on my agenda. There are a few brief (and somewhat dated) examples on the website, as well as partial javadoc for the EntityManager class. Thankfully, the framework itself is remarkably intuitive and very easy to pick up.

There’re so many more cool features I would love to have shown here, but unfortunately all bloggers have sworn in blood that they will not extend their posts beyond 1500 words. If you are interested, I’ll write a follow-up post going into further detail about the framework (including the more performant SaveableEntity super-interface, which does not execute an UPDATE on every setter call).

Do yourself a favor and take a look at the API and examples. Once you get used to the simplicity of Entity interfaces and non-configuration of database connections, you’ll never look back.

https://activeobjects.dev.java.net