Skip to content

Instantly share code, notes, and snippets.

@grkvlt
Created March 26, 2014 22:36
Show Gist options
  • Save grkvlt/9795207 to your computer and use it in GitHub Desktop.
Save grkvlt/9795207 to your computer and use it in GitHub Desktop.
Changes to Startable Interface Static Fields

Changes to Startable Interface Static Fields

Recently the Startable#START field (public static final, by virtue of being part of a public interface) was modified. This caused problems when using applications linked against Brooklyn. In particular, if Brooklyn was built after the change without issuing an 'mvn clean' command then classes that merely referenced this static field did not get re-compiled, and their bytecode (including the old field value) was simply included in generated Jar files.

When deploying a YAML file, a call is made to invoke the 'start' effector, referenced as Startable#START inside ApplicationResource. This began to fail for me, with the exception indicating that the START field was not found.

This is because references to final fields are treated as constants and the values are included in the referencing class at compile time. So, if the value changes in the declaring (API) class, this is not propagated. See the JLS, section 13.4.8, excerpted below:

If a field is a constant variable (§4.12.4), then deleting the keyword final or changing its value will not break compatibility with pre-existing binaries by causing them not to run, but they will not see any new value for the usage of the field unless they are recompiled. This is true even if the usage itself is not a compile-time constant expression (§15.28).

This result is a side-effect of the decision to support conditional compilation, as discussed at the end of §14.21.

As I mentioned, the obvious and simple fix is to recompile all the things. This is a nuisance, and end users of our APIs will still be affected when they try to load a Jar with a compiled entity or application linked against the pre-change Brooklyn, into the latest Brooklyn.

It's something to be aware of if your applications start failing or behaving oddly because old configuration values are being used. The place this will trip people up most often is a situation where a third-party application sets configuration like this:

Entity e = addChild(EntitySpec.create(Something.class)
        .configure(Something.SENSOR_KEY, SomethingElse.SENSOR));

Then, in Brooklyn, we change the definition of SENSOR in SomethingElse. The entity will still be referencing the old sensor details, even if we rebuild (without a 'clean') using Maven. And you may not even know there have been Brooklyn changes, an updated -SNAPSHOT build deployed to SonaType could be being used when you build your application locally.

But, I'm not really sure if there's anything much we can do to mitigate this. We use static final constants heavily for ConfigKey and AttributeSensor definitions, which isn't going to stop. And, of course, the problem goes away when you next remember to do an 'mvn clean install' often enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment