program story

JAX-WS 웹 서비스 클라이언트에 대한 제한 시간을 어떻게 설정합니까?

inputbox 2020. 9. 14. 20:46
반응형

JAX-WS 웹 서비스 클라이언트에 대한 제한 시간을 어떻게 설정합니까?


JAXWS-RI 2.1을 사용하여 WSDL을 기반으로 웹 서비스 용 인터페이스를 만들었습니다. 웹 서비스와 아무 문제없이 상호 작용할 수 있지만 웹 서비스에 요청을 보내기위한 제한 시간을 지정할 수 없습니다. 어떤 이유로 든 응답하지 않으면 클라이언트가 바퀴를 영원히 돌리는 것처럼 보입니다.

주위의 사냥을 통해 아마도 다음과 같은 것을 시도해야 할 것입니다.

((BindingProvider)myInterface).getRequestContext().put("com.sun.xml.ws.request.timeout", 10000);
((BindingProvider)myInterface).getRequestContext().put("com.sun.xml.ws.connect.timeout", 10000);

또한 보유하고있는 JAXWS-RI 버전에 따라 다음 속성을 대신 설정해야 할 수도 있음을 발견했습니다.

((BindingProvider)myInterface).getRequestContext().put("com.sun.xml.internal.ws.request.timeout", 10000);
((BindingProvider)myInterface).getRequestContext().put("com.sun.xml.internal.ws.connect.timeout", 10000);

내가 가진 문제는 위의 어느 것이 올바른지에 관계없이 어디서 이것을 할 수 있는지 모른다 는 것입니다. 내가 가진 모든 Service것은 웹 서비스에 대한 자동 생성 인터페이스를 구현 하는 하위 클래스이며 WSDL이 응답하지 않으면 속성을 설정하기에는 이미 너무 늦었습니다.

MyWebServiceSoap soap;
MyWebService service = new MyWebService("http://www.google.com");
soap = service.getMyWebServiceSoap();
soap.sendRequestToMyWebService();

누구든지 올바른 방향으로 나를 가리킬 수 있습니까?!


나는 이것이 오래되었고 다른 곳에서 대답했다는 것을 알고 있지만 희망적으로 이것은 이것을 닫습니다. WSDL을 동적으로 다운로드해야하는 이유는 모르겠지만 시스템 속성은 다음과 같습니다.

sun.net.client.defaultConnectTimeout (default: -1 (forever))
sun.net.client.defaultReadTimeout (default: -1 (forever))

JAX-WS가 사용하는 HttpURLConnection을 사용하여 모든 읽기 및 연결에 적용해야합니다. 원격 위치에서 WSDL을 가져 오는 경우 문제가 해결되지만 로컬 디스크에있는 파일이 더 좋습니다!

다음으로, 특정 서비스에 대한 시간 제한을 설정하려면 프록시를 만든 후이를 BindingProvider (이미 알고있는)로 캐스팅하고 요청 컨텍스트를 가져와 속성을 설정해야합니다. 온라인 JAX-WS 문서가 잘못되었습니다. 이것은 올바른 속성 이름입니다 (글쎄요, 저에게 적합합니다).

MyInterface myInterface = new MyInterfaceService().getMyInterfaceSOAP();
Map<String, Object> requestContext = ((BindingProvider)myInterface).getRequestContext();
requestContext.put(BindingProviderProperties.REQUEST_TIMEOUT, 3000); // Timeout in millis
requestContext.put(BindingProviderProperties.CONNECT_TIMEOUT, 1000); // Timeout in millis
myInterface.callMyRemoteMethodWith(myParameter);

물론 이것은 작업을 수행하는 끔찍한 방법입니다. 원하는 시간 제한을 삽입 할 수있는 이러한 바인딩 공급자를 생성하기위한 멋진 팩토리를 만들겠습니다.


허용 된 답변의 속성이 JAX-WS의 JBoss 구현을 사용하고 있기 때문에 작동하지 않았습니다.

다른 속성 집합 ( JBoss JAX-WS 사용자 가이드에 있음 )을 사용하면 다음과 같이 작동합니다.

//Set timeout until a connection is established
((BindingProvider)port).getRequestContext().put("javax.xml.ws.client.connectionTimeout", "6000");

//Set timeout until the response is received
((BindingProvider) port).getRequestContext().put("javax.xml.ws.client.receiveTimeout", "1000");

내 작업 솔루션은 다음과 같습니다.

// --------------------------
// SOAP Message creation
// --------------------------
SOAPMessage sm = MessageFactory.newInstance().createMessage();
sm.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
sm.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-8");

SOAPPart sp = sm.getSOAPPart();
SOAPEnvelope se = sp.getEnvelope();
se.setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/");
se.setAttribute("xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/");
se.setAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
se.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");

SOAPBody sb = sm.getSOAPBody();
// 
// Add all input fields here ...
// 

SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection();
// -----------------------------------
// URL creation with TimeOut connexion
// -----------------------------------
URL endpoint = new URL(null,
                      "http://myDomain/myWebService.php",
                    new URLStreamHandler() { // Anonymous (inline) class
                    @Override
                    protected URLConnection openConnection(URL url) throws IOException {
                    URL clone_url = new URL(url.toString());
                    HttpURLConnection clone_urlconnection = (HttpURLConnection) clone_url.openConnection();
                    // TimeOut settings
                    clone_urlconnection.setConnectTimeout(10000);
                    clone_urlconnection.setReadTimeout(10000);
                    return(clone_urlconnection);
                    }
                });


try {
    // -----------------
    // Send SOAP message
    // -----------------
    SOAPMessage retour = connection.call(sm, endpoint);
}
catch(Exception e) {
    if ((e instanceof com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl) && (e.getCause()!=null) && (e.getCause().getCause()!=null) && (e.getCause().getCause().getCause()!=null)) {
        System.err.println("[" + e + "] Error sending SOAP message. Initial error cause = " + e.getCause().getCause().getCause());
    }
    else {
        System.err.println("[" + e + "] Error sending SOAP message.");

    }
}

ProxyWs proxy = (ProxyWs) factory.create();
Client client = ClientProxy.getClient(proxy);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(0);
httpClientPolicy.setReceiveTimeout(0);
http.setClient(httpClientPolicy);

이것은 나를 위해 일했습니다.


JDK6에서 JAX-WS를 사용하는 경우 다음 특성을 사용하십시오.

com.sun.xml.internal.ws.connect.timeout  
com.sun.xml.internal.ws.request.timeout

In case your appserver is WebLogic (for me it was 10.3.6) then properties responsible for timeouts are:

com.sun.xml.ws.connect.timeout 
com.sun.xml.ws.request.timeout

Not sure if this will help in your context...

Can the soap object be cast as a BindingProvider ?

MyWebServiceSoap soap;
MyWebService service = new MyWebService("http://www.google.com");
soap = service.getMyWebServiceSoap();
// set timeouts here
((BindingProvider)soap).getRequestContext().put("com.sun.xml.internal.ws.request.timeout", 10000);
    soap.sendRequestToMyWebService();

On the other hand if you are wanting to set the timeout on the initialization of the MyWebService object then this will not help.

This worked for me when wanting to timeout the individual WebService calls.


the easiest way to avoid slow retrieval of the remote WSDL when you instantiate your SEI is to not retrieve the WSDL from the remote service endpoint at runtime.

this means that you have to update your local WSDL copy any time the service provider makes an impacting change, but it also means that you have to update your local copy any time the service provider makes an impacting change.

When I generate my client stubs, I tell the JAX-WS runtime to annotate the SEI in such a way that it will read the WSDL from a pre-determined location on the classpath. by default the location is relative to the package location of the Service SEI


<wsimport
    sourcedestdir="${dao.helter.dir}/build/generated"
    destdir="${dao.helter.dir}/build/bin/generated"
    wsdl="${dao.helter.dir}/src/resources/schema/helter/helterHttpServices.wsdl"
    wsdlLocation="./wsdl/helterHttpServices.wsdl"
    package="com.helter.esp.dao.helter.jaxws"
    >
    <binding dir="${dao.helter.dir}/src/resources/schema/helter" includes="*.xsd"/>
</wsimport>
<copy todir="${dao.helter.dir}/build/bin/generated/com/helter/esp/dao/helter/jaxws/wsdl">
    <fileset dir="${dao.helter.dir}/src/resources/schema/helter" includes="*" />
</copy>

the wsldLocation attribute tells the SEI where is can find the WSDL, and the copy makes sure that the wsdl (and supporting xsd.. etc..) is in the correct location.

since the location is relative to the SEI's package location, we create a new sub-package (directory) called wsdl, and copy all the wsdl artifacts there.

all you have to do at this point is make sure you include all *.wsdl, *.xsd in addition to all *.class when you create your client-stub artifact jar file.

(in case your curious, the @webserviceClient annotation is where this wsdl location is actually set in the java code

@WebServiceClient(name = "httpServices", targetNamespace = "http://www.helter.com/schema/helter/httpServices", wsdlLocation = "./wsdl/helterHttpServices.wsdl")

참고URL : https://stackoverflow.com/questions/2148915/how-do-i-set-the-timeout-for-a-jax-ws-webservice-client

반응형