Loading ...
Sorry, an error occurred while loading the content.

Newbie question: simple complex type

Expand Messages
  • andre_debruin
    Newbie question, sorry about that. I am trying to make a perl client connect to the example5 service as distributed with Apache axis. My naive implementation
    Message 1 of 3 , Mar 30, 2006
    • 0 Attachment
      Newbie question, sorry about that.

      I am trying to make a perl client connect to the "example5" service
      as distributed with Apache axis.

      My naive implementation looks like this:

      $wsdl = 'http://myhost:8080/axis/services/OrderProcessor?wsdl';
      $serv = SOAP::Lite -> service($wsdl);
      $result =
      $serv ->
      processOrder(
      SOAP::Data
      ->type('processOrder')
      ->name("arg1" =>
      SOAP::Data->value(
      SOAP::Data->name("customerName" => 'foo'),
      SOAP::Data->name("itemCodes" =>
      SOAP::Data->value(
      SOAP::Data->name("itemCodes"
      => ["a","b"])

      ->type("impl:ArrayOf_xsd_string")) ),
      SOAP::Data->name("quantities" =>
      SOAP::Data->value(
      SOAP::Data->name("quantities"
      => [1,2])

      ->type("impl:ArrayOf_xsd_int")) ),
      SOAP::Data->name("shippingAddress" => 'addr')))
      );

      This seems to be close enough to the relevant (?) part of the wsdl
      (and, for
      that matter the java client code):

      <complexType name="Order">
      <sequence>
      <element name="customerName" nillable="true" type="xsd:string"/>
      <element name="itemCodes" nillable="true"
      type="impl:ArrayOf_xsd_string"/>
      <element name="quantities" nillable="true"
      type="impl:ArrayOf_xsd_int"/>
      <element name="shippingAddress" nillable="true"
      type="xsd:string"/>
      </sequence>
      </complexType>

      The reason for this post is obviously that it, euh, well doesn't work.
      No errors, no warnings, no nothing, really, an empty result.

      So.. then I used the apache axis SOAPMonitor and compared the incoming
      XML from the Java client (included in the distribution of Apache Axis) and
      my feeble perl attempt.

      And sure enough, there are but a few differences.
      So..

      1) There seems to be a funny mismatch between aspects like name spaces
      (ns1 vs namespace1)
      is this a "don't care" or should I try to specify each and every
      detail exactly as what I see in the soap monitor for the java client ?

      2) Am I missing a very obvious thing ? (there seems to be at least a
      nesting
      problem related to the "Sequence" tag inside the "Order" item)

      3) Is there a smart way to derive the SOAP:Lite code from the WSDL or
      is this
      just a nitty-gritty hit-and-miss guru-only exercise ?

      3) Am I completely out of my mind to think that a simple complex structure
      function call can be handled in a simple way across languages with
      SOAP,
      am I really the only one who tries to get the fundametal Axis
      examples to work
      from Perl and am I just wasting everone's time with this posting ?
      (if so
      and in any case my sincere apologies).
    • Eric Bridger
      After a couple of months I still consider myself a newbie and I m not running Apache Axis, so take my advice with a grain of salt. If you take the wsdl
      Message 2 of 3 , Mar 31, 2006
      • 0 Attachment
        After a couple of months I still consider myself a newbie and I'm not
        running Apache Axis, so take my advice with a grain of salt.

        If you take the wsdl approach I'm not sure what S::L will do with your
        method arguments. Theoretically it should have created a method stub
        with the correct argument signature. Also note that you will not get a
        SOM object back unless you use $serv->want_som(1). Then you could check:
        $result->fault and $result->faultstring.

        But I would try using the proxy and call approach.
        $serv = SOAP::Lite->proxy("http::your server end point");
        $method = SOAP::Data->name("processOrder");

        $params = SOAP::Data-> .... (same as you have below)

        $result = $serv->call($method, $params);

        No need to call want->som(1). You'll get a SOM. $result->result will
        have at least the first result.

        You can use print $serv->transport->http_request->content(); to see
        exactly the xml being sent to the server and
        $serv->transport->http_response->content() to see the result.

        More notes in-line

        On Fri, 2006-03-31 at 01:24, andre_debruin wrote:
        > Newbie question, sorry about that.
        >
        > I am trying to make a perl client connect to the "example5" service
        > as distributed with Apache axis.
        >
        > My naive implementation looks like this:
        >
        > $wsdl = 'http://myhost:8080/axis/services/OrderProcessor?wsdl';
        > $serv = SOAP::Lite -> service($wsdl);
        > $result =
        > $serv ->
        > processOrder(
        > SOAP::Data
        > ->type('processOrder')
        > ->name("arg1" =>
        > SOAP::Data->value(
        > SOAP::Data->name("customerName" => 'foo'),
        > SOAP::Data->name("itemCodes" =>
        > SOAP::Data->value(
        > SOAP::Data->name("itemCodes"
        > => ["a","b"])
        >
        > ->type("impl:ArrayOf_xsd_string")) ),
        > SOAP::Data->name("quantities" =>
        > SOAP::Data->value(
        > SOAP::Data->name("quantities"
        > => [1,2])


        >
        > ->type("impl:ArrayOf_xsd_int")) ),
        > SOAP::Data->name("shippingAddress" => 'addr')))
        > );
        >
        > This seems to be close enough to the relevant (?) part of the wsdl
        > (and, for
        > that matter the java client code):
        >
        > <complexType name="Order">
        > <sequence>
        > <element name="customerName" nillable="true" type="xsd:string"/>
        > <element name="itemCodes" nillable="true"
        > type="impl:ArrayOf_xsd_string"/>
        > <element name="quantities" nillable="true"
        > type="impl:ArrayOf_xsd_int"/>
        > <element name="shippingAddress" nillable="true"
        > type="xsd:string"/>
        > </sequence>
        > </complexType>

        I don't think that your SOAP::Data structures above will produce
        something like "Order" complex type. I don't think you need to worry
        about using Axis' types, e.g. impl:ArrayOf_xsd_string. S::L should be
        able to pass it's array of strings.

        my $order = SOAP::Data->name("Order" =>
        \SOAP::Data->value( # not the reference here to get nested XML
        SOAP::Data->name("customerName" => 'foo'),
        SOAP::Data->name("itemCodes" => ['a','b']),
        SOAP::Data->name("quantitie" => [1,2]),
        SOAP::Data->name("shippingAddr" => 'addr),
        );

        You may still need to tweak this. E.g. you could try adding:
        SOAP::Data->name("itemCodes" => ['a','b'])->type('ArrayOf_xsd_string'),
        etc.
        >
        > The reason for this post is obviously that it, euh, well doesn't work.
        > No errors, no warnings, no nothing, really, an empty result.
        >
        > So.. then I used the apache axis SOAPMonitor and compared the incoming
        > XML from the Java client (included in the distribution of Apache Axis) and
        > my feeble perl attempt.
        >
        > And sure enough, there are but a few differences.
        > So..
        >
        > 1) There seems to be a funny mismatch between aspects like name spaces
        > (ns1 vs namespace1)
        > is this a "don't care" or should I try to specify each and every
        > detail exactly as what I see in the soap monitor for the java client ?

        This shouldn't matter.

        >
        > 2) Am I missing a very obvious thing ? (there seems to be at least a
        > nesting
        > problem related to the "Sequence" tag inside the "Order" item)
        >
        > 3) Is there a smart way to derive the SOAP:Lite code from the WSDL or
        > is this
        > just a nitty-gritty hit-and-miss guru-only exercise ?

        Often. SOAP::Lite wsdl support is limited. But I've used it successfully
        with simple arguments. Needs tweaking when the arguments are complex
        types.

        >
        > 3) Am I completely out of my mind to think that a simple complex structure
        > function call can be handled in a simple way across languages with
        > SOAP,
        > am I really the only one who tries to get the fundametal Axis
        > examples to work
        > from Perl and am I just wasting everone's time with this posting ?
        > (if so

        It can be done. Maybe check the Axis list.

        Eric

        > and in any case my sincere apologies).
        >
      • andre_debruin
        Thank you so much for the reply, that was most excellent, man I wish I could E-mail you a beer ! (hm, well there is an idea). I have copied the working code
        Message 3 of 3 , Mar 31, 2006
        • 0 Attachment
          Thank you so much for the reply, that was most excellent,
          man I wish I could E-mail you a beer !
          (hm, well there is an idea).


          I have copied the working code below for posterity.

          One question I should have asked before:

          I am to implement both the server and client side of
          a web service, the server will be Java, the clients will
          be both perl and Java.

          Now.. the application requires me to pass in and return
          a "deep structure" which can be represented as an array
          of structs (few hundred items in the array, some 5 fields
          in the struct).

          Would it make more sense to keep the method call simple and
          pass in the structure as a "blob", i.e. an attachment to
          be parsed by the server side or is that just "not done"
          in web sevices land ?
          (The question is thus related to best practices)






          ========
          Sample code for interfacing with "example5" of the Apache axis 1.3
          distribution, thanks much to Eric Bridger

          #!/usr/bin/env perl

          use SOAP::Lite +trace => qw(debug);

          $serv =
          SOAP::Lite->proxy("http://myhost:8080/axis/services/OrderProcessor");

          $method = SOAP::Data->name("processOrder");

          # from the wsdl:
          # <complexType name="Order">
          # <sequence>
          # <element name="customerName" nillable="true"
          # type="xsd:string"/>
          # <element name="itemCodes" nillable="true"
          # type="impl:ArrayOf_xsd_string"/>
          # <element name="quantities" nillable="true"
          # type="impl:ArrayOf_xsd_int"/>
          # <element name="shippingAddress" nillable="true"
          # type="xsd:string"/>
          # </sequence>
          # </complexType>

          my $order = SOAP::Data->name("arg1" =>
          \SOAP::Data->value( # note the reference here to get nested XML
          SOAP::Data->name("customerName" => 'foo' ),
          SOAP::Data->name("itemCodes" => ['a','b'] ),
          SOAP::Data->name("quantities" => [1,2] ),
          SOAP::Data->name("shippingAddress" => 'addr' ),
          ) );

          $result = $serv->call($method,
          SOAP::Data
          ->name("arg1" => $order ) );

          print $result;
        Your message has been successfully submitted and would be delivered to recipients shortly.