Since initialization of the WS client service and port takes ages I like to initialize them once at startup and reuse the same instance of the port. Initalization would look
A general solution for this is to use multiple client objects in a pool, then to use proxy that acts as a facade.
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class ServiceObjectPool extends GenericObjectPool {
public ServiceObjectPool(java.util.function.Supplier factory) {
super(new BasePooledObjectFactory() {
@Override
public T create() throws Exception {
return factory.get();
}
@Override
public PooledObject wrap(T obj) {
return new DefaultPooledObject<>(obj);
}
});
}
public static class PooledServiceProxy implements InvocationHandler {
private ServiceObjectPool pool;
public PooledServiceProxy(ServiceObjectPool pool) {
this.pool = pool;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
T t = null;
try {
t = this.pool.borrowObject();
return method.invoke(t, args);
} finally {
if (t != null)
this.pool.returnObject(t);
}
}
}
@SuppressWarnings("unchecked")
public T getProxy(Class super T> interfaceType) {
PooledServiceProxy handler = new PooledServiceProxy<>(this);
return (T) Proxy.newProxyInstance(interfaceType.getClassLoader(),
new Class>[]{interfaceType}, handler);
}
}
To use the proxy:
ServiceObjectPool servicePool = new ServiceObjectPool<>(createSomeNonThreadSafeService);
nowSafeService = servicePool .getProxy(SomeNonThreadSafeService.class);