【问题标题】:JAX-WS Soap Faults not appearing in WSDLJAX-WS Soap 错误未出现在 WSDL 中
【发布时间】:2013-02-27 18:54:08
【问题描述】:

我正在使用 JAX-WS 创建一个 Web 服务(我正在使用 Java 到 WSDL 方法创建它)。

我无法让我的异常按我的要求工作。

我创建了以下异常类:

@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());
    }
}

这允许我在我的 SOAP 响应中包含以下内容:

<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"/>

但是,因为我的异常是扩展 RuntimeExceptionSOAPFaultException,所以它没有被添加到 WSDL,所以当服务的用户生成他们的客户端存根时,不包括异常。

有谁知道如何创建这个异常来给我预期的输出(即包括故障代码和故障字符串),但也出现在 WSDL 中(我猜它需要是一个检查异常)

我搜索了如此高和低以想出我已经拥有的东西!

【问题讨论】:

  • 什么是 JAX-WS 运行时?
  • 您使用哪个 JAX-WS 实现来构建?
  • wsimport -version JAX-WS RI 2.1.6 in JDK 6
  • 我做了类似的解决方案。我对我们所有的服务操作都抛出了一个检查异常,因此我将一个 SOAP 错误元素映射到每个操作。我的异常是一个检查异常,因此当我从我的 WSDL 生成 java 客户端时,它会在代码中定义。如果您真的想引用故障代码和字符串,您可能必须定义一个新类型来定义您的故障代码和故障字符串,并在您的 WSDL 中引用它。

标签: java exception-handling jax-ws


【解决方案1】:

如果您声明您的 WebMethod 抛出 MyWebServiceException,它将出现在 WSDL 上。

但您可能不应该使用 SOAPFault 代码。如果你创建一个业务异常并抛出它,你可以在客户端得到错误代码,而不会弄乱soap内部。

您的网络方法如下所示:

@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;
}

您的业务例外:

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;

}

返回一个异常将是:

<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>

您也可以添加堆栈跟踪,但最好登录服务器,如果需要,可以使用 GUID 与客户端错误相关联。

【讨论】:

  • 最后选择了这个。完成这项工作,删除了堆栈跟踪,响应非常干净
  • faultcodefaultstring可以在这个解决方案中修改吗?
【解决方案2】:

假设您使用的是 JAX-WS 而不是 JAX-RPC,您可以删除 extends SOAPFaultException。然后将必填字段添加到您自己的异常中:

这是一个 StackTraceElement(仅作为示例):

    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;
    }

这是 SOAP 信息:

    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.  :-) */
    }

这是真正的例外:

    @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;
       }
   }

老实说,我没有把它放到一个测试项目中。所以你可能需要解决一些编译问题。但我希望你能明白。

【讨论】:

  • 我不太关心堆栈跟踪,而更关心faultCodefaultString 元素,您能说明如何在您的示例中集成这些元素吗?
  • 我将这两个元素添加到SOAPFaultInfo 类中。
  • 我还没有实际测试过这个,但它看起来是最有希望的答案,今天晚些时候会尝试,让你知道它是怎么回事。
  • 这不起作用,因为super(fault); 无法编译。我应该在这里扩展其他课程吗?
  • 该死...错别字... :-) 不只是将SOAPFaultInfo 存储在异常类的私有字段中。我从我的一个项目中的一个更复杂的场景中复制了这个课程......对不起。我编辑了我的答案...
猜你喜欢
  • 1970-01-01
  • 2014-03-02
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-21
  • 1970-01-01
相关资源
最近更新 更多