My first Hudson PlugIn

I set up a Hudson instance in my company. But after adding the 20th job I lost the overview: which job depends on which other job? I need a visualization.
I need a plugin which reads the job dependencies and creates a dependency graph.

This problem consists of two parts: getting te dependencies and creating the graph. And I need to solve both for getting the plugin work …

I start with creating the graph. Shouldn’t be a problem – I am sure there are some libraries I could use as dependency graphs are an old and common ‚problem‘. And searching for „java create dependency graph“ gave me a nice hit: yFiles.
But this lib has an enourmous drawback: it is commercial and the plugin should be published as OSS.
But I remembered another tool: Graphiz. And via its homepage I found a Java layer on top of it: Linguine Maps.

First played a little bit:

String dotExeFileName = "C:/temp/ec-dep/Job Dependency Visualizer/lib/graphiz/dot.exe";
 // create the board for the graph
 Graph graph = GraphFactory.newGraph();
 // create the nodes
 GraphNode child   = graph.addNode();
 GraphNode me      = graph.addNode();
 GraphNode wife    = graph.addNode();
 GraphNode father  = graph.addNode();
 GraphNode mother  = graph.addNode();
 GraphNode grandma = graph.addNode();
 GraphNode grandpa = graph.addNode();
 GraphNode friend  = graph.addNode();
 // connect the nodes according to the dependencies
 graph.addEdge(me, child);
 graph.addEdge(wife, child);
 graph.addEdge(father, me);
 graph.addEdge(mother, me);
 graph.addEdge(grandma, father);
 graph.addEdge(grandpa, father);
 // nodes have a caption
 // highlight some nodes
 // save as gif
 File dotFileName = File.createTempFile("tmp.graph.", ".dot");


Oh, this is the library I want to use. So I wrote a class tayloring the graph creation (Java 1.4) to dependency graphs with use of Java >=5 and a fluent interface.

 .addDependency("Child", "Me", "Wife")
 .addDependency("Me", "Father", "Mother")
 .addDependency("Father", "Grandma", "Grandpa")
 .nodeBorder("Grandma", BorderStyle.BORDER_DOTTED)
 .nodeBorder("Grandpa", BorderStyle.BORDER_DOTTED)
 .highlight("Me", Style.FILL_COLOR, "red")

My base concepts are:

  • a string could have dependency on other strings (me–>father,mother; wife:<none>)
  • the string is the caption of the graph node
  • the string is the unique node name
  • two strings can only be connected once

So I could store the dependencies as a map: Map<String,Set<String>>

public class DependencyGraph {

 /** Path to the Graphiz executable. */
 private String dotExeFileName = "C:/temp/ec-dep/Job Dependency Visualizer/lib/graphiz/dot.exe";

 /** The graph to create. */
 Graph graph = GraphFactory.newGraph();

/** All already created GraphNodes. */
 Map<String, GraphNode> nodes = new Hashtable<String, GraphNode>();

 /** Already created dependency lines. */
 Map<String, Set<String>> dependencies = new Hashtable<String, Set<String>>();

 public static DependencyGraph create() {
 return new DependencyGraph();

 * Adds a node and its dependencies to the graph. If the node exists
 * already, it is not created a second time.
 public DependencyGraph addDependency(String node, String... parents) {
 Set<String> list = new HashSet<String>();
 Collections.addAll(list, parents);
 addDependency(node, list);
 return this;

public DependencyGraph addDependency(String node, Set<String> parents) {
 for (String parent : parents) {
 if (!dependencies.get(node).contains(parent)) {
 // create the link
 graph.addEdge(nodes.get(parent), nodes.get(node));
 // register the dependency
 return this;

 * Helper method for creating graph nodes and store them in the cache if the
 * don't exist before.
 private void createGraphNode(String nodeName) {
 if (!nodes.containsKey(nodeName)) {
 GraphNode node = graph.addNode();
 nodes.put(nodeName, node);
 dependencies.put(nodeName, new HashSet<String>());

 * Modify the shape style of a node.
 * @param node the name of the node to style
 * @param style the new style
 * @return self
 public DependencyGraph nodeStyle(String node, ShapeStyle style) {
 return this;

 * Stores the graph as GIF image.
 * @param file the file to new image file
 * @return self
 * @throws IOException while file access
 public DependencyGraph toGif(File file) throws IOException {
 File dotFileName = File.createTempFile("tmp.graph.", ".dot");
 graph, dotFileName.getAbsolutePath(),
 file.getAbsolutePath(), dotExeFileName);
 return this;


public enum ShapeStyle {

 /** the LinguineMaps style value */
 int value;
 private ShapeStyle(int value) {
 this.value = value;


After solving the second part of my problem I have to solve the first part too. I need information from Hudson:

  • List<Job> getAllJobs()
  • List<Job> getParentJobs(Job)

For creating a graph per view I also need

  • List<View> getAllViews()
  • List<Job>  getJobs(View)

And for keeping the graphs up to date I need to be informed about configuration changes.

  • void onJobConfigChange(Job)

I have to search for these…

I am working on the plugin part now – so I’ll write more if I have finished that.

Explore posts in the same categories: en, Hudson

7 Kommentare - “My first Hudson PlugIn”

  1. kutzi Says:

    Sounds like exactly what I’m just looking for.
    Has there been any progress lately on the plugin?

    • janmaterne Says:

      Sorry, no news. I hadnt any time to work on that, but it’s still on my todo list.
      When finished it will be available via update center and in the Hudson svn repository.

      • kutzi Says:

        BTW: have you seen Hudson.getInstance().getDependencyGraph() ?
        Looks like that could be useful for your plugin.

  2. janmaterne Says:

    No I havent, but I dont have investigated much effort in that. Thanks for the hint – I’ll read the JavaDocs.

  3. darxriggs Says:

    I was also thinking of implementing such a plugin. Please let me know of your progress.

    Another feature I had in mind was to also analyze the dependencies from the below plugin to have the full picture.

  4. darxriggs Says:

    I just found out that there is already an experimental dependency graph implementation integrated into Hudson.

    Just add „/dependencyGraph/graph“ to your base Hudson URL (eg. http://localhost:8080/dependencyGraph/graph) and it shows up.

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

Du kommentierst mit Deinem Abmelden / Ändern )


Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )


Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: