1

What is the prefered way to manage and distribute configurations to many different class instances of differing class types (in Java)?

In other words, I have an Application class that stores config options in a Configuration class in a static variable. This allows all the other classes in the application to simply call Application.config to fetch config values.

I'd like to allow there to be multiple instances of Application with associated Configuration's per Application instance. This is were I am lost... Is my only option to cascade a Configuration reference to every other class (via constructors and setters)? Or is there another way?

Seems like a single configuration for an Application instance and all it's supporting instances isn't unreasonable, but the requirement to cascade the single configuration reference just seems like such a burden.

Thanks, Chenz

Crazy Chenz
  • 10,877
  • 12
  • 44
  • 57

3 Answers3

2

It sounds like you just found out that what you thought was global state is not really global.

There are several solutions,

  1. the one you outlined,
  2. use a dependency injection framework like Guice to scope configuration.
  3. use ClassLoader voodoo to create multiple "global" configurations in the same VM.

The best solution is really to thread your configuration through manually or via DI, but since you asked for other options, the third solution is to change your main class to create a UrlClassLoader per-instance of the application that points to your jars. This allows you to have multiple different versions of the Application class and its associated Condiguration class side-by-side in the same VM.

EDIT:

To do the classloader voodoo, you main looks something like this

URLClassLoader application1Loader = new ClassLoader(/* URLs to common Jars and the config files for instance 1*/);
URLClassLoader application2Loader = new ClassLoader(/* URLs to common Jars and the config files for instance 2*/);

// Assuming you have a wrapper for your application that you can run() to get it going
// in its own thread via reflection.

Class<? extends Runnable> app1Class = application1Loader.loadClass("my.pkg.MyApplicaion")
    .asSubclass(Runnable.class);
// newInstance() is problematic but I want this code to be brief.
app1Class.newInstance().run();

Class<? extends Runnable> app2Class = application2Loader.loadClass("my.pkg.MyApplicaion")
    .asSubclass(Runnable.class);
app2Class.newInstance().run();

UPDATE: The my.pkg.MyApplicaion class must not be in the JVM's classpath.

Crazy Chenz
  • 10,877
  • 12
  • 44
  • 57
Mike Samuel
  • 109,453
  • 27
  • 204
  • 234
  • What is DI? Also, what I have is global, but I'd like to make it a "limited" global. What kind of ClassLoader voodoo do you speak of? – Crazy Chenz Mar 11 '11 at 03:36
  • @Crazy Chenz, see http://stackoverflow.com/questions/130794/what-is-dependency-injection for your first question. – Mike Samuel Mar 11 '11 at 03:39
  • @Crazy Chenz, will edit with more details on classloader voodoo. – Mike Samuel Mar 11 '11 at 03:40
  • The "classloader voodoo" approach is likely to cause more problems than it is solving in the long run. – Stephen C Mar 11 '11 at 03:45
  • @Stephen C. Agreed, in the long term. It can buy time for you to implement a more principled solution though. – Mike Samuel Mar 11 '11 at 03:48
  • @Mike Samuel OK, so I've implemented the above code... I handle the newIntance issue by just casting to a Interface that extends Runnable, but the statics still stick. Do you know of a working example? If not I was going to nix the voodoo from the answer. Thanks for your help! – Crazy Chenz Mar 11 '11 at 14:07
  • @Mike Samuel Got it, you have to have the Application class being loaded not on the classpath. – Crazy Chenz Mar 11 '11 at 14:17
0

I generally use Spring and define my config in associated XML files, which I load wherever needed using the spring API's.

A quick and dirty method to pass around app config without rewriting all your API's would be to use the singleton pattern. You could get a reference to the config using AppConfig.getInstance() where ever required.

qwerty
  • 3,537
  • 2
  • 24
  • 40
0

if your objects know what Application they belong to, no problem: just make configuration be non-static.

If your Application instances are separate threads, no problem: put configuration on ThreadLocal

If there is some kind of namespace associated with each Application, and child objects know about it, no problem: store a static Map somewhere

if none of the above holds, you're kinda screwed...

iluxa
  • 6,733
  • 16
  • 33
  • I can't figure out a way for the objects to know what Application they belong to. Any solution to that problem would be the same complexity as just passing the Configuration reference around. – Crazy Chenz Mar 11 '11 at 03:33
  • Then like Mike Samuel above is saying, you should use dependency injection... but then again, you'll have to inject the configuration everywhere, so that won't simplify things much either... – iluxa Mar 11 '11 at 03:35
  • The idea of DI is that "something else" figures out where the dependencies need to be injected. The code typically just needs some annotations to say "inject configuration here". (There are other models of DI too.) – Stephen C Mar 11 '11 at 03:50