javaweb-servicesexceptionjax-wssoapfault

How to throw a custom fault on a JAX-WS web service?


How do you throw a custom soap fault on a JAX-WS web service? How can I specify the faultCode, faultString and detail of the soap fault? Is it possible to set the value of the detail as bean instead of a String?

Please note that I'm developing using code-first approach.


Solution

  • Use the @WebFault annotation.

    You can see a good example in Using SOAP Faults and Exceptions in Java JAX-WS Web Services - Eben Hewitt on Java.

    You will see the example:

    @WebFault(name="CheckVerifyFault",
        targetNamespace="http://www.example.com")
    public class CheckVerifyFault extends Exception {
    
        /**
         * Java type that goes as soapenv:Fault detail element.
         */
        private CheckFaultBean faultInfo;
    
        public CheckVerifyFault(String message, CheckFaultBean faultInfo) {
            super(message);
            this.faultInfo = faultInfo;
        }
    
        public CheckVerifyFault(String message, CheckFaultBean faultInfo, 
               Throwable cause) {
            super(message, cause);
            this.faultInfo = faultInfo;
        }
    
        public CheckFaultBean getFaultInfo() {
            return faultInfo;
        }
    }
    

    UPDATE

    Another way is to declare the typical exception in the throws clause.

    e.g. Suppose the following is my exception class:

    package pkg.ex;
    
    public class FooException extends Exception {
    
        public FooException(String message, Throwable cause) {
            super(message, cause);
        }
    
    }
    

    And the next class is the service implementation.

    package pkg.ws;
    
    import javax.jws.WebService;
    import pkg.ex.FooException;
    
    @WebService(serviceName = "FooSvc")
    public class FooService {
    
        public String sayHello(String name) throws FooException {
            if (name.isEmpty()) {
                Throwable t = new IllegalArgumentException("Empty name");
                throw new FooException("There is one error", t);
            }
            return "Hello, " + name;
        }
    
    }
    

    If my request is:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                      xmlns:ws="http://ws.pkg/">
       <soapenv:Header/>
       <soapenv:Body>
          <ws:sayHello>
             <arg0>Peter</arg0>
          </ws:sayHello>
       </soapenv:Body>
    </soapenv:Envelope>
    

    There is no problem:

    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
       <S:Body>
          <ns2:sayHelloResponse xmlns:ns2="http://ws.pkg/">
             <return>Hello, Peter</return>
          </ns2:sayHelloResponse>
       </S:Body>
    </S:Envelope>
    

    But...

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                      xmlns:ws="http://ws.pkg/">
       <soapenv:Header/>
       <soapenv:Body>
          <ws:sayHello>
             <arg0></arg0>
          </ws:sayHello>
       </soapenv:Body>
    </soapenv:Envelope>
    

    Then...

    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
       <S:Body>
          <S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
             <faultcode>S:Server</faultcode>
             <faultstring>There is one error</faultstring>
             <detail>
                <ns2:FooException xmlns:ns2="http://ws.pkg/">
                   <message>There is one error</message>
                </ns2:FooException>
             </detail>
          </S:Fault>
       </S:Body>
    </S:Envelope>