2014-03-03

Brooklyn ConfigKey and EntitySpec Interaction

Brooklyn ConfigKey Issue

I have been seeing some very strange behaviour in a Brooklyn application I am writing. Basically it looked like ConfigKeys were being overwritten, or the wrong values were being used. I have two clusters, which have their memberSpec key configured like this, in the init() method of their parent entity:

EntitySpec spec = getConfig(SPEC)
        .configure(PARENT, this);
Cluster cluster = addChild(EntitySpec.create(DynamicCluster.class)
        .configure(Cluster.INITIAL_SIZE, initialSize)
        .configure(DynamicCluster.MEMBER_SPEC, spec);

The intent is to have PARENT set to ParentOne for ClusterOne and ParentTwo for ClusterTwo. But, when I resize the clusters and look at the details of their child entities in the Config tab of the Brooklyn console, the information is as follows:

ClusterOne member EntityOne has PARENT set to ParentOne
ClusterOne member EntityTwo has PARENT set to ParentTwo
ClusterTwo member EntityThree has PARENT set to ParentTwo

Note line two, the PARENT ConfigKey should have the same value as the other entity in ClusterOne since they are both derived from the same specification. Instead, it has the same value as the entity in ClusterTwo which was created with a completely different specification!

Correct EntitySpec Usage

It seems that this is happening because I am modifying a shared EntitySpec object in the configure(PARENT, this) call, so it is overwriting the previous value of the PARENT ConfigKey with the mutated EntitySpec in the Cluster. This is why the second member of ClusterOne is wrong, as the resize(2) operation on it happens after ClusterTwo is created and the referenced spec object is modified.

So, the solution is to change the first line of the block above to this:

EntitySpec spec = EntitySpec.create(getConfig(SPEC))
        .configure(PARENT, this);

Note the added call to EntitySpec.create() wrapping the SPEC configuration value. This makes a copy of the provided EntitySpec before configuring that with the PARENT key. The spec object can now be used during the addChild method call.

Anyway, just to point out that this took longer than I thought to debug, so I wanted to share in case other people come across a similar issue.