JAX-WS spring服务器端为RuntimeExceptions设置自定义故障消息

时间:2016-06-24 16:22:13

标签: java spring web-services jax-ws jax-ws-customization

问题

默认情况下,当我的服务器上发生扩展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>

请注意,消息 NOT 应为RuntimeException的消息内容,但任何异常的自定义静态消息延伸{{1}可能发生在服务器端。

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

我正在使用spring插件:RuntimeException

我该怎么做?

2 个答案:

答案 0 :(得分:0)

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

  

SoapFaultMappingExceptionResolver更复杂   实现。此解析程序使您可以获取类名   任何可能抛出的异常并将其映射到SOAP Fault,例如   这样:

<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,只需要故障代码。   如果未设置故障字符串,则默认为异常   信息。如果未设置语言,则默认为英语。该   上面的配置将映射类型的异常   带有错误的客户端SOAP Fault的ValidationFailureException   字符串“无效请求”,如以下响应中所示:

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

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

您应该将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 ...

希望这有帮助

答案 1 :(得分: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

祝你好运!