将返回的 SOAPFaultException 重构为 MyFaultException

Refactor the returned SOAPFaultException to MyFaultException

我现在在尝试更改 wss4j 身份验证期间返回的错误异常时遇到问题。我成功地更改了错误主体,我可以向它添加详细信息,但返回给用户的异常仍然来自 javax.xml.ws.soap.SOAPFaultException 类型,而不是我的新错误异常。

当我从 camel 抛出我的故障异常时,因为在路由期间发生异常,故障类型对我的故障异常是正确的,而不是 javax.xml.ws.soap.SOAPFaultException,所以请让我知道是否有办法改变默认行为.

public class CustomFaultOutInterceptor  extends FaultOutInterceptor {

private static final transient Logger LOG = LoggerFactory.getLogger(CustomFaultOutInterceptor.class);

@Override
public void handleMessage(Message message) throws Fault {
    LOG.info(" >> Problem occurred during handling the request/response message");


    //Get the original exception from the fault exception
    Throwable callingServiceException = message.getContent(Exception.class);


    String faultString = null;
    FaultMessageEnum faultMessage = FaultMessageEnum.UN_DEFINED_ERROR;
    boolean isFaultExceptionNotFromTypeMyFaultException = false; //from camel route error handler
    boolean isFaultExceptionUnDefined = false;
    if(callingServiceException.getCause() != null) {
        if (callingServiceException.getCause() instanceof org.apache.wss4j.common.ext.WSSecurityException) {
            // Wrong header format or time-stamp
            faultMessage = FaultMessageEnum.MESSAGE_FORMAT_OR_TIMESTAMP_EXCEPTION;
            faultString = faultMessage.errorMessage();

            isFaultExceptionNotFromTypeMyFaultException = true;
        } else if (callingServiceException.getCause() instanceof org.apache.cxf.interceptor.security.AuthenticationException) {
            // Wrong User-name/Password

            faultMessage = FaultMessageEnum.AUTHENTICATION_FAILED_ERROR;
            faultString = faultMessage.errorMessage();

            isFaultExceptionNotFromTypeMyFaultException = true;
        } else if (callingServiceException.getCause() instanceof org.apache.cxf.interceptor.security.AccessDeniedException) {
            // Unauthorized Access
            faultMessage = FaultMessageEnum.AUTHORIZATION_FAILED_ERROR;
            faultString = faultMessage.errorMessage();

            isFaultExceptionNotFromTypeMyFaultException = true;
        } else if (callingServiceException.getCause() instanceof MyFaultException) {
            faultString = convertObjectToJSON(((MyFaultException)callingServiceException.getCause()).getFaultInfo());
        }

    }

    if (faultString == null) {
        isFaultExceptionUnDefined = true;
        isFaultExceptionNotFromTypeMyFaultException = true;

        while(callingServiceException.getCause() != null) { //Get the actual exception
            callingServiceException = callingServiceException.getCause();
        }

        faultString = "{\"faultString\":\"" + callingServiceException.getMessage() + "\",\"cause\":\""
                + callingServiceException.getClass().getCanonicalName() + "\"}";    
    }


    // Wrap the fault exception to MyFaultException if isFaultExceptionNotFromTypeMyFaultException = true
    if (isFaultExceptionNotFromTypeMyFaultException ) {
        // Alter the fault exception to MyFaultException
        SimpleExceptionBean wrappedException = new SimpleExceptionBean(faultMessage.getType(), faultMessage.getCode(), faultMessage.getDescription());
        MyFaultException newException = null;
        if(isFaultExceptionUnDefined)
            newException = new MyFaultException(callingServiceException.getMessage(), wrappedException, callingServiceException);
        else
            newException = new MyFaultException(faultMessage.getDescription(), wrappedException, callingServiceException);

        Fault newfault = new Fault(newException, new QName(faultMessage.getType()));
        /*try {
            JAXBDataBinding binding = new JAXBDataBinding(SimpleExceptionBean.class); 
            DataWriterImpl<Element> writer = new DataWriterImpl<Element>(binding);
            writer.write(wrappedException, null, newfault.getOrCreateDetail()); 
        } catch (JAXBException e) {
            LOG.error(e.getMessage());
        } */

        message.setContent(Exception.class, newfault);
    }

}

在客户端,CustomFaultOutInterceptor

包装 org.apache.cxf.interceptor.security.AuthenticationException

javax.xml.ws.soap.SOAPFaultException: Wrong Authentication Credentials.
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:161)
    at com.sun.proxy.$Proxy33.getCarInfoByPlate(Unknown Source)
    at com.mycompany.integration.elm.client.wsservice.TestWebService.main(TestWebService.java:49)
Caused by: org.apache.cxf.binding.soap.SoapFault: Wrong Authentication Credentials.
    at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterceptor.java:86)
    at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:52)
    at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:41)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
    at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:112)
    at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69)
    at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
    at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:801)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1672)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1551)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1348)
    at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:56)
    at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:216)
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:651)
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
    at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:514)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:423)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:324)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:277)
    at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:139)

我没有得到直接的解决方案。我通过如下构建故障的详细对象手册来解决它:

        // Build Fault Message Detail
        Document newDoc = DOMUtils.createDocument();
        Element exceptionDetail = newDoc.createElement("detail");

        Element esbFaultNode = newDoc.createElement(newException.getClass().getSimpleName());
        exceptionDetail.appendChild(esbFaultNode);

        Element faultTypeBeanNode = newDoc.createElement("ErrorType");
        faultTypeBeanNode.setTextContent(newFaultExceptionbean.getType().name());
        Element faultCodeBeanNode = newDoc.createElement("ErrorCode");
        faultCodeBeanNode.setTextContent(newFaultExceptionbean.getCode().toString());
        Element faultMessageBeanNode = newDoc.createElement("ErrorMessage");
        faultMessageBeanNode.setTextContent(newFaultExceptionbean.getMessage());

        esbFaultNode.appendChild(faultTypeBeanNode);
        esbFaultNode.appendChild(faultCodeBeanNode);
        esbFaultNode.appendChild(faultMessageBeanNode);


        // Set the fault detail
        newfault.setDetail(exceptionDetail);`