6

问题

默认情况下,当RuntimeException我的服务器上发生未捕获的扩展异常时,JAX-WS 构建以下 SOAP 错误消息:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <S:Fault xmlns:ns3="http://www.w3.org/2003/05/soap-envelope">
         <faultcode>S:Server</faultcode>
         <faultstring>[runtime exception message here]</faultstring>
         <detail>
            <ns2:exception class="java.lang.RuntimeException" 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>[runtime exception message here too]</message>
               <ns2:stackTrace>
                  [stack trace details]
               </ns2:stackTrace>
            </ns2:exception>
         </detail>
      </S:Fault>
   </S:Body>
</S:Envelope>

哪种有意义,除了我想改变这种行为以便发送它:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <S:Fault xmlns:ns3="http://www.w3.org/2003/05/soap-envelope">
         <faultcode>S:Server</faultcode>
         <faultstring>Something wrong happened and it's totally our fault</faultstring>
      </S:Fault>
   </S:Body>
</S:Envelope>

请注意,消息应该是 RuntimeException 的消息内容,而是自定义静态消息,用于扩展可能发生在服务器端的任何异常。RuntimeException

我无法更改 WSDL,也不想设置自定义异常。

我正在使用弹簧插件:com.sun.xml.ws.transport.http.servlet.WSSpringServlet

我怎样才能做到这一点?

4

2 回答 2

0

我认为您可以使用 SoapFaultMappingExceptionResolver http://docs.spring.io/spring-ws/site/reference/html/server.html解决问题

SoapFaultMappingExceptionResolver 是一个更复杂的实现。此解析器使您能够获取可能引发的任何异常的类名并将其映射到 SOAP 故障,如下所示:

<beans>
    <bean id="exceptionResolver"
        class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
        <property name="defaultFault" value="SERVER"/>
        <property name="exceptionMappings">
            <value>
                org.springframework.oxm.ValidationFailureException=CLIENT,Invalid request
            </value>
        </property>
    </bean> </beans>

键值和默认端点使用格式 faultCode,faultString,locale,其中只需要故障代码。如果未设置故障字符串,则默认为异常消息。如果未设置语言,则默认为英语。上述配置会将 ValidationFailureException 类型的异常映射到带有错误字符串“Invalid request”的客户端 SOAP Fault,如以下响应所示:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
       <SOAP-ENV:Fault>
           <faultcode>SOAP-ENV:Client</faultcode>
           <faultstring>Invalid request</faultstring>
       </SOAP-ENV:Fault>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

如果发生任何其他异常,它将返回默认故障:服务器端故障,异常消息作为故障字符串。

您应该将 org.springframework.oxm.ValidationFailureException 异常更改为您感兴趣的异常,即 java.lang.Exception 或 java.lang.RuntimeException

您还可以创建一个自定义异常类

public class CustomGenericAllException extends RuntimeException {


    private String errorCode;
    private String errorMsg;

   //getter and setter for errorCode and errorMsg       

    public CustomGenericAllException(String errorCode, String errorMsg) {
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

}

在每个方法中你都可以抛出这个异常

 throw new CustomGenericAllException("S:Server", "Something wrong happened and it's totally our fault");

并且在 xml 配置中,您可以映射此通用异常 <value>com.testpackage.CustomGenericAllException ...

希望这可以帮助

于 2016-06-27T11:57:15.960 回答
0

我假设您有一个类似于以下端点的端点:

import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.soap.SoapFaultException;
import org.w3c.dom.Element;

@Endpoint
public class HolidayEndpoint {

    private static final String NAMESPACE_URI = "http://mycompany.com/hr/schemas";

    public HolidayEndpoint() {
    }

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "HolidayRequest")                  
    public void handleHolidayRequest(@RequestPayload Element holidayRequest)               
        throws Exception {
      //your code to handle the request on the server
    }
}

现在,假设 handleHolidayRequest() 是您预期 RuntimeException 发生的地方,则必须像这样更改代码:

import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.soap.SoapFaultException;
import org.w3c.dom.Element;

@Endpoint
public class HolidayEndpoint {

    private static final String NAMESPACE_URI = "http://mycompany.com/hr/schemas";

    public HolidayEndpoint() {
    }

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "HolidayRequest")                  
    public void handleHolidayRequest(@RequestPayload Element holidayRequest)               
        throws Exception {
        try
        {
            //your code to handle the request on the server
        }
        catch(RuntimeException e)
        {
            String faultMessage = "Something's wrong on our end. Try again later.";
            throw new SoapFaultException(faultMessage);
        }
    }
}

请注意我如何捕获运行时异常并抛出新的 SoapFaultException?这样做的伎俩和响应是这样的:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <SOAP-ENV:Fault>
         <faultcode>SOAP-ENV:Server</faultcode>
         <faultstring xml:lang="en">Something's wrong on our end. Try again later.</faultstring>
      </SOAP-ENV:Fault>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

现在,如果您使用诸如 spring-integration 之类的服务激活器,它只是相同的概念,除了不是抛出 SoapFaultException,您只需构建一条带有 SoapFaultException 作为有效负载的消息:

@ServiceActivator(inputChannel = "input", outputChannel = "output")
public Message<?> handleHolidayRequest(HolidayRequest holidayRequest) {
   try {
      // your code to handle the request on the server
   } catch (RuntimeException e) {
      String faultMessage = "Something's wrong on our end. Try again later.";
      SoapFaultException soapFaultException = new SoapFaultException(faultMessage);
      return MessageBuilder.withPayload(soapFaultException).build();
   }
}

PS:为了您的理解,我使用了此处的 Web 服务教程示例进行说明(如果您仍在苦苦挣扎,我确实有一个工作示例): http ://docs.spring.io/spring-ws/site/reference/ html/tutorial.html

祝你好运!

于 2016-06-30T13:14:53.567 回答