Thanks all. Here's the use case. I have an external properties file, but it differs by topology. The contained properties are used by all spouts and bolts. So, I have a singleton registry class that loads this file, and it gets the file name/path via System.getProperty(). The registry class has no knowledge or dependency on Storm. It's just a library.
Method #3 below is closer to my use case. But with one problem. Storm doesn't serialize singleton objects. So, additional plumbing code is required in all spouts/bolts to fetch the key=value from the component config and explicitly pass it to the singleton. Or as long as spouts are created first by Storm, the code only needs to be added to the spouts. Overall though, this means that the properties file is now managed in multiple code paths, instead of just in the singleton registry class.
I think what would be good is that if I pass system arguments to Storm as "-Dkey=value", that Storm passes those on to the workers and makes them available there, too, by populating the system properties cache via System.setProperty(…). Then my code will work as-is when it calls System.getProperty(…).
Or perhaps I'm making this too complicated?