Bir JAX-WS web hizmeti istemcisi için zaman aşımını nasıl ayarlayabilirim?


93

Web hizmetim için WSDL tabanlı bir arayüz oluşturmak için JAXWS-RI 2.1 kullandım. Web hizmetiyle sorunsuz etkileşim kurabiliyorum, ancak web hizmetine istek göndermek için bir zaman aşımı belirleyemedim. Herhangi bir nedenle cevap vermezse, müşteri tekerleklerini sonsuza kadar döndürüyormuş gibi görünür.

Etrafta dolaşmak, muhtemelen böyle bir şey yapmaya çalışmam gerektiğini ortaya çıkardı:

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

Ayrıca, sahip olduğunuz JAXWS-RI sürümüne bağlı olarak şu özellikleri ayarlamanız gerekebileceğini de keşfettim:

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

Sorun şu ki, yukarıdakilerden hangisi doğru olursa olsun, bunu nerede yapabileceğimi bilmiyorum . Sahip olduğum tek şey Service, web hizmetine otomatik olarak oluşturulan arabirimi uygulayan bir alt sınıf ve bu noktada, WSDL yanıt vermiyorsa, özellikleri ayarlamak için çok geç kalınmıştır:

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

Biri beni doğru yönü gösterebilir mi ?!


5
Sana bir cevabım olduğunu sanmıyorum, ama sorunuz sorunumu çözmeme yardımcı oldu. Com.sun.xml.ws.request.timeout özelliğini biliyordum ama com.sun.xml.internal.ws.request.timeout birini bilmiyordum.
Ron Tuffin

Yanıtlar:


91

Bunun eski olduğunu ve başka bir yerde yanıtlandığını biliyorum ama umarım bu bunu kapatır. WSDL'yi neden dinamik olarak indirmek istediğinizden emin değilim ama sistem özellikleri:

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

JAX-WS'nin kullandığı tüm okumalara ve HttpURLConnection kullanılarak bağlanmaya uygulanmalıdır. WSDL'yi uzak bir konumdan alıyorsanız, bu sorununuzu çözmelidir - ancak yerel diskinizdeki bir dosya muhtemelen daha iyidir!

Daha sonra, belirli hizmetler için zaman aşımlarını ayarlamak istiyorsanız, proxy'nizi oluşturduktan sonra onu bir BindingProvider'a (zaten bildiğiniz) dönüştürmeniz, istek bağlamını almanız ve özelliklerinizi ayarlamanız gerekir. Çevrimiçi JAX-WS dokümantasyonu yanlış, bunlar doğru mülk isimleridir (benim için çalışıyorlar).

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

Elbette, bu işleri yapmanın korkunç bir yolu, istediğiniz zaman aşımlarıyla enjekte edilebilen bu bağlayıcı sağlayıcıları üretmek için güzel bir fabrika yaratırdım.


10
REQUEST_TIMEOUT / CONNECT_TIMEOUT özelliklerinin aslında SUN-dahili sınıf com.sun.xml.internal.ws.developer.JAXWSProperties ve (en azından 32-bit Linux'ta) javac 1.6.0_27 ve javac 1.7.0_03'ten miras alındığını unutmayın. bu kodu derleyin ( bugs.sun.com/view_bug.do?bug_id=6544224'e benzer ) ... çalışmasını sağlamak için -XDignore.symbol.file dosyasını javac'a geçirmeniz gerekir.
JavaGuy

Ne çalışmıyor? Bunu iki kez kontrol ettim ve benim için çalışıyor.
alpian

Sadece bunu JAX-WS RI 2.2.8 ve JDK 1.7 ile kullandığımı ve gayet iyi çalıştığını onaylıyorum. Teşekkür ederim!
bconneen

Tam olarak nitelenmiş adlarında "dahili" bulunan sınıflar ve parametreler, satıcıya bağlı olduğundan ve dolayısıyla farklı JDK uygulamaları arasında taşınabilir olmadığından kullanılmamalıdır. Örneğin jax-ws parametreleri durumunda, ilgili dahili olmayan özellikler com.sun.xml.ws.client.BindingProviderProperties sınıfında bulunur.
polaretto

1
@ Matt1776 evet, elbette eksik: JAX-WS bir API spesifikasyonu iken, bir kütüphane uygulamasına ihtiyacınız var, bu durumda JDK'nın bir parçası olmayan jaxws-ri.jar veya jaxws-rt.jar. İndirip ptoject'inize eklemeniz yeterlidir ve bu özelliklere sahip olacaksınız.
polaretto

45

Kabul edilen yanıttaki özellikler benim için işe yaramadı, muhtemelen JAX-WS'nin JBoss uygulamasını kullandığım için?

Farklı bir özellik kümesi kullanmak ( JBoss JAX-WS Kullanım Kılavuzunda bulunur ) işe yaramasını sağladı:

//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 kullanmıyorum, ancak yalnızca bu yorumdaki özellikler benim için çalıştı, başka hiçbir şey yapmadı.
PaulP

2
Özellik adları JAX-WS uygulamasına bağlıdır. Bir liste burada bulunabilir: java.net/jira/browse/JAX_WS-1166
fabstab

3
java.net bağlantısı kesildi. github.com/javaee/metro-jax-ws/issues/1166
trunkc

12

İşte benim çalışma çözümüm:

// --------------------------
// 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
Bu yapılandırmalar "javax.xml.ws.client.connectionTimeout" ve "javax.xml.ws.client.receiveTimeout" ile eşdeğer midir?
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);

Bu benim için çalıştı.


Teşekkürler! Benim için de gerçekten kolay bir yol
kosm

4
Bu, Apache CXF sınıflarını kullanır, bunu yanıta eklemek en iyisi olabilir. CXF kavanozlarının bunları içerdiği bir bağlantı da çok yardımcı olacaktır.
JBert

@JBert Kabul ediyorum. Bunu yıllar önce cevapladım ve hatırlayamıyorum. Cevabı düzenlemekten çekinmeyin.
Daniel Kaplan

8

JDK6'da JAX-WS kullanıyorsanız, aşağıdaki özellikleri kullanın:

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") benim için çalıştı.
2787184

2
Bazı bağlamlarda, hangi JAXWS sürümünün (dahili veya bağımsız) çalışma zamanı kullanılacağını programlama zamanı bilmiyorsunuz. Bu zaman aşımı özelliği dışında ikisi oldukça uyumludur. Anahtarlar farklıdır ( com.sun.xml.internal.ws.connect.timeoutvs com.sun.xml.ws.connect.timeout) ayrıca onları tanımlayan sınıf (veya arayüz) ( 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). En iyi fikrim, anahtar olarak değişmez değerleri kullanarak her ikisini de ayarlamaktır.
Lorinczy Zsigmond

5

Uygulama sunucunuz WebLogic ise (benim için 10.3.6 idi), zaman aşımlarından sorumlu özellikler şunlardır:

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

3

Bunun sizin bağlamınıza yardımcı olup olmayacağından emin değilim ...

Sabun nesnesi bir BindingProvider olarak kullanılabilir mi?

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

Öte yandan, MyWebService nesnesinin başlatılmasında zaman aşımını ayarlamak istiyorsanız, bu yardımcı olmayacaktır.

Bu, bireysel WebService çağrılarını zaman aşımına uğratmak istediğimde benim için çalıştı.


2

SEI'nizi başlattığınızda uzak WSDL'nin yavaş alınmasını önlemenin en kolay yolu, WSDL'yi çalışma zamanında uzak hizmet uç noktasından almamaktır.

bu, servis sağlayıcı etkili bir değişiklik yaptığında yerel WSDL kopyanızı güncellemeniz gerektiği anlamına gelir, ancak aynı zamanda servis sağlayıcısı etkili bir değişiklik yaptığında yerel kopyanızı güncellemeniz gerektiği anlamına gelir.

İstemci saplamalarımı oluşturduğumda, JAX-WS çalışma zamanına SEI'ye, WSDL'yi sınıf yolunda önceden belirlenmiş bir konumdan okuyacak şekilde açıklama eklemesini söylüyorum. varsayılan olarak konum, Hizmet SEI'sinin paket konumuna göredir


<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 özniteliği SEI'ye WSDL'yi nerede bulabileceğini söyler ve kopya wsdl'nin (ve destekleyen xsd .. vb ..) doğru konumda olduğundan emin olur.

konum, SEI'nin paket konumuna göre olduğundan, wsdl adında yeni bir alt paket (dizin) oluştururuz ve tüm wsdl yapılarını oraya kopyalarız.

Bu noktada yapmanız gereken tek şey, client-stub artifact jar dosyanızı oluştururken tüm * .class'a ek olarak tüm * .wsdl, * .xsd'yi dahil ettiğinizden emin olmaktır.

(merak ediyorsanız, @webserviceClient ek açıklaması, bu wsdl konumunun java kodunda gerçekten ayarlandığı yerdir

@WebServiceClient(name = "httpServices", targetNamespace = "http://www.helter.com/schema/helter/httpServices", wsdlLocation = "./wsdl/helterHttpServices.wsdl")
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.