Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singleton Object in Java Web service

Good morning, I am currently developing a java web application that exposes a web service interface. In order to keep a global object in memory, I use the following class as a Singleton:

public class SingletonMap {
    private static final SingletonMap instance = new SingletonMap();
    private static HashMap couponMap = null;
    private static long creationTime;

    private SingletonMap() {
        creationTime = System.currentTimeMillis();
        couponMap = new HashMap();
    }

    public static synchronized SingletonMap getInstance() {
        return instance;
    }

    public static long getCreationTime() {
        return creationTime;
    }
}

I am using the above class in order to have the same instance of the HashMap for all the threads of the web service. The Web service class that maintains the SingletonMap object is the following:

@WebService()
public class ETL_WS {
    private String TOMCAT_TEMP_DIR;
    private final int BUFFER_SIZE = 10000000;
    private static SingletonMap couponMap;
    private static SingletonProductMap productCategoryMap;
    private String dbTable = "user_preferences";

    public ETL_WS() {
        Context context = null;
        try {
            context = (Context) new InitialContext().lookup("java:comp/env");
            this.TOMCAT_TEMP_DIR = (String) context.lookup("FILE_UPLOAD_TEMP_DIR");
        }catch(NamingException e) {
        System.err.println(e.getMessage());
    }

    public long getCouponMapCreationTime() {
        return couponMap.getCreationTime();
    }

}

The reason i have the method getCouponMapCreationTime() is to check that all the threads of the web service are accessing the same object. Is the above approach correct? How about performance overheads? Do you think I need the Singleton properties, or could I just use a static HashMap for all the threads? If I use a static HashMap, is it going to be garbage collected in case no thread is active?

Thank you for your time.

like image 212
nick.katsip Avatar asked Jun 19 '12 07:06

nick.katsip


People also ask

What is singleton Web services?

A JAX-WS web service is by itself a Singleton. This means that all the request will be handled using a single web service instance (like a Servlet). So, any member of the class will be 'shared' between all the request. In your case, you do not need to make your members (i.e. couponMap) an static attributes.

What are singleton objects in Java?

In Java, Singleton is a design pattern that ensures that a class can only have one object. To create a singleton class, a class must implement the following properties: Create a private constructor of the class to restrict object creation outside of the class.

What is meant by singleton object?

A Singleton object is an object which defines a single object of a class. A singleton object provides an entry point to your program execution. If you do not create a singleton object in your program, then your code compile successfully but does not give output.

Where do we use singleton class in Java?

It is used where only a single instance of a class is required to control the action throughout the execution. A singleton class shouldn't have multiple instances in any case and at any cost. Singleton classes are used for logging, driver objects, caching and thread pool, database connections.


2 Answers

A JAX-WS web service is by itself a Singleton. This means that all the request will be handled using a single web service instance (like a Servlet).

So, any member of the class will be 'shared' between all the request. In your case, you do not need to make your members (i.e. couponMap) an static attributes.

Conclusion: Don't worry, all your threads (request) will be accessing the same 'couponMap'. Because you don't need the getCouponMapCreationTime anymore, I think that you can eliminate the SingletonMap abstraction and use directly a Map in your web service class.

But I have something very important to add. If several threads (request) will be accessing your Map you have to make it thread-safe!!! There are a lot of way to do this, but I will give an idea: Use a ConcurrentHashMap instead of a HashMap. This will make all your get(), put(), remove() operations thread-safe! If you need a larger scope you can use synchronized blocks, but please avoid synchronize methods because the scoop is too large and always synchronize over this object.

like image 62
ggarciao Avatar answered Sep 29 '22 10:09

ggarciao


JAX-WS has its own patterns for creating singletons, you don't need to use static fields. You use the @Inject annotation into each service. See this blog post: http://weblogs.java.net/blog/jitu/archive/2010/02/19/jax-ws-cdi-java-ee-6-0 (but don't use @SessionScoped, use @Singleton)

Some other points:

  1. HashMap isn't thread-safe, you need ConcurrentHashMap.

  2. This catch(NamingException e) { System.err.println(e.getMessage()); is unhelpful. Rethrow it as a RuntimeException. You can't recover from it.

  3. Don't worry about performance overhead at this stage. Measure it once you have something working.

like image 42
artbristol Avatar answered Oct 01 '22 10:10

artbristol