Details
-
Bug
-
Status: Open
-
Major
-
Resolution: Unresolved
-
3.2.6
-
None
-
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: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:
@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.