简体   繁体   中英

JAX-WS Handler Ignoring Fault Sub-elements

I'm implementing a web service client using JAX-WS over SOAP. Its error codes are returned in the following way:

<?xml version = '1.0' encoding = 'UTF-8'?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema">
   <env:Header>
      <!-- header stuff goes here -->
   </env:Header>
   <env:Body>
      <env:Fault>
        <abc:fault xmlns:abc="http://example.com/abc">
           <abc:faultcode>12345</abc:faultcode>
           <abc:faultstring>Error message goes here</abc:faultstring>
        </abc:fault>
     </env:Fault>
   </env:Body>
</env:Envelope>

As far as I know, this is not the correct way to do SOAP faults. The subelements of a env:Fault should be <faultcode> and <faultstring> , not a different namespaced <fault> . Unfortunately, I have no way of making the web service change this.

My hope was that I would be able to parse this message in a SOAPHandler and transform it into a regular fault before passing it on to the rest of my code, however when I logged the message in an earlier Handler I saw that the Fault element completely empty. The <abc:fault> was gone!

I'm using JAX-WS on WebSphere 7 and I've tried setting "jaxws.payload.highFidelity" to true in my system properties. Any clues on to how to get at the original message?

Leaving this alone will cause a WebServiceException with a NullPointerException because JAX-WS can't find the faultcode.

So I found the answer to my question. WebSphere 7 uses Axis2. Axis2's MessageContext provides a property called "TRANSPORT_IN" which contains a ByteArrayInputStream. TRANSPORT_IN, as the name implies, contains the exact SOAP message received.

I parsed through the original SOAP message in my Handler#handleFault method using a SAXHandler to retrieve the abc:fault message. I then wrote the abc:fault > faultcode and faultstring to the soapenv:Fault faultcode and faultstring. My application then handles the SOAPFaultException as if it was a normal one.

I'm still very open to any better answers since this feels like roundabout way to do this.

Handler Code:

public boolean handleFault(SOAPMessageContext context) {
    SOAPMessage m = context.getMessage();
    if(m != null) {
        SOAPBody body = m.getSOAPBody();
        SOAPFault fault = body.getFault();
        setAbcFault(fault, context);
    }
}

private void setAbcFault(SOAPFault fault, MessageContext context) {
    ByteArrayInputStream bis = (ByteArrayInputStream)context.get("TRANSPORT_IN");
    // do sax parsing on the input stream
    fault.setFaultCode(abcFaultCodeQName);
    fault.setFaultString(abcFaultString);
}

If you are using JAX-WS, you can use SOAP faults. or that, you need an Exception with @WebFault annotation. You can find a good example in Using SOAP Faults and Exceptions in Java JAX-WS Web Services - Eben Hewitt on Java .

See the answer for returning null or throw exception and How to throw a custom fault on a JAX-WS web service?

Example:

@WebService
public class CalculatorWS {

    public String factorial(int n) throws FactorialException {
        if (n < 0) {
            throw new FactorialException("Negative number!",     // faultstring
                                         "The number n = " + n); // detail
        }
        return BigIntegerMath.factorial(n).toString();
    }

}

With:

public class FactorialException extends Exception {

    String detail;

    public FactorialException(String message, String detail) {
        super(message);
        this.detail = detail;
    }

    public String getFaultInfo() {
        return detail;
    }

}

If the request is:

<soapenv:Envelope ... >
   <soapenv:Header/>
   <soapenv:Body>
      <test:factorial>
         <arg0>-1</arg0>
      </test:factorial>
   </soapenv:Body>
</soapenv:Envelope>

The response is:

<soapenv:Envelope ... >
   <soapenv:Body>
      <soapenv:Fault>
         <faultcode>soapenv:Server</faultcode>
         <faultstring>Negative number!</faultstring>
         <detail>
            <ns2:FactorialExceptionBean xmlns:ns2="http://...">
                The number n = -1
            </ns2:FactorialExceptionBean>
         </detail>
      </soapenv:Fault>
   </soapenv:Body>
</soapenv:Envelope>

( Tested in Websphere 7)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM