Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-7951

Async binding not JAX-WS compliant

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 3.2.6
    • None
    • JAX-WS Runtime
    • None
    • Unknown

    Description

      According to JAX-WS 2.3 spec (section 2.3.4.3), the async binding differs from the sync binding in the handling of in-out and out parameters, namely:

      • Out: The part or wrapper child is mapped to a property of the response bean.
      • In/Out: The part or wrapper child is mapped to a method parameter (no holder class) and to a property of the response bean.

      In our project we are deploying our services on Weblogic, which includes Metro (JAX-WS RI) as JAX-WS implementation. And that requires the above signature for the async binding to work. However, CXF does not behave the same way: it expects the same input parameters in both bindings (sync and async); that means we still have the Holder class and no ResponseBean.

      As a result, we cannot have the same, portable JAX-WS client that can be used either with Metro or CXF, which is what we are striving for...

      Take for example, the following WSDL. Note that there are two In-Out SOAP headers, along with the body.

      WSDL
          <wsdl:message name="readFileRecord_MSGIN">
              <wsdl:part element="readFileRecord:ReadFileRecord_IN" name="request"/>
          </wsdl:message>
          <wsdl:message name="readFileRecord_MSGOUT">
              <wsdl:part element="readFileRecord:ReadFileRecord_OUT" name="response"/>
          </wsdl:message>
          <!-- PortType -->
          <portType name="srv-exp-Bank_PortType">
              <wsdl:operation name="readFileRecord">
                  <wsdl:input message="tns:readFileRecord_MSGIN"/>
                  <wsdl:output message="tns:readFileRecord_MSGOUT"/>
                  <wsdl:fault message="tns:FaultDetail_MSG" name="error"/>
              </wsdl:operation>
          </portType>
          <!-- Binding -->
          <binding name="srv-exp-Bank_Binding" type="tns:srv-exp-Bank_PortType">
              <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
              <wsdl:operation name="readFileRecord">
                  <soap:operation soapAction="readFileRecord"/>
                  <wsdl:input>
                      <soap:header message="tns:TECabecera_MSG"
                          part="te_header" use="literal"/>
                      <soap:header message="tns:TEMetadatos_MSG"
                          part="te_metadata" use="literal"/>
                      <soap:body use="literal"/>
                  </wsdl:input>
                  <wsdl:output>
                      <soap:header message="tns:TECabecera_MSG"
                          part="te_header" use="literal"/>
                      <soap:header message="tns:TEMetadatos_MSG"
                          part="te_metadata" use="literal"/>
                      <soap:body use="literal"/>
                  </wsdl:output>
                  <wsdl:fault name="error">
                      <soap:fault name="error" use="literal"/>
                  </wsdl:fault>
              </wsdl:operation>
          </binding>
      

      ...and, as described above, the mapping to Java differs for Metro and CXF:

      Java interface
       
      @WebMethod(action = "readFileRecord")
      @WebResult(name = "ReadFileRecord_OUT", targetNamespace = "http://telefonica.com/gstr/srv/Bank/msg/readFileRecord-v3", partName = "response")
      public ReadFileRecord_OUT readFileRecord(
      @WebParam(name = "ReadFileRecord_IN", targetNamespace = "http://telefonica.com/gstr/srv/Bank/msg/readFileRecord-v3", partName = "request")
      ReadFileRecord_IN request,
      @WebParam(name = "TE_Cabecera", targetNamespace = "http://telefonica.com/tran/comarq/cc/cabecera", header = true, mode = WebParam.Mode.INOUT, partName = "te_header")
      Holder<TE_Cabecera> teHeader,
      @WebParam(name = "TE_Metadatos", targetNamespace = "http://telefonica.com/tran/comarq/cc/metadatos-2.0", header = true, mode = WebParam.Mode.INOUT, partName = "te_metadata")
      Holder<TE_Metadatos> teMetadata)
      throws TE_Excepcion
      ;
      
      // CXF
      @WebMethod(operationName = "readFileRecord", action = "readFileRecord")
      public Response<ReadFileRecord_OUT> readFileRecordAsync(
      @WebParam(name = "ReadFileRecord_IN", targetNamespace = "http://telefonica.com/gstr/srv/Bank/msg/readFileRecord-v3", partName = "request")
      ReadFileRecord_IN request,
      @WebParam(name = "TE_Cabecera", targetNamespace = "http://telefonica.com/tran/comarq/cc/cabecera", header = true, mode = WebParam.Mode.INOUT, partName = "te_header")
      Holder<TE_Cabecera> teHeader,
      @WebParam(name = "TE_Metadatos", targetNamespace = "http://telefonica.com/tran/comarq/cc/metadatos-2.0", header = true, mode = WebParam.Mode.INOUT, partName = "te_metadata")
      Holder<TE_Metadatos> teMetadata);
      
      // METRO 
      @WebMethod(operationName = "readFileRecord", action = "readFileRecord")
      public Response<ReadFileRecordResponse> readFileRecordAsync(
      @WebParam(name = "ReadFileRecord_IN", targetNamespace = "http://telefonica.com/gstr/srv/Bank/msg/readFileRecord-v3", partName = "request")
      ReadFileRecord_IN request,
      @WebParam(name = "TE_Cabecera", targetNamespace = "http://telefonica.com/tran/comarq/cc/cabecera", header = true, mode = WebParam.Mode.INOUT, partName = "te_header")
      TE_Cabecera teHeader,
      @WebParam(name = "TE_Metadatos", targetNamespace = "http://telefonica.com/tran/comarq/cc/metadatos-2.0", header = true, mode = WebParam.Mode.INOUT, partName = "te_metadata")
      TE_Metadatos teMetadata);
      

      In addition, CXF does not behave as required by the JAX-WS spec when an exception is thrown in "async" mode. The cause of ExecutionException is the inner exception, typically a checked one (such as ConnectException), instead of the required unchecked WebServiceException. This is mandated in section 4.3.3 of the spec:

      ♦ Conformance (Reporting asynchronous errors): If the operation invocation fails, an implementation MUST throw a java.util.concurrent.ExecutionException from the Response.get method. The cause of an ExecutionException is the original exception raised. In the case of a Response instance this can only be a WebServiceException or one of its subclasses

      Thank you in advance.

       

      Attachments

        Activity

          People

            Unassigned Unassigned
            Aritz Aritz Bastida
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: