smeenz has asked for the wisdom of the Perl Monks concerning the following question:

Greetings 'o wise ones,

I'm rather confused by the perl syntax that I've come across in SOAP::Lite examples, as it doesn't seem to follow any syntax rules that I've come across before.

Take this for example:

#!perl -w use SOAP::Lite; print SOAP::Lite -> uri('http://www.soaplite.com/Demo') -> proxy('http://services.soaplite.com/hibye.cgi') -> hi() -> result;
I really don't understand what the -> operator is doing here.. normally I'ld use it as a dereference, eg $hashptr->{'key'}, but this one is just weird.

I'ld be forever grateful if someone could explain what's going on in the example above.


Secondly, consider this example:

#!perl -w use SOAP::Lite +autodispatch => uri => 'http://www.soaplite.com/My/Examples', proxy => 'http://services.soaplite.com/auth/examples.cgi', ; print getStateName(21);

Where did the sub getStateName get defined ? Does SOAP::Lite add to perl's namespace dynamically depending on the SOAP call you're making ?

Retitled by holli from 'SOAP::Lite syntax and talking to a Cisco Call Manager'.

Replies are listed 'Best First'.
Re: Perl syntax question
by adrianh (Chancellor) on Jun 03, 2005 at 07:51 UTC
    I'm rather confused by the perl syntax that I've come across in SOAP::Lite examples, as it doesn't seem to follow any syntax rules that I've come across before.

    Many of the SOAP::Lite methods return the object they're given, so the example you gave is equivalent to:

    my $o = SOAP::Lite-> uri('http://www.soaplite.com/Demo'); $o->proxy('http://services.soaplite.com/hibye.cgi'); $o->hi(); print $o->result;

    but since uri(), proxy() and hi() all return the object they are called on you can chain the method calls and save some typing. Some people like this, and some people don't. See chaining method calls for some discussion.

Re: Perl syntax question
by Zaxo (Archbishop) on Jun 03, 2005 at 07:53 UTC

    The configuration setter functions all return the object which calls them, so method calls may be stacked like that. That is a design choice that I don't particularly like, but it does permit a high code density with a sparse appearance. The -> operator is indeed dereference, as with any perl method call.

    After Compline,
    Zaxo

Re: Perl syntax question
by spurperl (Priest) on Jun 03, 2005 at 07:56 UTC
    Your intuition is right, it is indeed used for dereference. All the methods called return the object itself, on which the dereference is called. This is "method call chaining" which allows compact code.
      While $obj is a reference, there is no dereferencing going on.
        Sorry, I don't understand. The OP didn't refer to any $obj - what do you mean ?
Re: Perl syntax question
by jhourcle (Prior) on Jun 03, 2005 at 15:02 UTC

    I think adrianh explained what's going on with the method calls rather well, but if you don't feel comfortable with that syntax (I personally found it confusing when I started out), you can do:

    my $soap = SOAP::Lite->new( uri => 'http://www.soaplite.com/Demo', proxy => 'http://services.soaplite.com/hibye.cgi', ); my $soap_result = $soap->hi(); print $soap_result->result();

    (Yes, the result of a soap call isn't actually the result of the value that was returned by the method... it's actually a SOAP::SOM object)

    As for the second part of your question, take a look at what '+autodispatch' does in the SOAP::Lite documentation.

      Thanks everyone for the replies.

      I think I'll stick with the 'traditional' syntax... at least until I really have this chained thing worked out in my head.

      Re the second part - the bit where the perl namespace is populated... I'm still not clear on where SOAP::Lite finds what names/methods are available on the remote server.

      What I'm doing is trying to talk to a Cisco Call Manager (some of you may remember my previous attempt doing it with XML::Twig which turned out to be a dead end), and I don't know what the method names are. I have a working example of what should be 'on the wire', but I don't know what method I should be calling to get SOAP::Lite to create the correct request packets.

      For example, after creating a SOAP::Lite object and specifying the uri and proxy, I would expect to execute something like this:

      my $response = $soap->functionname(param,param,param)->result
      ... but I don't know what 'functioname' is.

      If it helps anyone answer my question, this is the working packet trace that I did by manually posting the request to the SOAP handler.

      REQUEST

      <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/env +elope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:x +sd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <axl:getPhone xmlns:axl="http://www.cisco.com/AXL/1.0" xsi:sch +emaLocation="http://www.cisco.com/AXL/1.0 http://myhost/schema/axlsoa +p.xsd" sequence="1234"> <phoneName>SEP000011112222</phoneName> </axl:getPhone> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

      Reply
      <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/en +velope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/enco +ding/"> <SOAP-ENV:Body> <axl:getPhoneResponse xmlns:axl="http://www.cisco.com/AXL/1.0" xmlns: +xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="h +ttp://www.cisco.com/AXL/1.0 http://MCSCM1/CCMApi/AXL/V1/axlsoap.xsd" +sequence="1234"> <return> <device> (loads of response data removed) </device> </return> </axl:getPhoneResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
        Actually, it will be clearer still if I show you what SOAP::Lite is actually generating:

        If I execute this:

        my $req = $soap->getPhone('phoneName' => 'SEP000000000000');

        then it sends this request to the call manager's soap handler:

        <?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:xsi="ht +tp://www.w3.org/1999/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP- +ENV="http://schemas.xmlsoap.org/soap/envelope/" xm lns:xsd="http://www.w3.org/1999/XMLSchema" SOAP-ENV:encodingStyle="htt +p://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <namesp1:getPhone xmlns:namesp1="http://www.cisco.com/AXL/1.0"> <c-gensym3 xsi:type="xsd:string">phoneName</c-gensym3> <c-gensym5 xsi:type="xsd:string">SEP000000000000</c-gensym5> </namesp1:getPhone> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

        And the call manager complains that it doesn't know what a c-gensym3 is (output from Data::Dumper)

        $VAR1 = { 'error' => { 'request' => 'getPhone', 'message' => ' Unexpected element. Found <c-gensym3>, expecting <phoneName> or <phone +Id>..', 'code' => '5005' } };
        I'm still not clear on where SOAP::Lite finds what names/methods are available on the remote server.

        Believe it or not -- it doesn't.

        It's up to the programmer to know what the methods are. There are structured ways of representing this information, for those people who use code generators, using WSDL (which I consider to be the bane of my existance]

        Some SOAP toolkits will return a wsdl if you attempt to GET the proxy URL with a QUERY string of 'wsdl'.... so in your example, you could try pointing a web browser at:

        http://services.soaplite.com/hibye.cgi?wsdl

        (it won't actually work, though, because SOAP::Lite doesn't support this by default, as it doesn't generate WSDL -- you're left to do that on your own)

        Now -- you're probably going to ask how autodispatch works then ... well, it just assumes that if it sees a command that it doesn't know about, then it should try the SOAP service.