Як встановити час очікування для клієнта веб-служби JAX-WS?


93

Я використав 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();

Хтось може вказувати мені в правильному напрямку ?!


5
Я не думаю, що маю для вас відповідь, але ваше запитання допомогло мені вирішити мою проблему. Я знав про властивість com.sun.xml.ws.request.timeout, але не про властивість com.sun.xml.internal.ws.request.timeout.
Рон Таффін

Відповіді:


90

Я знаю, що це старе і відповіли в іншому місці, але, сподіваюся, це закриває це. Я не впевнений, чому ви хочете динамічно завантажувати WSDL, але властивості системи:

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

має застосовуватися до всіх зчитувань та підключень за допомогою HttpURLConnection, який використовує JAX-WS. Це має вирішити вашу проблему, якщо ви отримуєте 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);

Звичайно, це жахливий спосіб зробити щось, я б створив приємну фабрику для виробництва цих постачальників прив'язок, яким можна вводити потрібні тайм-аути.


10
Зверніть увагу, що властивості REQUEST_TIMEOUT / CONNECT_TIMEOUT насправді успадковуються від внутрішнього класу SUN com.sun.xml.internal.ws.developer.JAXWSProperties і (принаймні на 32-розрядної Linux) javac 1.6.0_27 та javac 1.7.0_03 не можуть скомпілюйте цей код (подібно до bugs.sun.com/view_bug.do?bug_id=6544224 ) ... вам потрібно передати -XDignore.symbol.file в javac, щоб він працював.
JavaGuy

Що не працює? Я просто двічі перевірив це, і це працює для мене.
alpian

Тільки підтверджуючи, що я щойно використовував це з JAX-WS RI 2.2.8 та JDK 1.7, і він працював чудово. Спасибі!
bconneen

Класи та параметри, що містять "внутрішній" у повному назві, не повинні використовуватися, оскільки вони залежать від постачальника і, отже, не переносяться серед різних реалізацій JDK. Наприклад, у випадку параметрів jax-ws, відповідні невнутрішні властивості існують у класі com.sun.xml.ws.client.BindingProviderProperties.
поляретто

1
@ Matt1776 так, звичайно, цього немає: хоча JAX-WS є специфікацією API, вам потрібна реалізація бібліотеки, в даному випадку jaxws-ri.jar або jaxws-rt.jar, яка не є частиною JDK. Вам просто потрібно завантажити та додати його до свого ptoject, і у вас будуть доступні ці властивості.
polaretto

41

Властивості прийнятої відповіді у мене не працювали, можливо тому, що я використовую реалізацію JBoss JAX-WS?

Використання іншого набору властивостей (знайдених у Посібнику користувача 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");

2
Я не використовую JBoss, але для мене працювали лише властивості в цьому коментарі, нічого іншого не працювало.
PaulP

2
Назви властивостей залежать від реалізації JAX-WS. Список можна знайти тут: java.net/jira/browse/JAX_WS-1166
fabstab

3
Посилання java.net порушено. github.com/javaee/metro-jax-ws/issues/1166
trunkc

12

Ось моє робоче рішення:

// --------------------------
// 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
Чи еквівалентні ці конфігурації "javax.xml.ws.client.connectionTimeout" та "javax.xml.ws.client.receiveTimeout" ??
Хосе Тепедіно 07.03.18

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

Це спрацювало для мене.


Дякую! Для мене теж це дуже простий спосіб
kosm

4
Тут використовуються класи Apache CXF, однак, можливо, найкраще додати це у відповідь. Посилання, на яке містяться банки CXF, також дуже допомогло б.
JBert

@JBert Я згоден. Я відповів на це багато років тому і не пам’ятаю. Не соромтеся редагувати відповідь.
Даніель Каплан

8

Якщо ви використовуєте JAX-WS на JDK6, використовуйте такі властивості:

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") працював у мене.
2787184,

2
У деяких контекстах ви не знаєте часу програмування, яка версія JAXWS (внутрішня чи автономна) буде використана під час виконання. Ці два цілком сумісні, за винятком цієї функції очікування. Клавіші різні ( com.sun.xml.internal.ws.connect.timeoutпроти com.sun.xml.ws.connect.timeout), а також клас (або інтерфейс), який їх визначає ( com.sun.xml.internal.ws.developer.JAXWSProperties/ com.sun.xml.internal.ws.client.BindingProviderPropertiesпроти com.sun.xml.ws.developer.JAXWSProperties/ com.sun.xml.ws.client.BindingProviderProperties). Моя найкраща ідея - встановити обидва, використовуючи буквальні значення як ключі.
Lorinczy Zsigmond

5

Якщо ваш сервер додатків WebLogic (для мене це було 10.3.6), тоді властивості, що відповідають за таймаути:

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

3

Не впевнений, чи це допоможе у вашому контексті ...

Чи можна мильний предмет відлити як 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();

З іншого боку, якщо ви хочете встановити час очікування для ініціалізації об’єкта MyWebService, це не допоможе.

Це спрацювало для мене, коли я бажав очікувати часу на окремі дзвінки WebService.


2

найпростіший спосіб уникнути повільного отримання віддаленого WSDL під час створення вашого SEI - це не отримувати WSDL з віддаленої кінцевої точки служби під час виконання.

це означає, що вам доведеться оновлювати локальну копію WSDL щоразу, коли постачальник послуг вносить зміни, але це також означає, що вам доведеться оновлювати локальну копію щоразу, коли постачальник послуг вносить зміни.

Коли я генерую клієнтські заглушки, я кажу часу виконання JAX-WS анотувати SEI таким чином, що він буде читати WSDL із заздалегідь визначеного місця на шляху до класу. за замовчуванням розташування є відносно розташування пакета Служби 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>

атрибут wsldLocation повідомляє SEI, де можна знайти WSDL, а копія переконується, що wsdl (і підтримка xsd .. та ін.) знаходиться у правильному місці.

оскільки розташування є відносно розташування пакета SEI, ми створюємо новий підпакет (каталог), який називається wsdl, і копіюємо всі артефакти wsdl туди.

все, що вам потрібно зробити на цьому етапі, - це обов’язково включити всі * .wsdl, * .xsd на додаток до всього * .class, коли ви створюєте файл jar-артефакту клієнт-заглушки.

(якщо вам цікаво, анотація @webserviceClient - це місце, де це розташування wsdl насправді встановлено в коді Java

@WebServiceClient(name = "httpServices", targetNamespace = "http://www.helter.com/schema/helter/httpServices", wsdlLocation = "./wsdl/helterHttpServices.wsdl")
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.