Confluence DC throws ClassCastException when getting object from Bandana after app upgrade

My app is keeping some objects in the Bandana table. (I know it is not best practice but wasn’t my choice). When I install a new package of my app I start getting ClassCastException while getting my objects via BandanaManager.getValue().

To be clear, BandanaManager.getValue() successfully returns an object but it can’t be cast to the desired type. While debugging I can clearly see that the class name (and even the hashcode) of the object I am getting from BandanaManager.getValue() and the class name that I am trying to cast to have the exact same Fully Qualified Name, yet I get an exception.

The package I am uploading does not have to be a new version of the app. Even uploading the same jar twice causes this problem. It happens only on DataCenter, even if it works as a single node, Confluence Server does not have this. I keep getting the exception until Confluence instance is restarted.

The issue reported below seems to be related to this. I guess it has something to do with how Bandana Caches work and which classloaders are used. Unlike the issue reported below, I am not creating and/or operating those caches, Confluence is.

I don’t want to use reflection as a workaround for performance considerations and I also don’t want to de-serialize/re-serialize the object, also based on performance considerations.

Any possible workarounds are welcome.

We prepared the following sample Confuence App project that reproduces the problem.

  • Compile and install the app on a Confluence DC instance.
  • Call the following endpoint which will save something to the Bandana table.
    ** <confluenceUrl>/rest/bandanaBugTest/latest/bandana/save/{SPACE_KEY}?id={ID}&name={NAME}
    ** ID is an integer and NAME is a string.
  • Call the following endpoint to confirm that you can read the object successfully.
    ** <confluenceUrl>/rest/bandanaBugTest/latest/bandana/get/{SPACE_KEY}/{ID}
  • Upload the same plugin jar file without changing (or even compiling) anything.
  • Call the second endpoint (get endpoint) again to get the exception.
1 Like