Uploaded image for project: 'Axis-C++'
  1. Axis-C++
  2. AXISCPP-1017

WSDL2Ws tool has serious problem when processing the schema: unbounded choice inside sequence

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Critical
    • Resolution: Unresolved
    • 1.6 Beta
    • None
    • WSDL processing - Doc
    • None
    • OS: Linux fedora 3.0
      Axiscpp version: Server-side Axis C++ 1.6Beta
      XML Parser Lib: xersesc 2.6
      WSDL2ws tool by using axis java 1.4
      Http Server Version: Apache 2.0.53

    Description

      When I was developing some web service based on axiscpp1.6b/apache2.0, I found that axiscpp1.6b's WSDL2Ws tool has serious problem to generate code for one kind of complex composite schema type: unbounded choice inside sequence.

      I'd like to give a piece of sample schema to replay this problem like the below:
      [FooMan.wsdl/FooMan.xsd]:

      ...
      <xsd:element name="AddFoo" type="usr:AddFoo" />
      <xsd:complexType name="AddFoo">
      <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="unbounded"
      name="Foo" type="usr:FooAddRequest" />
      </xs:sequence>
      </xsd:complexType>

      <xsd:element name="AddFooResponse"
      type="usr:AddFooResponse" />
      <xsd:complexType name="AddFooResponse">
      <xs:sequence>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="Foo" type="usr:Foo" />
      <xs:element name="Fault" type="mgt:Fault" />
      </xs:choice>
      </xs:sequence>
      </xsd:complexType>
      ...

      The generated code(interface): FooMan.hpp looks like the below:

      ...

      void AddFoo(FooAddRequest_Array * Value0, AXIS_OUT_PARAM Foo* * OutValue0, AXIS_OUT_PARAM Fault* * OutValue1);
      ...

      Though the generated code can be compiled without problem, and even it can be executed and communicate with some corresponding soap client(only simple & special case) without problem, but it's not correct according to the syntax definition from it's schema definition.

      For example, the generated code can only support the below case(simple & special case):
      [Request-1]:
      ...
      <AddFoo xmlns="http://www.foo.bar.com/foo">
      <Foo>
      <FooID>Foo1</FooID>
      <Password>FooPaa1</Password>
      </Foo>
      <Foo>
      <FooID>Foo2</FooID>
      <Password>FooPaa2</Password>
      </Foo>
      </AddFoo>
      ...

      [Response-1]:
      ...
      <AddFooResponse xmlns="http://www.foo.bar.com/foo">
      <Foo>
      <FooID>Foo1</FooID>
      <Index>FooDee1</Index>
      </Foo>
      <Fault>
      <FooID>Foo2</FooID>
      <Reason>WrongPassword</Reason>
      </Fault>
      </AddFooResponse>
      ...

      But the generated code can not support more general & complex case like the below:
      [Request-2]:
      ...
      <AddFoo xmlns="http://www.foo.bar.com/foo">
      <Foo>
      <FooID>Foo1</FooID>
      <Password>FooPaa1</Password>
      </Foo>
      <Foo>
      <FooID>Foo2</FooID>
      <Password>FooPaa2</Password>
      </Foo>
      <Foo>
      <FooID>Foo3</FooID>
      <Password>FooPaa3</Password>
      </Foo>
      <Foo>
      <FooID>Foo4</FooID>
      <Password>FooPaa4</Password>
      </Foo>
      </AddFoo>
      ...

      [Response-2]:
      ...
      <AddFooResponse xmlns="http://www.foo.bar.com/foo">
      <Foo>
      <FooID>Foo1</FooID>
      <Index>FooDee1</Index>
      </Foo>
      <Foo>
      <FooID>Foo2</FooID>
      <Index>FooDee2</Index>
      </Foo>
      <Fault>
      <FooID>Foo3</FooID>
      <Reason>WrongPassword</Reason>
      </Fault>
      <Fault>
      <FooID>Foo4</FooID>
      <Reason>UnknowError</Reason>
      </Fault>
      </AddFooResponse>
      ...

      The key-point for this problem is that, in C++ implementation, the "AddFooResponse" should be regarded as two complex arrays, not two simple objects.

      In order to let my web service work strictly like what the wsdl and schema defined, I have to correct the generated FooMan.hpp(and of course the corresponding FooMan.cpp) like the below:
      [FooMan.hpp]:
      ...
      //<-+ mxiong 2007/1/24 Modify "AddFoo" to fix schema problem
      // void AddFoo(FooAddRequest_Array * Value0, AXIS_OUT_PARAM Foo* * OutValue0, AXIS_OUT_PARAM Fault* * OutValue1);
      void AddFoo(FooAddRequest_Array * Value0, AXIS_OUT_PARAM Foo_Array & OutValue0, AXIS_OUT_PARAM Fault_Array & OutValue1);
      //>-+ mxiong 2007/1/24 Modify "AddFoo" to fix schema problem
      ...

      To let the above modification to work correctly, the FooManWrapper.cpp also need to be modified like the below:

      [FooManWrapper.cpp]:
      ...
      int FooManWrapper::AddFoo(void* pMsg)
      {
      IMessageData* mc = (IMessageData*)pMsg;
      int nStatus;
      IWrapperSoapSerializer* pIWSSZ = NULL;
      mc->getSoapSerializer(&pIWSSZ);
      if (!pIWSSZ)

      { return AXIS_FAIL; }
      IWrapperSoapDeSerializer* pIWSDZ = NULL;
      mc->getSoapDeSerializer(&pIWSDZ);
      if (!pIWSDZ)
      { return AXIS_FAIL; }

      /* check whether we have got correct message */
      if (AXIS_SUCCESS != pIWSDZ->checkMessageBody("AddFoo", "http://www.fujixerox.co.jp/2003/12/ssm/management/user"))

      { return AXIS_FAIL; }
      pIWSSZ->createSoapMethod("AddFooResponse", "http://www.fujixerox.co.jp/2003/12/ssm/management/user");

      FooAddRequest_Array * v0 = new FooAddRequest_Array();
      pIWSDZ->getCmplxArray(v0, (void*)Axis_DeSerialize_FooAddRequest,
      (void*)Axis_Create_FooAddRequest, (void*)Axis_Delete_FooAddRequest,
      (void*)Axis_GetSize_FooAddRequest, "Foo", Axis_URI_FooAddRequest);

      if (AXIS_SUCCESS != (nStatus = pIWSDZ->getStatus()))
      { return nStatus; }

      //<-+ mxiong 2007/1/24 Modify "AddFoo" to fix schema problem
      // Foo* out0;
      // Fault* out1;
      // try
      // { // pWs->AddFoo(v0,&out0,&out1); // pIWSSZ->addOutputCmplxParam(out0, (void*)Axis_Serialize_Foo, (void*)Axis_Delete_Foo, "Foo", Axis_URI_Foo); // pIWSSZ->addOutputCmplxParam(out1, (void*)Axis_Serialize_Fault, (void*)Axis_Delete_Fault, "Fault", Axis_URI_Fault); // return AXIS_SUCCESS; // }
      // catch(...)
      // { // return AXIS_FAIL; // }

      Foo_Array out0;
      Fault_Array out1;
      try
      { pWs->AddFoo(v0,out0,out1); pIWSSZ->addOutputCmplxArrayParam(&out0,(void*) Axis_Serialize_Foo, (void*) Axis_Delete_Foo, (void*) Axis_GetSize_Foo, "Foo", Axis_URI_Foo); pIWSSZ->addOutputCmplxArrayParam(&out1,(void*) Axis_Serialize_Fault, (void*) Axis_Delete_Fault, (void*) Axis_GetSize_Fault, "Fault", Axis_URI_Fault); return AXIS_SUCCESS; }
      catch(...)
      { return AXIS_FAIL; }

      //>-+ mxiong 2007/1/24 Modify "AddFoo" to fix schema problem
      }
      ...

      P.S. Because the necessary class Fault_Array.hpp/.cpp was not generated by WSDL2Ws tool, I also have to write the necessary class manually.

      After modifying FooMan.hpp/.cpp and FooManWrapper.cpp, adding necessary class, my web service can work strictly like the wsdl & schema defined.

      Though I have modified the generated code manually to let my web service to strictly follow the wsdl and schema definition, the more general solution should be to modify the WSDL2Ws tool to processing the related wsdl and schema definition correctly.

      Could some one to take an eye on this problem and take necessary modification to WSDL2Ws tool?

      Attachments

        Activity

          People

            Unassigned Unassigned
            mxiong Michael Xiong
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated: