Since 2.3.1.X app semi-permanently modifies a '@Field static final Map' variable

Since upgrading to 2.3.1.X, the unofficial ring integraion app has started modifying the value of an '@Field static final Map' variable. The changes to that variable survive across multiple runs of the App, and even persist after uninstalling the App. The only way to get back to the original value of the variable is to re-save the App Code.

I have created a simple test case for this bug here:

I discovered this issue while working to fix a bug for the unofficial ring integration. I was unable to reproduce the issue until I upgraded my hub from 2.3.0.X to 2.3.1.X. You can see the bugfix for that app here: Fix for Hubitat 2.3.1.X · HubitatCommunity/hubitat_ring_integration@94a5de9 · GitHub

I'm honestly surprised it ever worked the other way, given that line 52, map.headers = defaultHeaders, should be a reference to the original (not a copy), so any modifications should be reflected in both. It's also normal that uninstalling an installed app wouldn't "reset" the value of this static field; by definition of static, it is shared among all instances of the app, not associated with any particular installed instance (and this is why only re-saving the app code worked for you, reinitializing the value to whatever is in the code; a reboot should also do this). That much you should see on 2.3.0, too.

But ... I can't speak to why the other behavior above may have changed. Groovy was bumped up from 2.4.19 to 2.4.21, but I don't think that should have affected this. It's possible the platform is also doing different caching, compilation, or something than it was previously. @gopher.ny might be the best person to ask about that (see the test case above)--but I'd probably keep what you're doing regardless if you want to work with a copy of the data and not a reference.

Also, moving to the "Developers" category since it seems more appropriate--hope that is OK!

3 Likes

Shouldn't declaring the field 'final' have kept it from being changed? Or at least thrown some kind of runtime error?

The app modifies an element within a map, and final modifier does not make an object immutable, only its reference contained in the variable. Use java.util.Collections.unmodifiableMap to make sure nothing can write into the Map.

2 Likes

Thanks for the info. Apparently I have a very different definition of the word 'final' than Java/Groovy.

1 Like