1

I have some properties in a property file that I referenced in a singleton so that I can access them easily from different parts of my application. For each property, I put the properties along with some additional information for each property in a list of objects. I'm doing this in the singleton's private constructor. Is this the correct way to store/access static data on a server?

Any help or guidance is appreciated.


Added example of what I'm currently doing

public class PropertiesSingleton {

    private static PropertiesSingleton instance = null;
    private List<MyPropertyObject> properties = new ArrayList<>();

    private static PropertyManager pm = PropertyManager.getInstance();

    private PropertiesSingleton() {
        properties.add("first property description", 
                "other property info", 
                new MyPropertyObject(pm.getProperty("firstProperty")));
        properties.add("second property description", 
                "other property info", 
                new MyPropertyObject(pm.getProperty("secondProperty")));
        properties.add("third property description", 
                "other property info", 
                new MyPropertyObject(pm.getProperty("thirdProperty")));
    }

    public static getInstance() {
        if (instance == null) {
            instance = new PropertiesSingleton();
        }
        return instance;
    }

    public getProperties() {
        return this.properties;
    }
}
  • There is no single definition of correct in this industry. – whatsisname Mar 17 '17 at 21:22
  • @whatsisname But there surely are approaches upon which we can all agree definitely are NOT correct. – Andy Mar 17 '17 at 21:24
  • Be aware that the static data that you are exposing is a mutable object. So it is possible for the data to change and effect other code that expects it to be static. Depending on your actual use case, you might want to change the API exposed by PropertiesSingleton. – unholysampler Apr 17 '17 at 11:18
1

If it works for you, then in that sense it is correct.

In a broader sense, I think a lot of people would see it as a kind of anti-pattern if you were using it in the following fashion:

class Foo
{
    public void Bar()
    {
        int value = StaticData.getInstance().getUsefulPropertyValue();
        // do stuff with value
    }
}

This is considered an anti-pattern because the fact that Foo depends on StaticData is hidden within Foo's implementation. This tightly couples Foo and StaticData. In this specific situation it may not be that big of a problem because StaticData is unchanging, but in the general situation this makes it harder to test the parent class.

For example, if Foo was actually depending on the singleton DatabaseAccess then unit testing Foo would be impossible. Foo would require the presence of a database to be tested which is a) inconvenient, and b) no longer technically a unit test!

You can get around this by using Dependency Injection:

class Foo
{
    private DatabaseAccess databaseAccess;

    // Here we use Constructor Injection to inject Foo's dependencies into it.
    // NOTE: The dependency on DatabaseAccess is made explicit by being a part of Foo's constructor signature.
    // This makes it clear that Foo cannot be created without an instance of DatabaseAccess.  It therefore depends on it.
    public Foo(DatabaseAccess databaseAccess)
    {
        this.databaseAccess = databaseAccess;
    }

    public void Bar()
    {
        // NOTE: We are no longer plucking its dependency out of thin air!
        int data = this.databaseAccess.getTheCoolestIntegerEver();
    }
}

Functionally, this code is very similar, but in terms of testability and maintainability it is far superior.

Also, note that DatabaseAccess may still very well be a singleton. The key take-away here is to never access your singletons with a static getInstance() method.

  • I added an example of what I'm currently doing. Apologies for not doing that in the first place. Hopefully this gives you a better idea of why I'm thinking there's probably a better way to go about doing this than what I'm currently doing. – qbolt Mar 17 '17 at 17:03
  • @qbolt, add an usage example – Basilevs Apr 17 '17 at 2:51
0

What is variability of those properties? Are they supposed to differ between dev/test/prod environments?

If the answer is "Yes" - I'd pull those values from environmental variables. This would let you reuse the compiled artifact in all environments. Why use OS environmental vars, not JVM params? E.g. it is useful when packing your artifact inside docker image.

Then, have a look at HOCON config library from Lightbend. It lets you use environment variables and set sensible defaults stored in JSON-like structured and readable form in resources/application.conf.

At last, if your properties can be characterised as config, I usually prefer to let a single entrance for config data into my application. It enters where your app is wired, being validated by some config factory, and then relevant portions of config data are passed down the object graph via constructor parameters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.