0

My spaghetti monster consumes XML from several different SOAP services, and the URL for each service is hardcoded into the application. I'm in the process of undoing this hardcoding, and storing the URLs in a properties file.

In terms of reading the properties file, I'd like to encompass that logic in a Singleton that can be referenced as needed.

Change this:
accountLookupURL ="http://prodServer:8080/accountLookupService";

To this:
accountLookupURL =urlLister.getURL("accountLookup");

The Singleton would be contained within the urlLister.

I've tended to shy away from the Singleton pattern, only because I've not had to use it, previously. Am I on the right track, here?

Thanks!
IVR Avenger

IVR Avenger
  • 15,090
  • 13
  • 46
  • 57

6 Answers6

3

You haven't said why you need only one of whatever it is which will be getting the URL. If that just involves reading a properties file, I don't think you do need only one. Seems to me that having two threads read the same properties file at the same time isn't a problem at all.

Unless you were thinking of having some object which only reads the properties file once and then caches the contents for future use. But this is a web application, right? So the way to deal with that is to read in the properties when the application starts up, and store them in the application context. There's only one application context, so there's your "only one" object.

Paul Clapham
  • 1,074
  • 5
  • 6
  • I'm not sure that I'm going to be able to do this, as a good portion of this application is abstracted into a JAR file whose source is not available to us. What would this entail? – IVR Avenger Dec 22 '09 at 20:52
  • IVR Avenger, how do you pass the properties into the Jar file now then? – Poindexter Dec 23 '09 at 14:57
  • I would imagine that properties are read exactly as you describe, above. However, that reading happens outside of a realm that I have access to. My code extends classes whose source I don't have, and those classes are reading specific properties. Ideally, I'd change the base class so that these URLs are available just like existing properties, but I don't have access to the base class. Yet... :-) – IVR Avenger Dec 23 '09 at 15:32
2

As an alternative, did you consider using something like Apache Commons Configuration (or maybe another configuration framework)?

Community
  • 1
  • 1
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
1

Singletons are appropriate for this scenario, BUT you have to make sure you're doing the singleton right.

So, for example, what Bozhno suggests is not a singleton, it's an ugly concoction of nasty statics that's not mockable, not easily testable, not injectable, and generally comes back to bite you in the ass.

An acceptable singleton is just your average class with one notable exception that it is guaranteed either by itself or by some external factory/framework (e.g Spring IoC) to exist in only one instance. If you go with the first approach, you do something like

private MyUberSingletonClass() {
    //..do your constructor stuff, note it's private
}

private static MyUberSingletonClass instance = null;

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

public String getUberUsefulStuff(){
    return "42";
}

That's acceptable if you don't really feel the need for a factory otherwise, and aren't using any IoC container in your app (good idea to think about using one though). Note the difference from Bozhno's example: this is a good vanilla class where the only static is an instance var and a method to return it. Also note the synchronized keyword required for lazy-initialization.

update: Pascal recommends this very cool post about a better way to lazy-init singletons in the comments below: http://crazybob.org/2007/01/lazy-loading-singletons.html

Paul Milovanov
  • 706
  • 4
  • 18
  • 1
    You may want to read this: http://crazybob.org/2007/01/lazy-loading-singletons.html – Pascal Thivent Dec 22 '09 at 21:15
  • Very, very nice! Thanks Pascal. Much neater than the synchronized idiom. I'm just wondering whether this behavior is uniform for all JVMs since 1.3 -- i've been doing Blackberry devt lately, and as you know CLDC is a bitch. – Paul Milovanov Dec 22 '09 at 21:54
1

Based on your suggestions, and the fact that I don't think I have as much access to this application as I'd hoped (a lot of it is abstracted away in compiled code), here's the solution I've cooked up. This is, of course, a stub, and needs to be fleshed out with better exception handling and the like.

public class WebServiceURLs {

  private static class WebServiceURLsHolder  
  {  
    public static WebServiceURLs webServiceURLs = new WebServiceURLs(); 
  }

  private Properties webServiceURLs;


  public WebServiceURLs()
  {
    try
    {
      Properties newURLProperties = new Properties();      
      InputStreamReader inputStream = new InputStreamReader(
          FileLoader.class.getClassLoader().getResourceAsStream("../../config/URLs.properties") );
      newURLProperties.load(inputStream);
      webServiceURLs =newURLProperties;
    }
    catch (Exception e)
    {
      webServiceURLs =null;
    }        
  }

  public String getURLFromKey(String urlKey)
  {    
    if (webServiceURLs==null)
      return null;
    else
      return webServiceURLs.getProperty(urlKey);
  }

  public static WebServiceURLs getInstance()
  {
    return WebServiceURLsHolder.webServiceURLs;
  }

}

Is this a good effort as my "first" Singleton?

Thanks,
IVR Avenger

IVR Avenger
  • 15,090
  • 13
  • 46
  • 57
  • That is not exactly a singleton. You should have make an object of the WebServiceUrls an instance variable of itself and make the constructor private. The getInstance() method should check if the object has been created and create it if it has not before returning it. – Poindexter Dec 23 '09 at 15:02
  • Okay. But it mimics the structure detailed in Pascal's link, above. Is that not the approach that I should have taken? – IVR Avenger Dec 23 '09 at 15:14
0

To restate the obvious, Singleton is to be used when all client code should talk to a single instance of the class. So, use a Singleton IFF you are certain that you would not want to load multiple properties files at once. Personally, I would want to be able to have that functionality (loading multiple properties files).

danben
  • 80,905
  • 18
  • 123
  • 145
  • Using a singleton does not preclude loading multiple properties files at once... I have some code that uses a singleton to centralize access to multiple properties files (actually ResourceBundles in my case). Perhaps you meant multiple properties files that contain definitions for the same property names? – Nate Dec 22 '09 at 20:58
  • Right, I wouldn't expect that I would have to worry about name clashes if I loaded multiple properties files, since the system shouldn't (necessarily) assume they have anything to do with each other. – danben Dec 22 '09 at 21:05
  • Also, even if there aren't name clashes, you may want to have a logical separation of sets of properties (ie accessing sets from different instances). You could namespace them but I wouldn't be crazy about having to do that. – danben Dec 22 '09 at 21:06
0

Singletons are mutable statics and therefore evil. (Assuming a reasonably useful definition of "singleton".

Any code that uses the static (a transitive relationship), is has assumptions about pretty much everything else (in this case, a web server and the internet). Mutable statics are bad design, and bad design makes many aspects go rotten (dependency, understandability, testing, security, etc).

As an example, the only thing stopping late versions of JUnit 3 being used in a sandbox was loading a configuration file in one static initialiser. If it had used Parameterisation from Above, there would have been no issue.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305