Is this JAX-WS client call thread safe?

前端 未结 4 642
情歌与酒
情歌与酒 2020-12-14 06:34

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

4条回答
  •  旧时难觅i
    2020-12-14 07:17

    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 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);
    

提交回复
热议问题