0

I have a java web application that needs to read information from an external file when initialized (ie: when jboss server is started).

Since reading and parsing this text file is an expensive operation, we decided to load it only one time and then set it to memory so it can be accessed anywhere (the variable doesn't need to be modified after initialitazion).

I've read everywhere that global variables should be avoided, so what is the best practice for this scenario?

Edit: I should have mentioned that the information should be stored in a simple List variable.

Daniel Calderon Mori
  • 3,928
  • 5
  • 23
  • 31
  • 2
    Actually, I think these are different things. Configuration files should never be read only once. It would be better if you could just change it and the server read it again and perform the changes minimizing downtime. This is completely different of using global variables that any method and class can change and you can't trace. Global read-only variables such as constants are not bad. They're good. :-) – Leo Aug 27 '14 at 20:00
  • If you have properties for a web-application, consider defining them using JNDI. A properties file within a war can be good for defining static values or properties that can be overwritten, but it's not that good to define any sort of configuration. JNDI will allow you to define properties externally in a dynamic manner. – Isaiah van der Elst Aug 27 '14 at 20:00
  • @Leo I would say this qualifies as a Global read-only variable that is set only one time when initialized. – Daniel Calderon Mori Aug 27 '14 at 20:02
  • that's what configuration files are :-) the problem with global variables is when you can't keep track of what part of the code is changing it, and no code changes the properties files :-) – Leo Aug 27 '14 at 20:05

3 Answers3

2

it strongly depends on the framework you are using. In general you are right, global variables are often treated as anti-pattern. But you have to understand the reason, which is mainly testability.

To get "global" things tested you usually use patterns like Factories, Provider often in combination with dependency injection (e.g. Spring, Guide).

In the end you are caching. For caching you can also use some framework like EHCache. But maybe that's to much overhead for you.

To keep it simple and in plain Java I would suggest something like this (just first draft, not tested):

public class FileCache {
   Map<String, String> fileContents = new HashMap<String, String>();

   public void loadFile(String path) {
      if (fileContents.contains(path)) {
         return fileContents.get(path);
      }

      // Loading logic
      String content = loadContentOfFile(path);
      fileContents.put(path, content);
      return content;
   }
}

With this you keep your caching a bit scalable (you can cache as many files as you want) and it will be easy to test this class. But in the end you end up with some global place where you need to access this class.

And then you either have Dependency Injection, a static variable or some Singleton. With a singleton you should care to keep it simple, since it's again hard to test.

public class FileContentProvider {
   private static FileContentProvider instance;
   private final FileCache fileCache = new FileCache();

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

   public FileCache getFileCache() {
      return fileCache;
   }

}

Tarion
  • 14,013
  • 11
  • 61
  • 98
1

A static Configuration-Object that is global accessible is pretty common. You could use a Singleton-Pattern to access the Config. That could look like this:

public class Config {
    private static Config myInstance;

    private Config() {
        // Load the properties
    }

    public static getInstance() {
        if (myInstance == null) {
            myInstance = new Config();
        }

        return myInstance;
    }

    public String getConfigPropertyBla()

    ...
} 

If you use Spring you could let Spring load the properties to a Bean. You can then access the Bean via autowiring everywhere in your application. I personally think, that this is a very nice solution.

treeno
  • 2,148
  • 1
  • 16
  • 30
  • It isn't a configuration file but your answer solves my problem. Thank you. – Daniel Calderon Mori Aug 27 '14 at 20:03
  • This is a singleton. This is the pattern that you are reading about not being a best practice. – Isaiah van der Elst Aug 27 '14 at 20:05
  • @Daniel Calderon Mori You are welcome. If this solves your Problem, would you mind clicking on the solved-symbol? – treeno Aug 27 '14 at 20:08
  • I mean no disrespect, treeno. http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons – Isaiah van der Elst Aug 27 '14 at 20:11
  • @Isaiah van der Elst: A singleton has some downsides, but I don't think that you should generally avoid using it. Most downsides I know don't apply here, for example synchronisation issues, or extensive use of several Singletons... – treeno Aug 27 '14 at 20:15
  • @Isaiah van der Elst No problem. But even in that Thread is mentioned that there are some situations where it is perfectly ok to use a Singleton. If I have a single Config File that is not changed by my application and that is used in several places I don't want to pass that through n constructors or setters. I even think that this way is very error-prone because you have to manage the access to the config in several places instead of one central place. There are always benefits and withdraws, it depends on the situation which side weighs more. – treeno Aug 27 '14 at 20:25
  • @treeno My gripe with singletons is testability and higher coupling. The SUT inherits any logic defined in the used singleton and there's no way to mock it out... There are other arguments against it, like the rule of single responsibility... but it's maintaining testability having low coupling that matters to me. – Isaiah van der Elst Aug 27 '14 at 21:01
  • The issue with testability could be solved as Tarion showed below. If you have another class that does the loading of the configuration you have no logic in the singleton anymore. You could test the logic separate. That would also correspond to the rule of single responsibility. – treeno Aug 27 '14 at 22:19
0

DI, IoC container. Have a look at Guice, very nice thing.

kan
  • 26,120
  • 6
  • 61
  • 96