Griffon: visualizing an object graph - No Fluff Just Stuff

Griffon: visualizing an object graph

Posted by: Andres Almiray on November 16, 2009

You might have read before about Griffon's JUNG plugin and wondered "how can I visualize an arbitrary object graph with it?", if so then the following steps should give you a few hints.

Let's start by fleshing out the domain. I realize that at the time of writing this post Griffon does not support domain classes like Grails does (i.e, with GORM & scaffolding enabled), however you can create them in the same fashion, that is, place your domain classes under griffon-app/domain and have them participate on your app. With that in mind let's create a few domain classes related to the book publishing business, mainly a Publisher, a Book and an Author classes, like this:
If you're familiar with ObjectGraphBuilder you know you can populate an object graph with ease, as long as the domain classes follow the JavaBeans conventions. Luckily for us that is the case. Building a graph is as easy as executing the following code:
Nothing fancy, just what you would expect from a Groovy builder, isn't it? by the way I'm using the current list of Groovy related books published by Manning as an example. Alright, now comes the "tricky" part: transforming an object graph into something capable of being visualized with JUNG. I'm glad to say this task is also a simple one. We can instruct ObjectGraphBuilder to populate a JUNG Graph at the same time it builds the domain graph, after all ObjectGraphBuilder is quite extensible. There are two things to be done in order to achieve this goal:
  1. set the root node.
  2. append child nodes to their corresponding parents.
The following Griffon model shows how these two tasks can be done:
Task 1 is completed by calling addVertex on the publishers Graph using a special variable available to all FactoryBuilderSupport based builders: current. This variable points to the node that is currently being built, in our case, the publisher node. Task 2 is completed by changing the strategy used by the builder to set the parent/child relationships within nodes. Notice that it still calls the old behavior by keeping a reference to the previous strategy, then calls a Graph method on publishers that registers the child with its parent. Now both the object graph and the Graph are in sync. The following code shows how the publishers Graph can be visualized with minimal effort:
Running the application should result in a screen similar to the following snapshot


Time to get fancier with the visualizations. JUNG allows you to tweak almost every aspect of a visualization, we will concentrate on shapes and colors for now. It can be argued that visualization metadata belongs or not to domain classes. For example we could add shape and color properties to our domain classes, but perhaps those properties do not make any sense should our domain classes be persisted. In the end is your call how you want to add such metadata. In this howto I'll simply wrap each domain instance with a map, have the metadata (or spillover properties) be added to the map and the corresponding bean properties to each bean. In order to do that we must tweak two other OGB strategies, as shown next on the app's model:
The two strategies are
  • newInstanceResolver - takes care of instantiating a node. This is the perfect time to wrap the bean with a map.
  • attributeDelegate - this strategy takes care of setting properties on a node. By testing for MissingPropertyException we know the property may or may not be supported by the bean. If it is not supported we assume it is a metadata property and add it directly to the enclosing map.
Lastly we need to update the childPropertySetter strategy as the beans are now being wrapped. Now that the model has the desired metadata it is time to update the visualization code with a set of transformers. Given that the beans are now wrapped the ToStringLabeller will yield weird results, we need to provide a new value for vertexLabelTransformer. Two new transformers will be added:
  • vertexShapeTransformer - takes care of setting up the shape to be used for each node.
  • vertexFillPaintTransformer - takes care of setting up the color to be used as the fill for each node.
We will rely on jSilhouette's Star shape and a helper BasicVertexShapeTransfomer provided by the JUNG plugin. At this point only Books will have a custom shape (the Groovy star :-D) while the other domain classes will use a circle.
Reviewing each transformer yields:
  • vertexLabeler - queries the node's bean. v is of type Map.
  • vertexPainter - queries v's color property, uses a default color (WHITE) if no property is defined. The elvis operator becomes quite handy here.
  • shaper - another elvis enabled transformer, this one checks for the existence of a shape related to a class name.
  • vertexShaper - relies on the previous transformer to determine which shape will be used by each node. Notice that only books define a specific shape.
This is all that there is to it. Running the application should result in a similar screenshot like the following one


There you have it, a simple yet effective way to build and visualize an object graph with ObjectGraphBuilder and Griffon/JUNG.

Keep on Groovying!
Andres Almiray

About Andres Almiray

Andres is a Java/Groovy developer and a Java Champion with more than 20 years of experience in software design and development. He has been involved in web and desktop application development since the early days of Java. Andres is a true believer in open source and has participated on popular projects like Groovy, Griffon, and DbUnit, as well as starting his own projects (Json-lib, EZMorph, GraphicsBuilder, JideBuilder). Founding member of the Griffon framework and Hackergarten community event. https://ch.linkedin.com/in/aalmiray

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 8
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 4
  • Cloud
  • Automation Tools: Gradle, Git, Jenkins, Sonar
  • HTML5, CSS3, AngularJS, jQuery, Usability
  • Mobile Apps - iPhone and Android
  • More...
Learn More »