JAX-WS Soap Faults not appearing in WSDL
Asked Answered
L

2

9

I am creating a web service using JAX-WS (I am creating this using the Java to WSDL approach).

Im having trouble getting my exception to work as I require.

I have created the following exception class:

@WebFault
public class MyWebServiceException extends SOAPFaultException {

    private static final long serialVersionUID = 8234753208722614057L;

    protected MyWebServiceException(SOAPFault fault) {
        super(fault); 
    }

    protected MyWebServiceException(SOAPFault fault, Throwable throwable) {
        this(fault);
        super.setStackTrace(throwable.getStackTrace());
    }
}

This allows me to have the following in my SOAP response:

<faultcode>E0010</faultcode>
<faultstring>Invalid Report</faultstring>
<detail>
    <ns2:exception class="com.example.web.common.exceptions.MyWebServiceException" note="To disable this feature, set com.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace system property to false" xmlns:ns2="http://jax-ws.dev.java.net/">
     <message>Invalid Report</message>
     <ns2:stackTrace>
     <ns2:frame class="com.example.web.common.exceptions.ExceptionHandler" file="ExceptionHandler.java" line="34" method="getWebException"/>

However, because my exception is a SOAPFaultException which extends RuntimeException, it is not being added to the WSDL, so when users of the service generate their client stubs the exception is not included.

Does anyone know how to create this exception to give me the intended output (ie including the faultcode and faultstring) but also appear in the WSDL (I guess it needs to be a checked exception)

I searched SO high and low to come up with what I have already!

Lining answered 12/3, 2013 at 10:4 Comment(4)
What is the JAX-WS runtime?Knack
Which JAX-WS implementation are you using to build?Domesticity
wsimport -version JAX-WS RI 2.1.6 in JDK 6Lining
I did a similar solution. I throw a checked exception on all our service operations so I mapped a SOAP fault element to each operation. My Exception is a checked exception thus it is getting defined in code when I generate a java client out of my WSDL. If you really want to reference the fault codes and strings you may have to define a new type which defines your fault codes and fault strings and reference it in your WSDL.Boilermaker
K
5

If you declare that your WebMethod throws MyWebServiceException, it will appear on WSDL.

But probably you should not mess with SOAPFault codes. If you create a business exception and throw it, you can get error codes in client withoud messing with soap internals.

Your webmethod would look like:

@WebMethod
public String sayHello(@WebParam String name, @WebParam String thing)  throws MyException
{
    // TODO Auto-generated method stub
    if ("err".equals(name))
        throw new MyException("E0010","Report not found");
    return null;
}

Your business exception:

public class MyException extends Exception {

    private static final long serialVersionUID = -923394585528818428L;
    public MyException(String errorCode,String errorMessage)
    {
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
    }

    public String getErrorCode() {
        return errorCode;
    }
    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }
    public String getErrorMessage() {
        return errorMessage;
    }
    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }
    String errorCode;
    String errorMessage;

}

And the return onexception will be:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Server</faultcode>
         <faultstring>Fault occurred while processing.</faultstring>
         <detail>
            <ns1:MyException xmlns:ns1="http://ws/">
               <errorMessage xmlns:ns2="http://ws/">Report not found</errorMessage>
               <errorCode xmlns:ns2="http://ws/">E0010</errorCode>
            </ns1:MyException>
         </detail>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

You can also add a stack trace but that would be better to get logged in server, maybe with a GUUID to correlate with client error if needed.

Kester answered 25/3, 2013 at 11:4 Comment(2)
Went with this one in the end. Does the job, removed the stack trace and the response is quite cleanLining
Can faultcode and faultstring be modified in this solution?Frustule
F
1

Assuming You are using JAX-WS and not JAX-RPC you could just remove the extends SOAPFaultException. Afterwards add the required fields to your own exception:

This is a StackTraceElement (just as an example):

    public class SOAPStackElement implements Serializable {
       private static final long serialVersionUID = 1L;

       @XmlAttribute(name="class")
       private String class;
       @XmlAttribute(name="file")
       private String file;
       @XmlAttribute(name="methodname")
       private String methodName;
       @XmlAttribute(name="line")
       private Integer line;
    }

This is the SOAP-Info:

    public class SOAPFaultInfo implements Serializable {
        @XmlElementWrapper(name="stackTrace")
        private SOAPStackElement[] stackTrace;
        @XmlElement(name="faultcode")
        private String faultCode;
        @XmlElement(name="faultstring")
        private String faultString;
        /* what else your heart desires.  :-) */
    }

And this is the real exception:

    @WebFault
    public class MyWebServiceException extends Exception {

       private static final long serialVersionUID = 1L;
       private SOAPFaultInfo faultInfo;

       protected MyWebServiceException(SOAPFaultInfo fault) {
          super(); 
          this.faultInfo = fault;
       }

       protected MyWebServiceException(SOAPFaultInfo fault, Throwable cause) {
          super(cause);
          this.faultInfo = fault;
       }

       public SOAPFaultInfo getFaultInfo() {
          return faultInfo;
       }
   }

I honestly didnt get around to putting this into a test project. So you might need to iron out some compile issues. But I hope you get the picture.

Fernald answered 25/3, 2013 at 10:52 Comment(5)
I am less concerned about the stacktrace and more concerned about the faultCode and faultString elements, can you show how you would integrate these in your example?Lining
I added the two elements to the SOAPFaultInfo class.Fernald
I havent actually tested this yet but it looks the most promising answer, will try later today and let you know how it went.Lining
This doesnt work, as super(fault); doesnt compile. Is there some other class I should be extending here?Lining
Damn... Typo... :-) No just store the SOAPFaultInfo in a private field in your exception class. I copied the class from a more complex scenario in one of my projects... Sorry. I edited my answer...Fernald

© 2022 - 2024 — McMap. All rights reserved.