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

Soap Header contents getting mixed up

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Cannot Reproduce
    • Affects Version/s: 3.0.4, 3.2.4
    • Fix Version/s: None
    • Component/s: JAX-WS Runtime
    • Labels:
      None
    • Environment:

      Win7

      java 8 64bit

       

    • Estimated Complexity:
      Unknown

      Description

      I'm trying to consume following web service which defines 2 Soap Headers

      fsbHeader (inout, fsbheadertype) and sentOnBehalfOf ( out, String):

      https://fsb.services.int.belgium.be/PersonServices/GetExtendedPersonService/2.0/CPS_GetExtendedPersonService?WSDL

      The generated Interface (-exsh = true) looks as follows:

          @WebMethod
          @WebResult(name = "getExtendedPersonResponse", targetNamespace = "http://fsb.belgium.be/getExtendedPersonService/messages/v2_00", partName = "body")
          public GetExtendedPersonResponseType getExtendedPerson(
              @WebParam(partName = "body", name = "getExtendedPersonRequest", targetNamespace = "http://fsb.belgium.be/getExtendedPersonService/messages/v2_00")
              GetExtendedPersonRequestType body,
              @WebParam(partName = "header", name = "fsbHeader", targetNamespace = "http://fsb.belgium.be/header", header = true)
              FsbHeaderType header,
              @WebParam(partName = "header", name = "sentOnBehalfOf", targetNamespace = "http://fsb.belgium.be/getExtendedPersonService/v2_00", header = true)
              java.lang.String header1,
              @WebParam(partName = "header", mode = WebParam.Mode.OUT, name = "fsbHeader", targetNamespace = "http://fsb.belgium.be/header", header = true)
              javax.xml.ws.Holder<FsbHeaderType> header2
          );

      I call the server in following way (removing param contents as they are irrelevant)

             FsbHeaderType requestHeader = new FsbHeaderType().withMessageId(messageId);
              String onBehalfOf = requester.getOnBehalfOfToken().orNull();
              Holder<FsbHeaderType> headerHolder = new Holder<>(requestHeader);
              return service.getExtendedPerson(request, requestHeader,"test", headerHolder);

      It appears that during marshalling of the SOAP payload, the value of "sentOnBehalfOf" is being put in the part for "fsbHeader" and vice versa:

      <snip, business code...>
          at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
          at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
          at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
          at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
          at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
          at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
          at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
      Caused by: java.lang.ClassCastException: (org.company.package).getextendedpersonservice.v2.FsbHeaderType cannot be cast to java.lang.String
          at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$StringImplImpl.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:1034)
          at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.writeLeafElement(TransducedAccessor.java:256)
          at com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:130)
          at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:161)
          at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:131)
          at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:333)
          at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:340)
          at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:76)
          at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:494)
          at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323)
          at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:178)
          at org.apache.cxf.jaxb.JAXBEncoderDecoder.writeObject(JAXBEncoderDecoder.java:614)
          at org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:243)
          at org.apache.cxf.jaxb.io.DataWriterImpl.write(DataWriterImpl.java:239)
          at org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.handleHeaderPart(SoapOutInterceptor.java:259)
          at org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.writeSoapEnvelopeStart(SoapOutInterceptor.java:182)
          at org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.handleMessage(SoapOutInterceptor.java:88)
          at org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.handleMessage(SoapOutInterceptor.java:68)
          at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
          at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:533)
          at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:442)
          at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:343)
          at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:296)
          at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
          at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:139)
          ... 32 common frames omitted

      Debugging SoapOutInterceptor:259 (dataWriter.write(arg, header.getPart(), xtw); – at end of loop), I see this line gets hit twice:

      1)
      part = {MessagePartInfo@3936} "[MessagePartInfo name={http://fsb.belgium.be/getExtendedPersonService/v2_00}header, ConcreteName={http://fsb.belgium.be/header}fsbHeader"
      arg = "test"
      (weirdly enough this does not fail during marshalling)
      2)
      part = {MessagePartInfo@3998} "[MessagePartInfo name={http://fsb.belgium.be/getExtendedPersonService/v2_00}header, ConcreteName={http://fsb.belgium.be/getExtendedPersonService/v2_00}sentOnBehalfOf"
      arg = {FsbHeaderType@3999} 

      ==> when the 2nd part gets marshalled it results in above stacktrace

      I no longer have the debug info, but I saw that the root cause was inside org.apache.cxf.service.model.MessagePartInfo#getIndex, where the incorrect index was reported to obtain the header value. I tried to debug the initialization of the service to figure out how those indexes are set, but I got a bit lost there

      Originally I used cxf 3.0.4, which resulted in an xml parsing error by the Soap webservice. In our logging I saw that the value of the sentOnBehalfOf was put in an fsbHeader element:

      <ns22:fsbHeader xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns23="http://fsb.belgium.be/getExtendedPersonService/v2_00" xmlns:ns22="http://fsb.belgium.be/header" xmlns:ns21="http://fsb.belgium.be/data/entity/address/diplomaticplace/v1_00" xmlns:ns20="http://fsb.belgium.be/data/common/label/v1_00" xmlns:ns19="http://fsb.belgium.be/data/entity/address/v1_00" xmlns:ns18="http://fsb.belgium.be/data/business/address/v1_00" xmlns:ns17="http://fsb.belgium.be/data/entity/person/contactinfo/v1_00" xmlns:ns16="http://fsb.belgium.be/data/entity/person/sharedhosting/v1_00" xmlns:ns15="http://fsb.belgium.be/data/entity/person/nationality/v1_00" xmlns:ns14="http://fsb.belgium.be/data/entity/person/profession/v1_00" xmlns:ns13="http://fsb.belgium.be/data/entity/person/legaldisability/v1_00" xmlns:ns12="http://fsb.belgium.be/data/entity/person/legalcohabitation/v1_00" xmlns:ns11="http://fsb.belgium.be/data/entity/person/civilstate/v2_00" xmlns:ns10="http://fsb.belgium.be/data/entity/person/decease/v1_00" xmlns:ns9="http://fsb.belgium.be/data/common/date/v2_00" xmlns:ns8="http://fsb.belgium.be/data/entity/person/birth/v1_00" xmlns:ns7="http://fsb.belgium.be/data/entity/person/name/v1_00" xmlns:ns6="http://fsb.belgium.be/data/entity/person/v2_00" xmlns:ns5="http://fsb.belgium.be/data/common/error/v1_00" xmlns:ns4="http://fsb.belgium.be/data/common/code/v1_00" xmlns:ns3="http://fsb.belgium.be/data/business/person/v2_00" xmlns:ns2="http://fsb.belgium.be/getExtendedPersonService/messages/v2_00" xmlns="http://fsb.belgium.be/data/business/context/v1_00" xsi:type="xs:string">test</ns22:fsbHeader>

      there was no "sentOnBehalfOf" tag present containing the fsbHeader content...

      I aligned all cxf dependencies (library and cxf-codegen plugin) to latest version 3.2.4, which resulted in above stack trace (due to added xml validation I assume).

      Commenting the "sentOnBehalfOf" element in the wsdl getExtendedPerson>input element results in fsbHeader becoming an INOUT parameter:

          @WebMethod
          @WebResult(name = "getExtendedPersonResponse", targetNamespace = "http://fsb.belgium.be/getExtendedPersonService/messages/v2_00", partName = "body")
          public GetExtendedPersonResponseType getExtendedPerson(
              @WebParam(partName = "body", name = "getExtendedPersonRequest", targetNamespace = "http://fsb.belgium.be/getExtendedPersonService/messages/v2_00")
              GetExtendedPersonRequestType body,
              @WebParam(partName = "header", mode = WebParam.Mode.INOUT, name = "fsbHeader", targetNamespace = "http://fsb.belgium.be/header", header = true)
              javax.xml.ws.Holder<FsbHeaderType> header
          );

      ==> this results in a working call

      Leaving the wsdl as-is and editing the generated code to below also results in a working call, but the "sentOnBehalfOf" header is not filled in:

          @WebMethod
          @WebResult(name = "getExtendedPersonResponse", targetNamespace = "http://fsb.belgium.be/getExtendedPersonService/messages/v2_00", partName = "body")
          public GetExtendedPersonResponseType getExtendedPerson(
              @WebParam(partName = "body", name = "getExtendedPersonRequest", targetNamespace = "http://fsb.belgium.be/getExtendedPersonService/messages/v2_00")
              GetExtendedPersonRequestType body,
              @WebParam(partName = "header", name = "sentOnBehalfOf", targetNamespace = "http://fsb.belgium.be/getExtendedPersonService/v2_00", header = true)
              java.lang.String header1,
              @WebParam(partName = "header", mode = WebParam.Mode.INOUT, name = "fsbHeader", targetNamespace = "http://fsb.belgium.be/header", header = true)
              javax.xml.ws.Holder<FsbHeaderType> header2
          );

      I can provide more info if needed (cxf-codegen plugin config, instantiation of the service, but that's all pretty standard)

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              glever Glen Vermeylen
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: