How do you create and later access an application level resource?

260 views Asked by At

Edit: I am trying to create a shared database connection pool for all sessions of a web application. A different post said the best way to create a servlet context object was by having the init listener create it. I am however unclear on how to make this object available for use by my servlet.

5

There are 5 answers

8
assylias On

One solution is using a private holder class:

public class SomeClass {
    private static class ResourceHolder {
        private static final Resource INSTANCE = new Resource();
    }

    public static Resource getInstance() { 
        return ResourceHolder.INSTANCE;
    }
}

the instance will be initialized when SomeClass.getInstance() is called the first time.

0
Obicere On

Another way you could do this is use static initialization:

public class SomeClass {

    private static final Object[] CONTENT;

    static {
        CONTENT = new Object[SomeOtherClass.getContentSize()]; // To show you can access runtime variables
    }

}

This will initialize the CONTENT array once the class is loaded using the ClassLoader.

0
Tom On

Something like:

public static abstract class Lazy<T> {

    private T t = null;

    public synchronized T get() {
        if (t == null) {
            t = create();
        }
        return t;
    }

    protected abstract T create();
}

public static final Lazy<List<String>> lazyList = new Lazy<List<String>>(){

    @Override
    protected List<String> create() {
        return new ArrayList<String>();
    }
}; 
0
dimo414 On

I'll caution you up front, what you're describing has a bit of code smell, and I suspect you'll do better to avoid this pattern entirely. A static resource that depends on external runtime state breaks all sorts of best practices about variable scope.


What you're describing, however, would best be implemented by either a Supplier or a Future, depending on the work involved in successfully constructing the object you need. The difference is somewhat pedantic, but you'd generally use a Future to hold a reference that will take a long time to compute, while a Supplier generally returns quickly. Future also has some nice hook-ins with Java's concurrency utilities, but by the sound of it you don't need that.

You'd use a Supplier like so:

public class GlobalState {
  public static final Supplier<LazyData> MY_DATA = Suppliers.memoize(
    new Supplier<LazyData>() {
      public LazyData get() {
        // do whatever you need to construct your object, only gets executed once needed
      }
    });

  ...
}

Suppliers.memoize() will cache the result of the first call to the underlying Supplier in a threadsafe way, so simply wrapping the Supplier you define with this call prevents duplicate processing.

0
Peter Lawrey On

The simplest lazy initialisation is to use an enum with one instance.

enum Singleton {
    INSTANCE; // lazy initialised
}

The added problem is you want initialisation values. To handle this you can nest the class.

enum Utility {;
     static MyType val;
     static OtherType val2;

     enum Holder {
         INSTANCE;

         Holder() {
            // uses val and val2
         }
     }

     public static Holder getInstance(MyType val, OtherType val2) {
         Utility.val = val;
         Utility.val2 = val2;
         return Holder.INSTANCE; // only created the first time.
     }
 }

Note: this is thread safe as static block initialisation is safe.