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

Re: [soaplite] Newbie question: simple complex type

Expand Messages
  • 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 1 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 2 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.