【问题标题】:CXF JaxWs Endpoint fail with 'The given SOAPAction does not match an operation' when the action contains accents当操作包含重音符号时,CXF JaxWs 端点因“给定的 SOAPAction 与操作不匹配”而失败
【发布时间】:2014-06-23 23:02:30
【问题描述】:

我对包含重音符号的 SOAPAction 有疑问。

通过第三方 WSDL,我使用 CXF wsdl2java 插件生成了 Java 类。使用生成的类,我开发了一个基于 CXF 的客户端和服务器。问题是服务器无法获取客户端的请求并出现以下错误:

2014-06-19 11:45:08,423 [qtp1051344475-17] WARN - Interceptor for {http://simulator.be.connectors.cam/}RIBSOAPSoapImplService#{http://tempuri.org/}Opération_1 has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: The given SOAPAction http://tempuri.org/RIB_SOAP/Opération_1 does not match an operation.
    at org.apache.cxf.binding.soap.interceptor.SoapActionInInterceptor$SoapActionInAttemptTwoInterceptor.handleMessage(SoapActionInInterceptor.java:188)
    at org.apache.cxf.binding.soap.interceptor.SoapActionInInterceptor$SoapActionInAttemptTwoInterceptor.handleMessage(SoapActionInInterceptor.java:163)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    at ...

客户端的请求日志显示 SOAPAction 的正确值,而服务器端的请求显示错误的值。

客户端的请求是:

2014-06-19 11:45:08,349 [main] INFO - Outbound Message
---------------------------
ID: 1
Address: http://localhost:17081/SIMULATOR/RIB/WS
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml
Headers: {Accept=[*/*], Connection=[Keep-Alive], SOAPAction=["http://tempuri.org/RIB_SOAP/Opération_1"]}
Payload: <?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ns3:Opération_1 xmlns:ns2="http://Rib_InSchema" xmlns:ns3="http://tempuri.org/" xmlns:ns4="http://Rib_OutSchema">
      <ns2:Root>
        <RIB>1234567890</RIB>
      </ns2:Root>
    </ns3:Opération_1>
  </soap:Body>
</soap:Envelope>

--------------------------------------

服务器端的请求是:

2014-06-19 11:45:08,408 [qtp1051344475-17] INFO - Inbound Message
----------------------------
ID: 2
Address: http://localhost:17081/SIMULATOR/RIB/WS
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[339], content-type=[text/xml; charset=UTF-8], Host=[localhost:17081], Pragma=[no-cache], SOAPAction=["http://tempuri.org/RIB_SOAP/Opération_1"], User-Agent=[Apache CXF 2.7.10]}
Payload: <?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ns3:Opération_1 xmlns:ns2="http://Rib_InSchema" xmlns:ns3="http://tempuri.org/" xmlns:ns4="http://Rib_OutSchema">
      <ns2:Root>
        <RIB>1234567890</RIB>
      </ns2:Root>
    </ns3:Opération_1>
  </soap:Body>
</soap:Envelope>

--------------------------------------

从日志中可以看出,UTF-8 是所有级别都使用的编码。但是,由于某种原因,在服务器端,SOAPAction 已使用 ISO-8859-1 进行解码。

使用的 WSDL 是:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/"
    xmlns:s1="http://Rib_InSchema" xmlns:s="http://www.w3.org/2001/XMLSchema"
    xmlns:s2="http://Rib_OutSchema"
    xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
    targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
    <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">BizTalk assembly
        "BTS, Version=1.0.0.0, Culture=neutral,
        PublicKeyToken=dab3109d17486051" published web service.
    </wsdl:documentation>
    <wsdl:types>
        <s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
            <s:import namespace="http://Rib_InSchema" />
            <s:import namespace="http://Rib_OutSchema" />
            <s:element name="Opération_1">
                <s:complexType>
                    <s:sequence>
                        <s:element minOccurs="0" maxOccurs="1" ref="s1:Root" />
                    </s:sequence>
                </s:complexType>
            </s:element>
            <s:element name="Opération_1Response">
                <s:complexType>
                    <s:sequence>
                        <s:element minOccurs="0" maxOccurs="1" ref="s2:Root" />
                    </s:sequence>
                </s:complexType>
            </s:element>
        </s:schema>
        <s:schema elementFormDefault="qualified"
            targetNamespace="http://Rib_InSchema">
            <s:element name="Root">
                <s:complexType>
                    <s:sequence>
                        <s:element minOccurs="0" maxOccurs="1" form="unqualified"
                            name="RIB" type="s:string" />
                    </s:sequence>
                </s:complexType>
            </s:element>
        </s:schema>
        <s:schema elementFormDefault="qualified"
            targetNamespace="http://Rib_OutSchema">
            <s:element name="Root">
                <s:complexType>
                    <s:sequence>
                        <s:element minOccurs="0" maxOccurs="1" form="unqualified"
                            name="NumCompte" type="s:string" />
                        <s:element minOccurs="0" maxOccurs="1" form="unqualified"
                            name="Nom" type="s:string" />
                        <s:element minOccurs="0" maxOccurs="1" form="unqualified"
                            name="Prenom" type="s:string" />
                        <s:element minOccurs="0" maxOccurs="1" form="unqualified"
                            name="Agence" type="s:string" />
                        <s:element minOccurs="0" maxOccurs="1" form="unqualified"
                            name="AgenceAdresse" type="s:string" />
                        <s:element minOccurs="0" maxOccurs="1" form="unqualified"
                            name="RIB" type="s:string" />
                    </s:sequence>
                </s:complexType>
            </s:element>
        </s:schema>
    </wsdl:types>
    <wsdl:message name="Opération_1SoapIn">
        <wsdl:part name="parameters" element="tns:Opération_1" />
    </wsdl:message>
    <wsdl:message name="Opération_1SoapOut">
        <wsdl:part name="parameters" element="tns:Opération_1Response" />
    </wsdl:message>
    <wsdl:portType name="RIB_SOAPSoap">
        <wsdl:operation name="Opération_1">
            <wsdl:input message="tns:Opération_1SoapIn" />
            <wsdl:output message="tns:Opération_1SoapOut" />
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="RIB_SOAPSoap"
        type="tns:RIB_SOAPSoap">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="Opération_1">
            <soap:operation
                soapAction="http://tempuri.org/RIB_SOAP/Opération_1"
                style="document" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:binding name="RIB_SOAPSoap12"
        type="tns:RIB_SOAPSoap">
        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="Opération_1">
            <soap12:operation
                soapAction="http://tempuri.org/RIB_SOAP/Opération_1"
                style="document" />
            <wsdl:input>
                <soap12:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap12:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="RIB_SOAP">
        <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">BizTalk assembly
            "BTS, Version=1.0.0.0, Culture=neutral,
            PublicKeyToken=dab3109d17486051" published web service.
        </wsdl:documentation>
        <wsdl:port name="RIB_SOAPSoap"
            binding="tns:RIB_SOAPSoap">
            <soap:address
                location="http://localhost/BTS_Proxy/RIB_SOAP.asmx" />
        </wsdl:port>
        <wsdl:port name="RIB_SOAPSoap12"
            binding="tns:RIB_SOAPSoap12">
            <soap12:address
                location="http://localhost/BTS_Proxy/RIB_SOAP.asmx" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

客户端的 Spring conf:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/jaxws
            http://cxf.apache.org/schemas/jaxws.xsd
        http://cxf.apache.org/transports/http/configuration
            http://cxf.apache.org/schemas/configuration/http-conf.xsd
    "
>
    <!--.~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~-->
    <!--.~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~-->
    <http-conf:conduit name=".*">
        <http-conf:client ConnectionTimeout="30000" ReceiveTimeout="30000" />
    </http-conf:conduit>

    <jaxws:client 
        id="ribWebServiceClient"
        serviceClass="org.tempuri.RIBSOAPSoap"
        address="${ws.rib.url}"
    >
        <jaxws:features>
            <bean class="org.apache.cxf.feature.LoggingFeature" >
                <property name="prettyLogging" value="true" />
            </bean>
        </jaxws:features>
        <jaxws:properties>
            <entry key="exceptionMessageCauseEnabled" value="true" />
            <entry key="faultStackTraceEnabled" value="true" />
        </jaxws:properties>
    </jaxws:client>
    <!--.~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~-->
</beans>

服务器的 Spring conf:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/jaxws
            http://cxf.apache.org/schemas/jaxws.xsd
    "
>
    <!--.~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~-->
    <!--.~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~-->
    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

    <!--.~~~~~~~~..~~~~~~~~..~~~~~~~~-->
    <jaxws:endpoint
        id="ribWebServiceEndPoint"
        implementor="#ribWebService"
        address="${ws.rib.url}"
    >
        <jaxws:features>
            <bean class="org.apache.cxf.feature.LoggingFeature" >
                <property name="prettyLogging" value="true" />
            </bean>
        </jaxws:features>
        <jaxws:properties>
            <entry key="exceptionMessageCauseEnabled" value="true" />
            <entry key="faultStackTraceEnabled" value="true" />
        </jaxws:properties>
    </jaxws:endpoint>
    <!--.~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~..~~~~~~~~-->
</beans>

【问题讨论】:

    标签: soap cxf action non-ascii-characters


    【解决方案1】:

    根据 HTTP 规范,所有 HTTP 标头都应该是 ISO-8859-1。关于如何将非 ISO-8859-1 字符编码到标头 (https://www.rfc-editor.org/rfc/rfc2047) 中有一个单独的规范,但我不确定 JDK 中的 HTTPUrlConnection 对象是否支持。我也不确定其他soap客户端是否也支持它。

    我强烈建议确保 SOAPAction 值与 ISO-8859-1 兼容。

    【讨论】:

    • 谢谢@Daniel。我明白你的意思了。您是否认为这是 CXF 中的错误,因为它在客户端使用 UTF-8 对 SOAPAction 标头进行编码,而根据 HTTP 规范它应该使用 ISO-8859-1?
    【解决方案2】:

    请参考this discussion in CXF Users Mainling List。正如 Aki 所提到的,HTTP 规范要求 HTTP 标头仅使用 US-ASCII 字符(请参阅rfc2822)。正如 Daniel 和 Aki 所提到的,如果需要使用非 US-ASCII 字符,则应使用规范 rfc2047

    此问题的解决方案是避免使用非 US-ASCII 字符(当然包括重音字符)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-24
      • 2021-03-31
      • 1970-01-01
      相关资源
      最近更新 更多