http://www.perlmonks.org?node_id=650397

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

Hello monks!

I'm hoping someone can point me in the right direction! I've never used SOAP... but a lot of folk seem to offer SOAP-based API's and I'd like to play with some. However, the more I look though nodes here the more confused I get. So I'm making an appeal for information.

Frankly, it all looks a little weird and scary and a little overwhelming to me, but I'd like to learn. I've just found that getting a more complete picture of things has me leaping from one module to the next and what I need to know grows exponentially before I even understand how the basic stuff works. Help? If I'm gonna do something I'd like to do it right... I feel like it's more of an information overload than a shortage of information.

Apologies if this is too general.

Many thanks!

update: ack (a great grep replacement as well as a good expression of annoyance). fixed a little grammar... it's a good think i don't write books

update le second: whoops. SOAP::WDSL _is_ still being maintained. I'm gonna hafta find that node again.

update troisieme: I am a sad Panda. :-( SOAP::WSDL is not a fan of the WSDL I'm trying to play with. Are there alternatives? Can I make my own "fake" spec of some kind? XML templates instead?

--
meraxes

Replies are listed 'Best First'.
Re: Starting on SOAP
by trwww (Priest) on Nov 13, 2007 at 03:39 UTC

    Hello,

    What I did was read the books Programming Web Services with SOAP and Programming Web Services with Perl. Cover to cover those books and you'll be all set.

    Here is a bit of code to get you started. You'll need to install the RPC::XML and SOAP::Lite distros.

    It is not SOAP, it is XMLRPC. But if you read the books above, you'll see that XMLRPC is just a subset of SOAP. Be sure to run the client with LWP::Debug turned on so you see the HTTP request/response cycle.

    On machine A:

    $ cat server.pl use warnings; use strict; use RPC::XML::Server; my $server = RPC::XML::Server->new(port => 9000); $server->add_method({ name => 'test.hello', signature => [ q|string string| ], help => 'this method greets an argument... cool, huh?', code => sub { my($server, $str) = @_; return( "Hello, $str!" ); } }); print "listening on port 9000\n"; $server->server_loop; [trwww@waveright rpc]$ perl server.pl listening on port 9000

    On Machine X:

    $ XMLRPCsh.pl http://localhost:9000/ Usage: method[(parameters)] > system.listMethods('test') --- XMLRPC RESULT --- [ 'test.hello' ] > system.methodHelp('test.hello') --- XMLRPC RESULT --- 'this method greets an argument... cool, huh?' > system.methodSignature('test.hello') --- XMLRPC RESULT --- [ [ 'string', 'string' ] ] > test.hello('perlmonks') --- XMLRPC RESULT --- 'Hello, perlmonks!'

    regards,

    trwww

Re: Starting on SOAP
by ruoso (Curate) on Nov 13, 2007 at 11:13 UTC

    One thing to understand is that SOAP is a very flexible protocol that stablishes a set of possible scenarios, being RPC or not.

    The common scenarios are:

    • RPC/Encoded
    • RPC/Literal
    • Document/Literal Wrapped (used by MS .Net)
    • Document/Literal

    RPC and Document style services.

    So what defines RPC? RPC is when you have a service endpoint that provides several operations, or "procedures" to be called with a set of parameters. This means that the first and only child of the "body" element of the SOAP message will be the name of the operation to be invoked.

    This way, the "Document/Literal Wrapped" pattern used by MS .Net *is* a RPC style service, even if it uses the "document/literal" SOAP style, it in fact is a mess confusion, and in the end is completely similar to the RPC style.

    The other aspect of the RPC style is how the parameters are encoded. The most standard way is using the "SOAP Encoding", which then results in the "RPC/Encoded" pattern. This encoding standard is fairly simple and usefull for most cases.

    The "literal" encoding is supposed to handle an arbitrary XML document, that would be delivered as-is to the service. What is wrong in the "wrapped" implementation is that, in fact the encoding is not "literal", but it is an encoding defined by the .Net framework. It is just not documented, so they call it "literal", where it probably needed to be called ".Net encoding" which would make a more reasonable name "RPC/.Net".

    The idea behind the literal is the possibility of having arbitrary XML documents as parameters. But what is most important to realise is that SOAP allows you to define a custom encoding, for instance, let's suppose your RPC method receives an RDF information. You can just declare it as "RPC/RDF", and your framework would be able to automatically serialize and desserialize between some RDF high-level object and the RDF document.

    The Document style services, on the other hand are a kind of service which do not implement the semantics of a remote procedure call, this means that the message don't contain an "operation name". It simply will contain an arbitrary XML document inside the body, you may even have several elements below body.

    This is important to implement services that would, for instance, register your Europass CV (which have a known XML schema), in a system. You don't need any RPC on that, you just need a SOAP service endpoint where the EuroPass CV may be published and that's all.

    The encoding is also meaningfull in the Document style. While Document/Encoded is a standard that simply doesn't seem to make sense (as SOAP encoding is RPC related) you may implement several variations beyound the Document/Literal pattern, which is simply a way to implement a non-declarative arbitrary encoding. The more sane would be, in the above case, to declare it as "Document/EuroPass", as the framework implementations would then be able to automatically provide a higher-level representation of the europass cv instead of a plain XML document to the service

    Toolkits

    Here, the more important question is: are you going to serve or consume SOAP?

    To consume SOAP you can use SOAP::Lite, SOAP::WSDL and XML::Compile::SOAP. SOAP::Lite is very efficient with "RPC/Encoded" services, althought SOAP::Lite code is very weird, the module just work. On the other hand, if you need to deal with Document style services and encoding different from "SOAP Encoding" SOAP::Lite will start to be a problem (I will refer "Document/Literal Wrapped" as "RPC/.Net" from now on).

    SOAP::WSDL and XML::Compile::SOAP seems to be more smart to deal with different encodings. I didn't stressed any of the both, but they seem to solve your problems in most cases.

    On the other hand, if you're going to serve SOAP, then you have only SOAP::Lite and Gantry at the moment, I'm working on Catalyst::Controller::SOAP to provide that in Catalyst as well, and I should release the first early version this week. The good part is that this module I'm working on will be oriented to the SOAP concepts as I presented earlier. It will be easier to implement different types of encodings.

    But again, if you're going to serve anything different from "RPC/Encoded" SOAP::Lite will not be very helpfull.

    Important Disclaimer

    Even when there are a lot of articles saying that RPC/Encoded is bad, these articles are promoting the "just plain broken" "Document/Literal Wrapped" pattern. So, be a good guy and declare your style and encoding accordingly. If you're going to do RPC, use RPC style, if you're going to encode parameters to the procedures, declare your encoding. The easy path is: "stick to RPC/Encoded".

    daniel

      Thank you so much! This actually clarifies a few things for me. The SOAP is slippery indeed! I'd best not drop it.

      --
      meraxes
Re: Starting on SOAP
by bart (Canon) on Nov 13, 2007 at 10:53 UTC
    then that SOAP::WSDL is no longer maintained
    That module seems to have gotten an update to the official release only 5 weeks ago, and to the developer release about a week ago.

    I think the reports of its death are somewhat exaggerated. :)

      Whoops! I noticed that last night actually. I'll have to find that node again that said it wasn't maintained. It certainly seems a bit easier to use if you have a WSDL document.

      --
      meraxes
      hmm... this seems pretty nice, will give it a try.
Re: Starting on SOAP
by rootcho (Pilgrim) on Nov 14, 2007 at 01:16 UTC
    I had to use SOAP.. so I started with SOAP::Lite.. a good module but very complex, especially if you have to read the internals.... oo maaan :), they are complex.
    In the beginning I tried creating objects (bless {...}) and pass them to SOAP to create the xml-message, but this didn't worked well. Most of the times it created SOAP-xml that wasn't what the other side expected i.e. it was useless.
    So my final solution was to use SOAP::Lite like wrapper for the communication and build the XML myself via Template-toolkit. I find the pseudo XPath expressions you can use on the result very useful.

    The bad thing about this approach is that you have to read .wsdl and .xsd specs :( arggh..
    One more thing to know about .wsdl. What SOAP::Lite does is it parses the .wsdl file and creates a module on the fly with all the methods, but that is. It does not go further to parse .xsd schemas, so you are on your own from there.
    Another thing to be aware is if you have to preserve sessions and also use WSDL ->service() method i.e. you want to login with the first request and reuse this on subsequent one. To solve this I modified SOAP::Lite itself. At the end of SOAP::Lite::HTTP::new() add the following code :
    use HTTP::Cookies; my $c = HTTP::Cookies->new(ignore_discard => 1); $self->cookie_jar( $c);
    In normal SOAP::Lite usage afaik you can override this easier, but if want to use the wsdl functionality, then use this

    hth

    PS> If you decide to use TT like me to build the SOAP message I will recommend you to read the tutorials on : http://www.w3schools.com for XML Schema.
    One thing to know 'S' in SOAP does not mean Simple, really .
      In the beginning I tried creating objects (bless {...}) and pass them to SOAP to create the xml-message, but this didn't worked well. Most of the times it created SOAP-xml that wasn't what the other side expected i.e. it was useless.
      So my final solution was to use SOAP::Lite like wrapper for the communication and build the XML myself via Template-toolkit. I find the pseudo XPath expressions you can use on the result very useful.
      SOAP::Lite has absorbed some but not all functionality from SOAP::WSDL.

      If you want to send objects (complexTypes) to a SOAP web-service use SOAP::WSDL. It works. Really.

      Hand-building XML for SOAP (even using templates) is just a waste of time. That's what WSDL is for.

      The only conceivably non-useless scenario I can think of for partially building SOAP messages with templates is the case where the web-service expects Document/Literal (or .NET) encoding, but at the same time allows for recursively defined complexTypes to be passed. That's quite a lot more complicated than what most developers have to deal with.

      Everyone should know that "SOAP Interoperability" is a cosmic-scale joke perpetrated on the industry by hermit-like evil geniuses.

      That being said, it's still much better to use SOAP::WSDL and to override its default behaviour where necessary. If you find you're using set of overrides a lot, create a sub-class of SOAP::WSDL. Simple.

      The bad thing about this approach is that you have to read .wsdl and .xsd specs :( arggh..
      One more thing to know about .wsdl. What SOAP::Lite does is it parses the .wsdl file and creates a module on the fly with all the methods, but that is. It does not go further to parse .xsd schemas, so you are on your own from there.
      If you've gone down this path because SOAP::Lite / SOAP::WSDL don't yet implement the WSDL 'import' construct... that's a little drastic :-)

      You have a few options:

      • Alter the web-service (if you wrote it) to "inline" the XSD schemas.
      • Save the WSDL file and modify it by hand to include the imported XSD schemas inline.
      • Get some off-the-shelf XSL to transform the WSDL such that the XSD schemas are inlined. You could even create a WSDL proxy service to automate the process.
      In summary, stop doing things the hard way. ;)

      -David

        when I started the project, SOAP::WSDL wasn't so advanced ;(, but I will definitely will give it another try.
        Seems much promising now.

        I don't have access to the SOAP server.(it is Java based server and they have libs only for Java and .NET).

        Everyone should know that "SOAP Interoperability" is a cosmic-scale joke perpetrated on the industry by hermit-like evil geniuses

        liked that ;)

        Didn't knew that import was not supported, thanx for telling me that..
      As of now using SOAP::Lite it is difficult to construct complex SOAP data structures.
      My statement holds good when the wsdl schema on the server has lots and lots of complex SOAP datatypes.
      In which case using SOAP::Lite will be laborious.

      PHP works smoother, when the wsdl schema has complex datatypes
      (there is something called as wsdl2php which converts the wsdl schema to equivalent php classes) using which one can avoid manually constructing the SOAP equivalent complex php data structures

      SOAP::Lite can be used if the wsdl schema is simple or not so complex, such a google web services.


      In a global sense, SOAP::Lite is better and fully defined, Also usability wise yes, if the wsdl is simple.
        As of now using SOAP::Lite is difficult to construct complex SOAP data structures.
        My statement holds good when there is wsdl schema already defined and if this wsdl schema has lots and lots of complex types, the using SOAP::Lite will be laborious.
        Obviously you've trouble with reading. I'll write smaller sentences: Update: It seems I misunderstood whom you were replying to:

        Use SOAP::WSDL.

        It handles the construction of SOAP::Data heirarchies for you when given (blessed or not) hash-based data-structures.

        -David