Java – How to dynamically instantiate an asynchronous service worker in Java

How to dynamically instantiate an asynchronous service worker in Java… here is a solution to the problem.

How to dynamically instantiate an asynchronous service worker in Java

I

work for a bank and I use Java 1.4 for development and applications.
I had to call some specific AS400 service asynchronously, so I decided to use this approach: I created a private static map and populated it into a static block. When I have to call an instance, I get the name of the service to call as a parameter, search for map to contain that string as a key and instantiate the service class.

The problem I’m having is that there are many asynchronous processes working on the same JVM at the same time, and they may retrieve the same service class instance at the same time.

For example:

  • At time 1, Process A calls WBX133 and releases it at time 10
  • At time 3, Process B calls the WBX220 and releases it at time 8
  • At time 4, process C calls WBX133 and releases it at time 13

Since the mapping is static, I will always provide the same instance of the work class to the process, however, each process will have different inputs and expect different outputs from the same service.

Here is the code I explained :

public class AS400ServiceFactory {
   private static Map serviceMap;

static {
       serviceMap = new HashMap();

serviceMap.put("WBX133", new Wbx133Service());
       serviceMap.put("WBX134", new Wbx134Service());
       serviceMap.put("WBX220", new Wbx220Service()); 
       serviceMap.put("WBX360", new Wbx360Service());
       serviceMap.put("WBX370", new Wbx370Service());
       serviceMap.put("WBX371", new Wbx371Service());
   }

public static AS400Container getInstance(String serviceName) {
       ASService service = null;        
       if (serviceMap.containsKey(serviceName)) {
           service = (ASService) serviceMap.get(serviceName);
       }
   }
}

A quick (but not elegant in my opinion) solution is not to use a static map, just :

public class AS400ServiceFactory {
   public static AS400Container getInstance(String serviceName) {
      ASService service = null;

if (("WBX133").equals(serviceName)) {
          service = new Wbx133Service();
      }
      if (("WBX134").equals(serviceName)) {
          service = new Wbx134Service();
      }
      if (("WBX220").equals(serviceName)) {
          service = new Wbx220Service();
      }
      if (("WBX360").equals(serviceName)) {
          service = new Wbx360Service();
      }
      if (("WBX370").equals(serviceName)) {
          service = new Wbx370Service();
      }
      if (("WBX371").equals(serviceName)) {
          service = new Wbx371Service();
      }
   }
}

This way I don’t have the problem of always having the same instance anymore. However, I will have if-else if like 60-70 service and 60-70 in the future that are not really readable.

Any suggestions would be appreciated.
Thanks in advance,
Francesco

Solution

You can create a service factory map and then use it.

public class AS400ServiceFactory {
  private static Map factories = createFactories();

private static Map createFactories() {
    Map factories = new HashMap();
    factories.put("WBX133", new ServiceFactory(){ public ASService create() { return new Wbx133Service(); } });
    factories.put("WBX134", new ServiceFactory(){ public ASService create() { return new Wbx134Service(); } });
    factories.put("WBX220", new ServiceFactory(){ public ASService create() { return new Wbx220Service(); } });
     More factories here
    return factories;
  }

public static AS400Container getInstance(String serviceName) {
    ServiceFactory factory = (ServiceFactory)factories.get(serviceName);
    ASService service = null;
    if (factory != null) {
      service = factory.create();
    }
     Rest of the method
  }
  private interface ServiceFactory {
    ASService create();
  }
}

Related Problems and Solutions