ปัญหาแท็ก XML ที่ไม่คาดคิดกับไคลเอนต์ Jax Ws

ฉันกำลังใช้บริการเว็บของผู้ขาย สร้างคลาสโดยใช้ JDK6 wsimport สำหรับผู้จำหน่าย WSDL ตอนนี้ฉันกำลังพยายามเรียกใช้บริการเว็บโดยใช้คลาสไคลเอนต์ Java แบบธรรมดาและรับข้อยกเว้นนี้พร้อมการตอบกลับ

แท็ก XML ที่ไม่คาดคิด คาดหวัง: {http://www.abcd.com/addressValidation/}validateAddressResponse แต่พบ: {} ตรวจสอบ AddressResponse

ผู้ขายบอกว่าลองใช้คลาสที่สร้างโดย Apache Axis มันใช้งานได้ดี สิ่งที่ฉันสังเกตเห็นคือ JaxWS จะต่อท้าย/ผูกเนมสเปซกับแต่ละองค์ประกอบที่ร้องขอโดยอัตโนมัติ และคาดหวังเนมสเปซในองค์ประกอบตอบกลับด้วย

อินเทอร์เฟซที่สร้างขึ้นคือ

    @WebService(name = "AddressStandardize", targetNamespace = "http://www.abcd.com/addressValidation/")
@XmlSeeAlso({
    com.abcd.ObjectFactory.class
})
public interface AddressStandardize {

    @WebMethod(action = "http://www.abcd.com/standardizeAddress")
    @RequestWrapper(localName = "validateAddress", targetNamespace = "", className = "com.abcd.ValidateAddress")
    @ResponseWrapper(localName = "validateAddressResponse", targetNamespace = "", className = "com.abcd.ValidateAddressResponse")
    public void standardizeAddress(
    ...
    ...
    ...
    );
}

ฉันเดาว่า Jax-WS จะเพิ่มเนมสเปซเป้าหมายนี้ให้กับทั้งองค์ประกอบ validateAddress และ validateAddressResponse

วิธีหลีกเลี่ยงการผูกเนมสเปซเป้าหมายเพื่อตรวจสอบองค์ประกอบ AddressResponse เพื่อที่จะไม่คาดหวังการตอบกลับ กรุณาช่วย!

Jax WS สร้างคำขอ:

    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Header>
        <ns2:id xmlns:ns2="http://www.abcd.com/addressValidation/">PSA</ns2:id>
    </S:Header>
    <S:Body>
        <ns2:validateAddress xmlns:ns2="http://www.abcd.com/addressValidation/">
            <arg1>
                <addresslineone>126 corbin st</addresslineone>
                <addresslinetwo/>
                <addresslinethree/>
                <city>jersey city</city>
                <state>NJ</state>
                <postalcode/>
                <country/>
                <isocountrycode>US</isocountrycode>
            </arg1>
        </ns2:validateAddress>
    </S:Body>
</S:Envelope>

การตอบกลับ:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xyz="http://www.abcd.com/xyz">
    <soapenv:Header xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <xyz:id>PSA</xyz:id>
    </soapenv:Header>
    <soapenv:Body xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <validateAddressResponse xsi:noNamespaceSchemaLocation="addressValidation.xsd">
            <validateAddressReturn>
                ...
                ...
                ...
            </validateAddressReturn>
            <ResponseStatus>
                <StatusCode>SUCCESS</StatusCode>
            </ResponseStatus>
        </validateAddressResponse>
    </soapenv:Body>
</soapenv:Envelope>

การตอบกลับนี้มาพร้อมกับข้อยกเว้นนี้... แท็ก XML ที่ไม่คาดคิด คาดหวัง: {http://www.abcd.com/addressValidation/}validateAddressResponse แต่พบ: {} ตรวจสอบ AddressResponse


person Gouse1123    schedule 26.08.2015    source แหล่งที่มา


คำตอบ (1)


ฉันพบปัญหานี้ด้วย และไม่สามารถหาวิธีบอก JAX-WS ได้ว่าอย่าคาดหวังเนมสเปซ อย่างไรก็ตาม ฉันสามารถแก้ไขได้โดยการประมวลผลการตอบสนองล่วงหน้าใน SOAPHandler และเพิ่มเนมสเปซให้กับองค์ประกอบ XML ด้วยตนเอง (โดยให้ QName ใหม่ที่มีการประกาศเนมสเปซ)

MyHandler.java:

public class MyHandler implements SOAPHandler<SOAPMessageContext> {
    @Override
    public void close(MessageContext context) { 
    }

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        //Don't intercept outbound messages (SOAP Requests)
        if ((Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) {return true;}

        SOAPMessage message = context.getMessage();
        try {
            SOAPBody body = message.getSOAPBody();
            Iterator<SOAPElement> bodyIterator = body.getChildElements();
            SOAPElement responseElement = bodyIterator.next();
            responseElement.setElementQName(new QName("http://www.theserver.com/cmdb_rel_ci", origGetRecordsResponse.getLocalName(), "cmdb"));
        } catch (Exception e) {e.printStackTrace();}
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return false;
    }

    @Override
    public Set<QName> getHeaders() {
        return Collections.emptySet();
    }
}

จากนั้นฉันก็ต้องเพิ่ม Handler ของฉันไปที่ HandlerChain ด้วยโค้ดต่อไปนี้ในคลาสหลักของฉัน และมันก็ใช้งานได้

Binding binding = ((BindingProvider)port).getBinding();
List<Handler> handlers = binding.getHandlerChain();
handlers.add(new MyHandler());
binding.setHandlerChain(handlers);
person cwh711    schedule 22.04.2016