5

We have some data in properties file. This data is used across many classes. So, we create a Properties class object in each and every class and then read data using getProperty() method. This is leading to duplication of code.

Can someone please suggest some best practices to avoid this?

One thing that came to my mind is:
Create a class
Have a public variable for each property in property file in this class
Have a method that assigns values to each and every property
In the class where property values are required, create an object for this class and access the public variables

But, things i don't like with this approach are public variables and if at all a new property is added to the property file, i need to add code to read that property in the class.

Any help is appreciated.

Thank you!

Austin
  • 1,237
  • 1
  • 11
  • 22

6 Answers6

20

You can create a Singleton class, that loads the properties the first time it gets invoked.. and a public method that retrieves the property value, for a given property key..

This is assuming you're using a standart Properties file... But you can extrapolate this to any key-value pair, changing Properties type to a Map or something else.

Something like

public class PropertyHandler{

   private static PropertyHandler instance = null;

   private Properties props = null;

   private PropertyHandler(){
         // Here you could read the file into props object
         this.props = ..... 
   }

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

   public String getValue(String propKey){
       return this.props.getProperty(propKey);
   }
}

Then you can invoke this as needed.. from any code.. like this.

String myValue = PropertyHandler.getInstance().getValue(propKey);

Hope this helps

Cristian Meneses
  • 4,013
  • 17
  • 32
2

for me static inner class is the best possible way to do it. It will do it with lazily, as class loading is synchronized so thread safe, plus performant also. So with this we are achieving three things:

  1. good performance because with synchronizing the liveliness will suffer, but here we are using static inner class.
  2. thread safety because when inner class will be loaded than only map will be initialized as the class loading is thread safe hence all total thread safe.
  3. Inner class will be loaded when we will call Singleton.initialize().get(key) so the map gets initialized lazily.

Below is the code...

public class SingletonFactory 
{   
    private static class Singleton
    {
        private static final Map<String, String> map = new HashMap<String, String>();
        static
        {
            try
            {
                //here we can read properties files
                map.put("KEY", "VALUE");
            }
            catch(Exception e)
            {
                //we can do the exception handling
                System.out.println(e);
            }
        }
        private static Map<String, String> initialize()
        {   
            return map;
        }
    }

    public static String getValue(String key)
    {
        return Singleton.initialize().get(key);
    }
}
Trying
  • 14,004
  • 9
  • 70
  • 110
0

One out of the box option is to use system properties. You can add your own system properties to your execution environment.

codethulhu
  • 3,976
  • 2
  • 21
  • 15
0

You can do this with a dedicated class having a static Properties object. See here for an example.

Community
  • 1
  • 1
Joe
  • 6,767
  • 1
  • 16
  • 29
0

I could be misunderstanding your data flow here, but this is what seems "normal" to me:

  • Create a readPropFile method.
    • This should read a file and appropriately parse the properties it finds.
    • These properties can be stored in a Map<String, Object>, hashed by property name.
  • Read property file once (presumably when the application starts, or whenever it's appropriate to load properties) --> Properties object (say, props).
  • Pass props around to anything that needs access to those properties.
    • Or if you don't want to pass it around explicitly, use a static accessor as illustrated here.
  • Access properties using props.get("PROPERTY_NAME") (which just looks up that property in the internal Map).
    • If you don't want to use String lookups, you can keep an enum of valid property names somewhere, and do storage/lookups using that, but then you have to update that enum every time you add a new property to the file.
Community
  • 1
  • 1
Henry Keiter
  • 16,863
  • 7
  • 51
  • 80
0

I've had success using an Enum, and in the constructor using the name() method to read a property of the same name. Be sure to handle exceptions in a reasonable way or else the whole class will fail to load and you won't get a helpful error message.

Benefits of this approach are that each enum value automatically corresponds to a property without having to write individual mapping code for each property. You do of course need an enum value for each property (that's unavoidable if you want DRY prop references), but you avoid repetitive per-property initialization code using unchecked Strings.

Drawbacks are that enums don't allow generic types, so if you wanted certain properties to return Integer and others to return String, then you might be better served with a classic singleton class design.

If you want to go crazy with this you could also write a script to generate your Enum or singleton java source code from the properties file, to keep your code extra DRY.

Magnus
  • 10,736
  • 5
  • 44
  • 57