Làm cách nào để đặt thời gian chờ cho máy khách dịch vụ web JAX-WS?


93

Tôi đã sử dụng JAXWS-RI 2.1 để tạo giao diện cho dịch vụ web của mình, dựa trên WSDL. Tôi có thể tương tác với dịch vụ web không có vấn đề gì, nhưng không thể chỉ định thời gian chờ để gửi yêu cầu đến dịch vụ web. Nếu vì lý do nào đó mà nó không phản hồi, khách hàng có vẻ như quay bánh xe của nó mãi mãi.

Việc săn lùng xung quanh đã tiết lộ rằng tôi có lẽ nên cố gắng làm điều gì đó như thế này:

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

Tôi cũng phát hiện ra rằng, tùy thuộc vào phiên bản JAXWS-RI mà bạn có, bạn có thể cần đặt các thuộc tính này để thay thế:

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

Tôi có vấn đề là, bất kể là những điều trên là đúng, tôi không biết nơi tôi có thể làm điều này. Tất cả những gì tôi có là một Servicelớp con triển khai giao diện được tạo tự động cho dịch vụ web và tại thời điểm điều này đang được cài đặt, nếu WSDL không đáp ứng thì đã quá muộn để đặt các thuộc tính:

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

Ai đó có thể chỉ cho tôi phương hướng đúng không?!


5
Tôi không nghĩ tôi có câu trả lời cho bạn, nhưng câu hỏi của bạn đã giúp tôi giải quyết vấn đề của mình. Tôi biết về thuộc tính com.sun.xml.ws.request.timeout nhưng không biết về thuộc tính com.sun.xml.internal.ws.request.timeout.
Ron Tuffin

Câu trả lời:


90

Tôi biết điều này đã cũ và đã được trả lời ở nơi khác nhưng hy vọng điều này sẽ kết thúc điều này. Tôi không chắc tại sao bạn muốn tải xuống WSDL động nhưng thuộc tính hệ thống:

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

sẽ áp dụng cho tất cả các lần đọc và kết nối bằng HttpURLConnection mà JAX-WS sử dụng. Điều này sẽ giải quyết vấn đề của bạn nếu bạn đang nhận WSDL từ một vị trí từ xa - nhưng một tệp trên đĩa cục bộ của bạn có lẽ tốt hơn!

Tiếp theo, nếu bạn muốn đặt thời gian chờ cho các dịch vụ cụ thể, sau khi tạo proxy, bạn cần truyền nó tới BindingProvider (mà bạn đã biết), lấy ngữ cảnh yêu cầu và đặt thuộc tính của bạn. Tài liệu JAX-WS trực tuyến là sai, đây là những tên thuộc tính chính xác (tốt, chúng phù hợp với tôi).

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

Tất nhiên, đây là một cách làm kinh khủng, tôi sẽ tạo ra một nhà máy tốt để sản xuất các nhà cung cấp ràng buộc này có thể được cung cấp với thời gian chờ bạn muốn.


10
Lưu ý rằng các thuộc tính REQUEST_TIMEOUT / CONNECT_TIMEOUT thực sự được kế thừa từ lớp SUN-internal com.sun.xml.internal.ws.developer.JAXWSProperties và (ít nhất trên Linux 32-bit) javac 1.6.0_27 và javac 1.7.0_03 không thành công biên dịch mã này (tương tự như bug.sun.com/view_bug.do?bug_id=6544224 ) ... bạn cần chuyển -XDignore.symbol.file cho javac để làm cho nó hoạt động.
JavaGuy

Điều gì không hoạt động? Tôi chỉ cần kiểm tra lại điều này và nó đang hoạt động cho tôi.
alpian

Chỉ cần xác nhận rằng tôi vừa sử dụng cái này với JAX-WS RI 2.2.8 và JDK 1.7 và nó hoạt động tốt. Cảm ơn bạn!
bconneen

Không nên sử dụng các lớp và tham số có "nội bộ" trong tên đủ điều kiện của chúng, vì phụ thuộc vào nhà cung cấp và do đó không thể di động giữa các triển khai JDK khác nhau. Ví dụ: trong trường hợp tham số jax-ws, các thuộc tính không phải bên trong tương ứng tồn tại trong lớp com.sun.xml.ws.client.BindingProviderProperties.
polaretto

1
@ Matt1776 vâng, tất nhiên là nó bị thiếu: mặc dù JAX-WS là một đặc tả API, bạn cần triển khai thư viện, trong trường hợp này là jaxws-ri.jar hoặc jaxws-rt.jar, không phải là một phần của JDK. Bạn chỉ cần tải xuống và thêm nó vào ptoject của mình và bạn sẽ có những thuộc tính đó.
polaretto

41

Các thuộc tính trong câu trả lời được chấp nhận không hoạt động với tôi, có thể vì tôi đang sử dụng triển khai JBoss của JAX-WS?

Sử dụng một tập hợp các thuộc tính khác nhau (có trong Hướng dẫn sử dụng JBoss JAX-WS ) đã làm cho nó hoạt động:

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

2
Tôi không sử dụng JBoss, nhưng chỉ các thuộc tính trong nhận xét này phù hợp với tôi, không có gì khác đã làm.
PaulP

2
Tên thuộc tính phụ thuộc vào việc triển khai JAX-WS. Bạn có thể tìm thấy danh sách tại đây: java.net/jira/browse/JAX_WS-1166
fabstab

3
liên kết java.net bị hỏng. github.com/javaee/metro-jax-ws/issues/1166
trunkc

12

Đây là giải pháp làm việc của tôi:

// --------------------------
// 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.");

    }
}

3
Các cấu hình này có tương đương với "javax.xml.ws.client.connectionTimeout" và "javax.xml.ws.client.receiveTimeout" không ??
Jose Tepedino

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

Điều này đã làm việc cho tôi.


Cảm ơn! Đối với tôi cũng vậy, đó là một cách thực sự dễ dàng
kosm

4
Tuy nhiên, điều này sử dụng các lớp Apache CXF, tốt nhất có thể thêm điều này vào câu trả lời. Một liên kết đến các lọ CXF chứa chúng cũng sẽ giúp ích rất nhiều.
JBert

@JBert Tôi đồng ý. Tôi đã trả lời điều này nhiều năm trước và không thể nhớ. Vui lòng chỉnh sửa câu trả lời.
Daniel Kaplan

8

Nếu bạn đang sử dụng JAX-WS trên JDK6, hãy sử dụng các thuộc tính sau:

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

System.setProperty ("com.sun.xml.internal.ws.connect.timeout", "300"); System.setProperty ("com.sun.xml.internal.ws.request.timeout", "300") phù hợp với tôi.
2787184

2
Trong một số ngữ cảnh, bạn không biết thời gian lập trình phiên bản JAXWS nào (nội bộ hoặc độc lập) sẽ được sử dụng trong thời gian chạy. Cả hai khá tương thích, ngoại trừ tính năng thời gian chờ này. Các khóa khác nhau ( com.sun.xml.internal.ws.connect.timeoutso với com.sun.xml.ws.connect.timeout) cũng như lớp (hoặc giao diện) xác định chúng ( com.sun.xml.internal.ws.developer.JAXWSProperties/ com.sun.xml.internal.ws.client.BindingProviderPropertiesvs com.sun.xml.ws.developer.JAXWSProperties/ com.sun.xml.ws.client.BindingProviderProperties). Ý tưởng tốt nhất của tôi là đặt cả hai, sử dụng các giá trị theo nghĩa đen làm khóa.
Lorinczy Zsigmond

5

Trong trường hợp máy chủ ứng dụng của bạn là WebLogic (đối với tôi là 10.3.6) thì các thuộc tính chịu trách nhiệm về thời gian chờ là:

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

3

Không chắc liệu điều này có hữu ích trong bối cảnh của bạn không ...

Đối tượng xà phòng có thể được đúc như một BindingProvider không?

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

Mặt khác, nếu bạn muốn đặt thời gian chờ khi khởi tạo đối tượng MyWebService thì điều này sẽ không hữu ích.

Điều này phù hợp với tôi khi muốn hết thời gian chờ các cuộc gọi WebService riêng lẻ.


2

cách dễ nhất để tránh truy xuất chậm WSDL từ xa khi bạn khởi tạo SEI là không truy xuất WSDL từ điểm cuối dịch vụ từ xa trong thời gian chạy.

điều này có nghĩa là bạn phải cập nhật bản sao WSDL cục bộ của mình bất cứ khi nào nhà cung cấp dịch vụ thực hiện một thay đổi có ảnh hưởng, nhưng cũng có nghĩa là bạn phải cập nhật bản sao cục bộ của mình bất cứ khi nào nhà cung cấp dịch vụ thực hiện một thay đổi có ảnh hưởng.

Khi tôi tạo các sơ khai máy khách của mình, tôi yêu cầu thời gian chạy JAX-WS chú thích SEI theo cách mà nó sẽ đọc WSDL từ một vị trí được xác định trước trên classpath. theo mặc định, vị trí có liên quan đến vị trí gói của Dịch vụ 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>

thuộc tính wsldLocation cho SEI biết nơi có thể tìm thấy WSDL và bản sao đảm bảo rằng wsdl (và hỗ trợ xsd .. vv ..) ở đúng vị trí.

vì vị trí có liên quan đến vị trí gói của SEI, chúng tôi tạo một gói con (thư mục) mới được gọi là wsdl và sao chép tất cả các tạo tác wsdl ở đó.

tất cả những gì bạn phải làm tại thời điểm này là đảm bảo bạn bao gồm tất cả * .wsdl, * .xsd ngoài tất cả * .class khi bạn tạo tệp jar tạo tác client-sơ khai của mình.

(trong trường hợp bạn tò mò, chú thích @webserviceClient là nơi vị trí wsdl này thực sự được đặt trong mã java

@WebServiceClient(name = "httpServices", targetNamespace = "http://www.helter.com/schema/helter/httpServices", wsdlLocation = "./wsdl/helterHttpServices.wsdl")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.