ฉันจะตั้งค่าการหมดเวลาสำหรับไคลเอ็นต์บริการเว็บ 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 หนึ่ง
Ron Tuffin

คำตอบ:


91

ฉันรู้ว่านี่เป็นเรื่องเก่าและมีคำตอบที่อื่น แต่หวังว่าสิ่งนี้จะปิดลง ฉันไม่แน่ใจว่าทำไมคุณถึงต้องการดาวน์โหลด 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 และ (อย่างน้อยบน Linux 32 บิต) 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
polaretto

1
@ Matt1776 ใช่แน่นอนว่ามันหายไป: ในขณะที่ JAX-WS เป็นข้อกำหนด API คุณต้องใช้ไลบรารีในกรณีนี้คือ jaxws-ri.jar หรือ jaxws-rt.jar ซึ่งไม่ได้เป็นส่วนหนึ่งของ JDK คุณต้องดาวน์โหลดและเพิ่มลงใน ptoject ของคุณและคุณจะมีคุณสมบัติเหล่านั้น
polaretto

45

คุณสมบัติในคำตอบที่ยอมรับไม่ได้ผลสำหรับฉันอาจเป็นเพราะฉันใช้งาน 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" หรือไม่
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);

สิ่งนี้ได้ผลสำหรับฉัน


ขอบคุณ! สำหรับฉันเช่นกันมันเป็นวิธีที่ง่ายมาก
kosm

4
สิ่งนี้ใช้คลาส Apache CXF แต่อาจเป็นการดีที่สุดที่จะเพิ่มสิ่งนี้ในคำตอบ ลิงค์ที่ใส่ขวด CXF ไว้ก็ช่วยได้มากเช่นกัน
JBert

@JBert ฉันเห็นด้วย ฉันตอบเมื่อหลายปีก่อนและจำไม่ได้ แก้ไขคำตอบได้ตามต้องการ
Daniel Kaplan

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.timeoutvs com.sun.xml.ws.connect.timeout) เช่นเดียวกับคลาส (หรือส่วนต่อประสาน) ที่กำหนด ( 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) ความคิดที่ดีที่สุดของฉันคือการตั้งค่าทั้งสองโดยใช้ค่าตามตัวอักษรเป็นคีย์
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 จากตำแหน่งที่กำหนดไว้ล่วงหน้าบนคลาสพา ธ โดยค่าเริ่มต้นตำแหน่งจะสัมพันธ์กับตำแหน่งแพ็คเกจของ 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>

แอตทริบิวต์ 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")
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.