|
NAMEXML::Compile::SOAP - base-class for SOAP implementationsINHERITANCEXML::Compile::SOAP is extended by XML::Compile::SOAP11 XML::Compile::SOAP12 SYNOPSIS** SOAP1.[12] and WSDL1.1 over HTTP # !!! The next steps are only required when you do not have # !!! a WSDL. See XML::Compile::WSDL11 if you have a WSDL. # !!! Without WSDL file, you need to do a lot manually use XML::Compile::SOAP11::Client; my $client = XML::Compile::SOAP11::Client->new; $client->schemas->importDefinitions(...); use XML::Compile::Util qw/pack_type/; my $h1el = pack_type $myns, $some_element; my $b1el = "{$myns}$other_element"; # same, less clean my $encode_query = $client->compileMessage ( 'SENDER' , style => 'document' # default , header => [ h1 => $h1el ] , body => [ b1 => $b1el ] , destination => [ h1 => 'NEXT' ] , mustUnderstand => 'h1' ); my $decode_response = $client->compileMessage ( 'RECEIVER' , header => [ h2 => $h2el ] , body => [ b2 => $b2el ] , faults => [ ... ] ); my $transport = XML::Compile::Transport::SOAPHTTP ->new(address => $server); my $http = $transport->compileClient(action => ...); my @query = (h1 => ..., b1 => ...); my $request = $encode_query->(@query); my ($response, $trace) = $http->($request); my $answer = $decode_response->($response); use Data::Dumper; warn Dumper $answer; # discover a HASH with h2 and b2! if($answer->{Fault}) ... # when an error was reported # Simplify your life: combine above into one call # Also in this case: if you have a WSDL, this is created # for you. $wsdl->compileClient('MyFirstCall'); my $call = $client->compileClient ( kind => 'request-response' # default , name => 'MyFirstCall' , encode => $encode_query , decode => $decode_response , transport => $http ); # !!! Usage, with or without WSDL file the same my $result = $call->(@query) # SCALAR only the result print $result->{h2}->{...}; print $result->{b2}->{...}; my ($result, $trace) = $call->(...); # LIST will show trace # $trace is an XML::Compile::SOAP::Trace object DESCRIPTIONThis module handles the SOAP protocol. The first implementation is SOAP1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/), which is still most often used. The SOAP1.2 definition (http://www.w3.org/TR/soap12/) is provided via the separate distribution XML::Compile::SOAP12.Be aware that there are three kinds of SOAP:
Don't forget to have a look at the examples in the examples/ directory included in the distribution. Please support my development work by submitting bug-reports, patches and (if available) a donation. METHODSConstructors
Accessors
Single message
HelpersTranscoding
DETAILSSOAP introductionAlthough the specifications of SOAP1.1 and WSDL1.1 are thin, the number of special constructs are many. And, of course, all are poorly documented. SOAP 1.2 has a much better specification, but is not used a lot. I have not seen WSDL2 in real life.WSDL defines two kinds of messages: document style SOAP and rpc style SOAP. In document style SOAP, the messages are described in great detail in the WSDL: the message components are all defined in Schema's. The worst things you can (will) encounter are "any" schema elements which require additional manual processing. "RPC Literal" behaves very much the same way as document style soap, but has one extra wrapper inside the Body of the message. "Encoded SOAP-RPC", however, is a very different ball-game. It is simple to use with strongly typed languages, to exchange data when you create both the client software and the server software. You can simply autogenerate the data encoding. Clients written by third parties have to find the documentation on how to use the encoded RPC call in some other way... in text, if they are lucky; the WSDL file does not contain the prototype of the procedures, but that doesn't mean that they are free-format. Encoded RPC messages are shaped to the procedures which are being called on the server. The body of the sent message contains the ordered list of parameters to be passed as 'in' and 'in/out' values to the remote procedure. The body of the returned message lists the result value of the procedure, followed by the ordered 'out' and 'in/out' parameters. Supported serversOnly the commercial hype speaks about SOAP in very positive words. However, the "industry quality" of these modern "technologies" clearly demonstrates the lack of education and experience most programmers and designers have. This is clearly visible in many, many bugs you will encounter when working with schemas and WSDLs.Interoperability of SOAP clients and servers is more "trial and error" and "manually fixing" than it should be. For instance, a server may report internal server errors back to the client... but a WSDL does not tell you which namespace/schema is used for these errors. Both BEA and SharePoint servers produce illegal SOAP responses! It is a sad story. To be able to install some fixes, you can specify a server type via XML::Compile::SOAP::Operation::new(server_type), XML::Compile::WSDL11::new(server_type), or [3.06] XML::Compile::WSDL11::operations(server_type). The following server types are currently understood:
Examples: my $wsdl = XML::Compile::WSDL11->new($wsdlfn, server_type => 'SharePoint'); my $op = XML::Compile::SOAP11::Operation->new(..., server_type => 'BEA'); my @op = XML::Compile::WSDL11->operations(server_type => 'SharePoint') [3.17] Be warned: the licenses of some server_type schema's are unknown or unclear. At least, they touch commercial products hence can better not be released in a (Debian) Linux distribution, even not as non-free. Therefore, you need to install XML::Compile::Licensed from CPAN yourself. Naming types and elementsXML uses namespaces: URIs which are used as constants, grouping a set of type and element definitions. By using name-spaces, you can avoid name clashes, which have frustrated many projects in the past when they grew over a certain size... at a certain size, it becomes too hard to think of good distinguishable names. In such case, you must be happy when you can place those names in a context, and use the same naming in separate contexts without confusion.That being said: XML supports both namespace- and non-namespace elements and schema's; and of cause many mixed cases. It is by far preferred to use namespace schemas only. In a schema XSD file, look for the "targetNamespace" attribute of the "schema" element: if present, it uses namespaces. In XML data, it is seen as a hassle to write the full length of the URI each time that a namespace is addressed. For this reason, prefixes are used as abbreviations for the namespace URI. In programs, you can simply assign short variable names to long URIs, so we do not need that trick. Within your program, you use $MYNS = 'long URI of namespace'; ... $type => "{$MYNS}typename" ... or nicer use XML::Compile::Util qw/pack_type/; use constant MYNS => 'some uri'; ... $type => pack_type(MYNS, 'typename') ... The XML::Compile::Util module provides a helpful methods and constants, as does the XML::Compile::SOAP::Util. Client and Server implementationsTo learn how to create clients in SOAP, read the DETAILS section in XML::Compile::SOAP::Client. The client implementation is platform independent.Servers can be created with the external XML::Compile::SOAP::Daemon distribution. Those servers are based on Net::Server. Can be used to create a test-server in a few minutes... or production server. Don't forget to have a look at the examples in the examples/ directory included in the distribution. Use of wildcards (any and anyAttribute)Start reading about wildcards in XML::Compile. When you receive a message which contains "ANY" elements, an attempt will be made to decode it automatically. Sending messages which contain "ANY" fields is harder... you may try hooks or something more along these lines:my $doc = XML::LibXML::Document->new('1.0', 'UTF-8'); my $type = pack_type $ns, $local; my $node = $wsdl->writer($type)->($doc, $value); my $message = { ..., $type => $node }; my $call = $wsdl->compileClient('myOpToCall'); my ($answer, $trace) = $call->(_doc => $doc, message => $message); Here, $type is the type of the element which needs to be filled in on a spot where the schema defines an "ANY" element. You need to include the full typename as key in the HASH (on the right spot) and a fully prepared $node, an XML::LibXML::Element, as the value. You see that the $doc which is created to produce the special node in the message is also passed to the $call. The call produces the message which is sent and needs to use the same document object as the node inside it. The chances are that when you forget to pass the $doc it still works... but you may get into characterset problems and such. SEE ALSOThis module is part of XML-Compile-SOAP distribution version 3.27, built on April 07, 2021. Website: http://perl.overmeer.net/CPAN/LICENSECopyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog.This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://dev.perl.org/licenses/
Visit the GSP FreeBSD Man Page Interface. |