The discussion at the mailing list quickly turned into a technical discussion of what the plugin could do and eventually DomainBuilder was mentioned, as it pretty much was designed for the same tasks as the Fixtures plugin. What does this have to do with ObjectGraphBuilder? well DomainBuilder is based on ObjectGraphBuilder, and as it were both couldn't solve the following problem:
Say you have two typical domain classes (Author, Book) living under package "com.acme", Author has a list of followers (also Authors) and a list of authors it may follow (a following relationship), given the Fixtures plugin you could create a sample dataset with the following code
This version of the DSL is a bit verbose and has a bit of repetition, but don't worry there are ways to make it DRY, Luke is looking into it. Alright so let's look at the code that might be produced by DomainBuilder shall we?
Though that code looks nice and shiny it will fail if you try it. Why? well let's say OGB and DB have some issues with it
- You can register a String as a ClassNameResolver strategy but cannot do it for an IdentifierResolver nor a ReferenceResolver (line 7).
- DB does not know what type of object it must create for 'follower' and 'following' in an automatic way, you must provide the mapping.
- DB cannot resolve the reference at line 21, as the mechanism requires a 'refId' property to do so.
1. Stringfied resolvers
Both identifierResolver and referenceResolver can be specified as Strings, as it is the case with classNameResolver, which makes the code snappier.2. Node values taken into account
Both the regular Object factory and the ObjectReference factory take the value into account. If you supply a value to a node and it matches the node's mapped class then it will be used as the object associated with the node, this is pretty much the same behavior behind SwingBuilder. This feature enables direct references as in line 21 also.3. Builder set as delegate on resolver
As you may know, almost all resolvers accept a Closure as their value, problem is that the current builder was not set as the delegate on those closures, which meant you couldn't access the current node's context to take a better decision on those strategies, will not anymore.4. Lazy references
This one is huge. OGB and DB resolved references in a sequential manner, you had to define the node prior to it being referenced. Look at the Fixtures DSL, that is not the case there (thanks to Spring's DI capabilities). FactoryBuilderSupport includes a dispose() method that should be called once building has finished, so it was a simple matter of registering a disposalClosure that took care of any unresolved references, along with the factories storing the unresolved references information in a convenient place. Now you're free to lay out nodes in the order that best serve your needs, for exampleThese 4 tricks should make your OGB based code slicker, they also solve DomainBuilder's issues #1 and #3, but what about issue #2? DomainBuilder also received a face lift and I'm glad to say that it is now able to resolve those relationships in an automatic way, no need to mess around with mappings as every domain class should follow a predefined set of conventions right? the DomainBuilder update has been submitted as a patch (GRAILS-3474), if you want to try it out you'll have to build a copy of Groovy 1.6 directly from svn. OGB's code has been submitted to all affected Groovy branches (1.5.x, 1.6.x, 1.7) and it should be available in the next release of each one.
Keep on Groovying!