`
sillycat
  • 浏览: 2536055 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

CXF and Custom Fault Error

 
阅读更多
CXF and Custom Fault Error

Recently, my friend is working on CXF working with Spring boot 2.0.
We get an error as follow:
org.apache.cxf.interceptor.Fault: No binding operation info while invoking unknown method with params unknown.
    at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:59)
Is this a real ERROR from spring boot and CXF? NO, it is not.
If the system visit the ?wsdl link, everything works great, according to a lot of documents or discussion like this https://codeday.me/bug/20190219/659141.html. It is the right behavior from the server side. If the request is not SOAP protocol and can not match any SOAP operation, it will give No binding operation. Our request is a normal GET HTTP to the SOAP Servlet URL, that is the right response.
In old days with axis1.4 in axis.war, they may provide some html response.
It latest CXF 3 or other SOAP library now, It will give error response from org.apache.cxf.interceptor.Fault classes. Which is SOAP response.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
    <soap:Fault>
        <faultcode>soap:Server</faultcode>
        <faultstring>
            No binding operation info while invoking unknown method with params unknown.
        </faultstring>
    </soap:Fault>
    </soap:Body>
</soap:Envelope>
We can use OutInterceptor in CXF to custom the error content. That is a good thing. Even we are using a integration help plugin called https://github.com/codecentric/cxf-spring-boot-starter consider to custom the error contents.
The issue is, all people consider to custom is the content in <faultstring> or <faultcode>. NOT very popular to make a SOAP SERVER response NON SOAP response, haha.
But in our requirement, we can not change or do anything to the old beasts, legacy system, that is out of our control. They need SOAP Service to return HTML or Text. Let us make it happen.
Fork the plugin project, directly hard code the response there if the error is “No binding….” From Fault class.
https://github.com/luohuazju/cxf-spring-boot-starter
Here is the Interceptor we change
package de.codecentric.cxf.xmlvalidation;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.UnmarshalException;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.transport.http.AbstractHTTPDestination;
import com.ctc.wstx.exc.WstxException;
import com.ctc.wstx.exc.WstxUnexpectedCharException;
import de.codecentric.cxf.common.FaultType;
import de.codecentric.cxf.logging.BaseLogger;
/**
* Apache CXF Interceptor, which is processed early in the Interceptor-Chain,
* that tries to analyze and handle all XML schema valdiation errors that could
* occur somewhere in Apache CXF´s SOAP-Processing. Refers to the
* {@link SoapFaultBuilder} to build a custom Soap-Fault, when
* {@link CustomFaultBuilder} is implemented and configured.
*
* @author Jonas Hecht
*
*/
public class XmlValidationInterceptor extends AbstractSoapInterceptor {
    private static final String NO_BINDDING_ERROR_MESSAGE = "No binding operation info while invoking unknown method with params unknown.";
    private static final String MATCH_TO_OLD_BAD_WRONG_AXIS1 = "<h1>QBWebService</h1>\n"
            + "<p>Hi there, this is an AXIS service!</p>\n"
            + "<i>Perhaps there will be a form for invoking the service here...</i>";
    private static final BaseLogger LOG = BaseLogger.getLogger(XmlValidationInterceptor.class);
    private SoapFaultBuilder soapFaultBuilder;
    public XmlValidationInterceptor() {
        super(Phase.PRE_STREAM);
    }
    @Override
    public void handleMessage(SoapMessage soapMessage) throws Fault {
        Fault fault = (Fault) soapMessage.getContent(Exception.class);
        Throwable faultCause = fault.getCause();
        String faultMessage = fault.getMessage();
        if (containsFaultIndicatingNotSchemeCompliantXml(faultCause, faultMessage)) {
            LOG.schemaValidationError(FaultType.SCHEME_VALIDATION_ERROR, faultMessage);
            soapFaultBuilder.buildCustomFaultAndSet2SoapMessage(soapMessage, FaultType.SCHEME_VALIDATION_ERROR);
        } else if (containsFaultIndicatingSyntacticallyIncorrectXml(faultCause)) {
            LOG.schemaValidationError(FaultType.SYNTACTICALLY_INCORRECT_XML_ERROR, faultMessage);
            soapFaultBuilder.buildCustomFaultAndSet2SoapMessage(soapMessage,
                    FaultType.SYNTACTICALLY_INCORRECT_XML_ERROR);
        } else if (nobindingIssue(faultMessage)) {
            HttpServletResponse response = (HttpServletResponse) soapMessage.getExchange().getInMessage()
                    .get(AbstractHTTPDestination.HTTP_RESPONSE);
            response.setStatus(200);
            try {
                response.getOutputStream().write(MATCH_TO_OLD_BAD_WRONG_AXIS1.getBytes());
                response.getOutputStream().flush();
                soapMessage.getInterceptorChain().abort();
            } catch (IOException ioex) {
                throw new RuntimeException("Error writing the response");
            }
        } else if (someOtherErrorOccured(faultCause)) {
            // Some other Error occured, we don´t know. But we want to react with a Custom
            // Error-Message
            LOG.errorOccuredInBackendProcessing(faultCause);
            soapFaultBuilder.buildCustomFaultAndSet2SoapMessage(soapMessage, FaultType.BACKEND_PROCESSING_FAILED);
        }
    }
    private boolean nobindingIssue(String faultMessage) {
        if (NO_BINDDING_ERROR_MESSAGE.equalsIgnoreCase(faultMessage)) {
            return true;
        }
        return false;
    }
    private boolean containsFaultIndicatingNotSchemeCompliantXml(Throwable faultCause, String faultMessage) {
        if (faultCause instanceof UnmarshalException
                // 1.) If the root-Element of the SoapBody is syntactically correct, but not
                // scheme-compliant,
                // there is no UnmarshalException and we have to look for
                // 2.) Missing / lead to Faults without Causes, but to Messages like "Unexpected
                // wrapper element XYZ found. Expected"
                // One could argue, that this is syntactically incorrect, but here we just take
                // it as Non-Scheme-compliant
                || isNotNull(faultMessage) && faultMessage.contains("Unexpected wrapper element")) {
            return true;
        }
        return false;
    }
    private boolean containsFaultIndicatingSyntacticallyIncorrectXml(Throwable faultCause) {
        if (faultCause instanceof WstxException
                // If Xml-Header is invalid, there is a wrapped Cause in the original Cause we
                // have to check
                || isNotNull(faultCause) && faultCause.getCause() instanceof WstxUnexpectedCharException
                || faultCause instanceof IllegalArgumentException) {
            return true;
        }
        return false;
    }
    private boolean someOtherErrorOccured(Throwable faultCause) {
        // Catch all other (un-)checked Exceptions, to handle with Custom Error-Message
        return isNotNull(faultCause);
    }
    private boolean isNotNull(Object object) {
        return object != null;
    }
    public void setSoapFaultBuilder(SoapFaultBuilder soapFaultBuilder) {
        this.soapFaultBuilder = soapFaultBuilder;
    }
}
When you want to use that Custom Fault, you just enable it like this.
package com.sillycat.connectors.quickbooks.customfault;
import org.springframework.stereotype.Component;
import de.codecentric.cxf.common.FaultType;
import de.codecentric.cxf.xmlvalidation.CustomFaultBuilder;
@Component
public class CustomSOAPNoBindingFault implements CustomFaultBuilder {
private static final String MATCH_TO_OLD_BAD_WRONG_AXIS1 = "<h1>QBWebService</h1>\n"
+ "<p>Hi there, this is an AXIS service!</p>\n"
+ "<i>Perhaps there will be a form for invoking the service here...</i>";
@Override
public Object createCustomFaultDetail(String originalFaultMessage, FaultType faultContent) {
return MATCH_TO_OLD_BAD_WRONG_AXIS1;
}
@Override
public String createCustomFaultMessage(FaultType arg0) {
return MATCH_TO_OLD_BAD_WRONG_AXIS1;
}
}

References:
https://alvinalexander.com/java/jwarehouse/apache-cxf/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomOutFaultInterceptor.java.shtml
https://github.com/codecentric/cxf-spring-boot-starter
https://github.com/luohuazju/cxf-spring-boot-starter
https://stackoverflow.com/questions/37984617/propagate-exception-from-cxf-interceptor-to-exception-mapper
https://www.jianshu.com/p/db047f740269
https://codeday.me/bug/20190219/659141.html

分享到:
评论

相关推荐

    Developing Web Services with Apache CXF and Axis2(3rd Edition).zip

    Apache CXF = Celtix + XFire,Apache CXF 的前身叫 Apache CeltiXfire,现在已经正式更名为 Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且...

    CXF 一个完整的webService(整合客户端和服务端)

    【CXF:构建Web服务的全面指南】 CXF(CXF: XFire Community eXtended)是一个开源的Java框架,用于构建和部署Web服务。它提供了强大的支持,包括SOAP、RESTful API、WS-*规范等多种协议和服务模型。CXF不仅简化了...

    实战Web Service 之CXF

    实战Web Service 之 CXF 实战Web Service 之 CXF

    apache-cxf-3.3.5

    CXF helps you build and develop services using frontend programming APIs, like JAX-WS and JAX-RS. These services can speak a variety of protocols such as SOAP, XML/HTTP, RESTful HTTP, or CORBA and ...

    CXF打印SOAP报文,记录WebService日志

    import org.apache.cxf.interceptor.Fault; import org.apache.cxf.interceptor.LoggingMessage; import org.apache.cxf.io.CachedOutputStream; import org.apache.cxf.message.Message; import org.apache.cxf....

    Developing Web Services with Apache CXF and Axis2, 3rd Edition

    ### 开发Web服务:使用Apache CXF与Axis2 #### 书籍概述 《开发Web服务:使用Apache CXF与Axis2》(第三版)是一本详细介绍如何利用Apache CXF和Axis2开发高质量Web服务的专业书籍。该书由Kent Kaiok Tong编写,并...

    cxf 3.1.1 jar包

    CXF(CXF: The Apache CXF project is an open source services framework)是一个开源的Java服务框架,它允许开发者创建和消费各种Web服务。CXF的名字来源于"Code first"和"XML first",代表着它支持从Java代码或者...

    cxf的jar包

    CXF(CXF: Composite eXtensible Services Framework)是一个开源的Java框架,它用于构建和开发服务导向架构(SOA)中的Web服务。CXF允许开发者以他们选择的语言(如Java)编写服务端和客户端代码,同时支持多种Web...

    cxf.xml,cxf-servlet.xml,cxf-extension-soap.xml

    &lt;import resource="classpath:META-INF/cxf/cxf.xml"/&gt; &lt;import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/&gt; &lt;import resource="classpath:META-INF/cxf/cxf-servlet.xml"/&gt;

    Cxf转换器示例

    【Cxf转换器示例】是一个关于Web服务技术的实践项目,主要聚焦于Apache CXF框架中的转换器(Converter)功能。Apache CXF是一个开源的Java框架,它用于构建和开发服务导向架构(SOA)和RESTful应用程序。CXF不仅支持...

    cxf框架包 apache-cxf-3.4.3.tar.gz

    Apache CXF是一个开源的Java框架,它主要用于构建和开发Web服务。这个框架允许开发者通过SOAP、RESTful HTTP、XML以及各种协议来实现服务接口。在本案例中,我们讨论的是"apache-cxf-3.4.3.tar.gz",这是Apache CXF ...

    CXF源码:CXF_Spring源码

    【CXF源码分析】 Apache CXF 是一个开源的Java框架,主要用于构建和服务导向架构(SOA)的应用程序。它提供了多种方式来实现Web服务,包括基于Java API for Web Services (JAX-WS) 和 Java API for RESTful Web ...

    cxf源代码,样例,cxfdemo

    【标题】"cxf源代码,样例,cxfdemo" 涉及的主要知识点是Apache CXF框架的使用,特别是其在服务端开发中的应用。Apache CXF是一个开源的Java框架,它允许开发者创建和消费各种Web服务,包括SOAP和RESTful服务。CXF...

    apache-cxf-2.7.7以及cxf客户端所需要的jar包

    Apache CXF是一个开源的Java框架,它主要用于构建和开发Web服务。这个压缩包"apache-cxf-2.7.7以及cxf客户端所需要的jar包"包含了Apache CXF 2.7.7版本及其客户端运行所需的库文件。这些jar包对于创建、部署和消费...

    apache-cxf-2.7.7

    CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载 CXF下载

    Developing Web Services with Apache CXF and Axis2_3rd Edition

    ### 开发Web服务:使用Apache CXF与Axis2(第三版) #### 一、书籍概述 本书《开发Web服务:使用Apache CXF与Axis2》是针对希望学习如何使用Java创建Web服务的专业人士所编写的实用教程。作者Kent Kai Ok Tong以...

    Spring CXF Restful 实例

    在IT行业中,Spring CXF是一个广泛使用的开源框架,它整合了Spring框架的功能和Apache CXF的服务堆栈,为开发人员提供了构建和实现Web服务的强大工具。在这个“Spring CXF Restful实例”中,我们将深入探讨如何利用...

    CXF客户端支持最少jar

    在Java世界中,Apache CXF是一个广泛使用的开源框架,它提供了服务级的API来构建和消费Web服务。CXF客户端是开发人员用来与CXF服务交互的重要组件,它允许我们轻松地调用远程Web服务。然而,为了减小程序的体积和...

    apache-cxf-2.5.2

    Apache CXF 是一个开源的Java框架,用于构建和开发服务导向架构(Service-Oriented Architecture, SOA)和Web服务。这个"apache-cxf-2.5.2"版本是该框架的一个特定发行版,发布于2011年,包含了CXF框架的所有组件和...

    cxf-3.1.5 和 cxf-3.3.13 JAVA7和JAVA8对应CXF资源

    JAVA7和JAVA8对应CXF资源 WebService CXF 用了一天时间找,官网打不开,国内要积分,下下来又永不了。最后终于搞到手,上传上来分享给大家。 jdk版本 CXF版本 java 9及以上 3.3.x java 8 3.x java 7 2.2x --- ...

Global site tag (gtag.js) - Google Analytics