How to set timeout in JAX-RPC Web Service client

การกำหนดค่า Timeout ให้กับ Web Service Client ที่เป็น JAX-RPC นั้นถ้าใช้งานกับ WebSphere ก็ไม่อยากอะไรครับมี method ให้กำหนด Timeout อยู่ในตัว Stub เลยแต่พอมาทำบน Netbean และใช้งานกับ GlassFish Netbean กลับไม่สร้างให้ วุ่นวายพอควร ก็เลยหาวิธีจาก อ.google แล้วพอมีหนทางประมาณนี้
1. สร้าง HttpURLConnection ขึ้นมาเองโดยการ extends HttpClientTransport แล้วทำการ Override method createHttpConnection ดังนี้

package com.secondknow.ws;
import com.sun.xml.rpc.client.http.HttpClientTransport;
import com.sun.xml.rpc.soap.message.SOAPMessageContext;
import java.io.IOException;
import java.net.HttpURLConnection;

/**
 * Example HttpTransport
 * @author Supot Saelao
 * @version 1.0
 */
public class ExampleHttpTransport extends HttpClientTransport{
    private int timeout;

    public ExampleHttpTransport(){
		super();
	}

    public ExampleHttpTransport(int timeout){
        this.timeout = timeout;
    }

    @Override
    protected HttpURLConnection createHttpConnection(String endpoint, SOAPMessageContext context) throws IOException {
        HttpURLConnection httpConn = super.createHttpConnection(endpoint, context);
		//If set tmeout 0 never set timeout
        if(timeout > 0){
            httpConn.setReadTimeout(timeout);
            httpConn.setConnectTimeout(timeout);
        }
        return httpConn;
    }
}


2. ทำการสร้าง class เพื่อimplement interface ClientTransportFactory ดังนี้

package com.secondknow.ws;
import com.sun.xml.rpc.client.ClientTransport;
import com.sun.xml.rpc.client.ClientTransportFactory;

/**
 * Example ClientTransportFactory
 * @author Supot Saelao
 * @version 1.0
 */
public class ExampleTransportFactory implements ClientTransportFactory{
    private int timeout;
    
    public EWSTransportFactory(){
    }
    
    public EWSTransportFactory(int timeout){
        this.timeout = timeout;
    }

    public ClientTransport create() {
        return new EWSHttpTransport(timeout);
    }
}

3. จากนั้นเพิ่มการ set ค่า ที่ stub ดังนี้

package com.secondknow.ws;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;

/**
 * Example Test
 * @author Supot Saelao
 * @version 1.0
 */
public class ClientWebservice {

    private static final String WS_URL  = "http://localhost/ExpWS";
    private static final int WS_TIME_OUT    = "30000"; //30 sec , 1 sec = 1000 ms
    private ExampleWS exWS;
    
	public static void main(String[] args){
		ClientWebservice client = new ClientWebservice();
		
		HelloRequest req = new HelloRequest();
		req.setName("Supot");
		req.setAge(28);
		try{
			HelloResponse res = client.hayHello(req);
			System.out.println("response : "+ res);
		} catch (Exception ex) {
			System.out.printl("Exception : "+ ex);
		}
	}

    public ExampleWSSEI createStub() throws ServiceException {
        return createStub(WS_TIME_OUT);
    }

    public ExampleWSSEI createStub(int timeout) throws ServiceException {
        if (exWS == exWS) {
            exWS = new ExampleWS_Impl();
        }

        ExampleWSSEI_Stub wsPortStub = (ExampleWSSEI_Stub) exWS.getExampleWSSEIPort();
        wsPortStub._setProperty(ExampleWSSEI_Stub.ENDPOINT_ADDRESS_PROPERTY, WS_URL);
        if(timeout > 0){
			//Set TransportFactory to customer TransportFactory
            wsPortStub._setTransportFactory(new ExampleTransportFactory(timeout)); 
        }

        return wsPortStub;
    }

    public HelloResponse hayHello(HelloRequest req) throws Exception {
        return hayHello(req, WS_TIME_OUT);
    }

    public HelloResponse hayHello(HelloRequest req, int timeout) throws Exception {
        HelloResponse res = new HelloResponse();
        try {
            ExampleWSSEI service = createStub(timeout);            
            res = service.hayHello(req);
        } catch (javax.xml.rpc.ServiceException ex) {
            throw ex;
        } catch (java.rmi.RemoteException ex) {
            throw ex;
        } catch (Exception ex) {
            throw ex;
        }
		
        return res;
    }
}

สำหรับใครที่ขี้เกียจสร้าง class ExampleTransportFactory ก็ทำแบบนี้ก็ได้ครับ ง่ายดี

public ExampleWSSEI createStub(final int timeout) throws ServiceException {
	if (exWS == exWS) {
		exWS = new ExampleWS_Impl();
	}

	ExampleWSSEI_Stub wsPortStub = (ExampleWSSEI_Stub) exWS.getExampleWSSEIPort();
	wsPortStub._setProperty(ExampleWSSEI_Stub.ENDPOINT_ADDRESS_PROPERTY, WS_URL);
	if(timeout > 0){
		//Set TransportFactory to customer TransportFactory
		wsPortStub._setTransportFactory(new ClientTransportFactory(){
			public ClientTransport create() {
				return new ExampleHttpTransport(timeout);
			}                
		}); 
	}
	return wsPortStub;
}

หมายเหตุ : ผมไม่แน่ใจว่าเป็นวิธีที่ถูกต้อง และดีที่สุดหรือเปล่า ใครพอมีวิธีที่ดีกว่านี้ แนะนำแจ้งด้วยครับ

แหล่งข้อมูล
Setting the timeout value for a JAX-RPC Web Service client [IBM WebSphere]
How to set a connection timeout when using JAXRPC-RI web services client?

  1. No comments yet.

  1. No trackbacks yet.