1=encoding utf8
2
3=head1 NAME
4
5XML::Compile::SOAP::Client - SOAP message initiators
6
7=head1 INHERITANCE
8
9 XML::Compile::SOAP::Client is extended by
10   XML::Compile::SOAP11::Client
11   XML::Compile::SOAP12::Client
12
13=head1 SYNOPSIS
14
15 # never used directly, only via XML::Compile::SOAP1[12]::Client
16
17=head1 DESCRIPTION
18
19This class defines the methods that each client side of the SOAP
20message exchange protocols must implement.
21
22=head1 METHODS
23
24=head2 Constructors
25
26This object can not be instantiated, but is only used as secundary
27base class.  The primary must contain the C<new>.
28
29=head2 Handlers
30
31=over 4
32
33=item $obj-E<gt>B<compileClient>(%options)
34
35 -Option   --Default
36  async      <false>
37  decode     <required>
38  encode     <required>
39  kind       request-response
40  name       <undef>
41  soap       'SOAP11'
42  transport  <required>
43
44=over 2
45
46=item async => BOOLEAN
47
48If true, a whole different code-reference is returned. Each time it
49is called, the call will be made but the function returns immediately.
50As additional parameter to the call, you must provide a C<_callback>
51parameter which is a code-reference which will handle the result.
52
53=item decode => CODE
54
55The CODE reference is produced by L<XML::Compile::SOAP::compileMessage()|XML::Compile::SOAP/"Single message">,
56and must be a RECEIVER: translate a SOAP message into Perl data.  Even in
57one-way operation, this decode should be provided: some servers may pass
58back some XML in case of errors.
59
60=item encode => CODE
61
62The CODE reference is produced by L<XML::Compile::SOAP::compileMessage()|XML::Compile::SOAP/"Single message">,
63and must be a SENDER: translates Perl data structures into the SOAP
64message in XML.
65
66=item kind => STRING
67
68Which kind of client is this.  WSDL11 defines four kinds of client-server
69interaction.  Only C<request-response> (the default) and C<one-way> are
70currently supported.
71
72=item name => STRING
73
74=item soap => OBJECT|'SOAP11'|'SOAP12'
75
76When the transport parameter is an object, this is used to wrap the
77SOAP content according to the matching transporter regulation.
78
79=item transport => CODE|OBJECT
80
81The CODE reference is produced by an extensions of
82L<XML::Compile::Transport::compileClient()|XML::Compile::Transport/"Handlers"> (usually
83L<XML::Compile::Transport::SOAPHTTP::compileClient()|XML::Compile::Transport::SOAPHTTP/"Handlers">.
84
85If you pass a L<XML::Compile::Transport::SOAPHTTP|XML::Compile::Transport::SOAPHTTP> object, the
86compileClient will be called for you.  This is possible in case you do
87not have any configuration options to pass with the compileClient().
88
89=back
90
91example:
92
93Normal call:
94
95   my $call = $wsdl->compileClient('myOp');
96   my ($answer, $trace) = $call->(@params);
97   #do something with $answer
98
99Async call:
100
101   my $call = $wsdl->compileClient('myOp', async => 1);
102   sub cb
103   {  my ($answer, $trace) = @_;
104      #do something with $answer
105   };
106   $call->(@params, _callback => \&cb);
107
108=back
109
110=head1 DETAILS
111
112=head2 Client side SOAP
113
114=head3 Calling the server (Document style)
115
116First, you compile the call either via a WSDL file (see
117L<XML::Compile::WSDL11|XML::Compile::WSDL11>), or in a few manual steps (which are described
118in the next section).  In either way, you end-up with a CODE references
119which can be called multiple times.
120
121    # compile once
122    my $call   = $soap->compileClient(...);
123
124    # and call often
125    my $answer = $call->(%request);  # list of pairs
126    my $answer = $call->(\%request); # same, but HASH
127    my $answer = $call->(\%request, 'UTF-8');  # same
128
129    # or with trace details, see XML::Compile::SOAP::Trace
130    my ($answer, $trace) = $call->...
131
132But what is the structure of C<%request> and C<$answer>?  Well, there
133are various syntaxes possible: from structurally perfect, to user-friendly.
134
135First, find out which data structures can be present: when you compiled
136your messages explicitly, you have picked your own names.  When the
137call was initiated from a WSDL file, then you have to find the names of
138the message parts which can be used: the part names for header blocks,
139body blocks, headerfaults, and (body) faults.  Do not worry to much,
140you will get (hopefully understandable) run-time error messages when
141the structure is incorrect.
142
143Let's say that the WSDL defines this (ignoring all name-space issues)
144
145 <definitions xmlns:xx="MYNS"
146   <message name="GetLastTradePriceInput">
147    <part name="count" type="int" />
148    <part name="request" element="xx:TradePriceRequest"/>
149   </message>
150
151   <message name="GetLastTradePriceOutput">
152    <part name="answer" element="xx:TradePrice"/>
153   </message>
154
155   <binding
156    <operation
157     <input>
158      <soap:header message="GetLastTradePriceInput" part="count"
159      <soap:body message="GetLastTradePriceInput" parts="request"
160     <output>
161      <soap:body message="GetLastTradePriceOutput"
162
163The input message needs explicitly named parts in this case, where the
164output message simply uses all defined in the body.  So, the input message
165has one header part C<count>, and one body part C<request>.  The output
166message only has one part named C<answer>, which is all defined for the
167message and therefore its name can be omitted.
168
169Then, the definitions of the blocks:
170
171 <schema targetNamespace="MYNS"
172   <element name="TradePriceRequest">
173    <complexType>
174     <all>
175      <element name="tickerSymbol" type="string"/>
176
177   <element name="TradePrice">
178    <complexType>
179     <all>
180      <element name="price" type="float"/>
181 </schema>
182
183Now, calling the compiled function can be done like this:
184
185  my $got
186     = $call->(  count => 5, request => {tickerSymbol => 'IBM'}  );
187     = $call->({ count => 5, request => {tickerSymbol => 'IBM'} });
188     = $call->({ count => 5, request => {tickerSymbol => 'IBM'} }
189        , 'UTF-8');
190
191If the first arguments for the code ref is a HASH, then there may be
192a second which specifies the required character-set.  The default is
193C<UTF-8>, which is very much advised.
194
195=head3 Parameter unpacking (Document Style)
196
197In the example situation of previous section, you may simplify the
198call even further.  To understand how, we need to understand the
199parameter unpacking algorithm.
200
201The structure which we need to end up with, looks like this
202
203  $call->(\%data, $charset);
204  %data = ( Header => {count => 5}
205          , Body   =>
206             { request => {tickerSymbol => 'IBM'} }
207          );
208
209The structure of the SOAP message is directly mapped on this
210nested complex HASH.  But is inconvenient to write each call
211like this, therefore the C<$call> parameters are transformed into
212the required structure according to the following rules:
213
214=over 4
215
216=item 1.
217
218if called with a LIST, then that will become a HASH
219
220=item 2.
221
222when a C<Header> and/or C<Body> are found in the HASH, those are used
223
224=item 3.
225
226if there are more parameters in the HASH, then those with names of
227known header and headerfault message parts are moved to the C<Header>
228sub-structure.  Body and fault message parts are moved to the C<Body>
229sub-structure.
230
231=item 4.
232
233If the C<Body> sub-structure is empty, and there is only one body part
234expected, then all remaining parameters are put in a HASH for that part.
235This also happens if there are not parameters: it will result in an
236empty HASH for that block.
237
238=back
239
240So, in our case this will also do, because C<count> is a known part,
241and C<request> gets all left-overs, being the only body part.
242
243 my $got = $call->(count => 5, tickerSymbol => 'IBM');
244
245This does not work if the block element is a simple type.  In most
246existing Document style SOAP schemas, this simplification probably
247is possible.
248
249=head3 Understanding the output (Document style)
250
251The C<$got> is a HASH, which will not be simplified automatically:
252it may change with future extensions of the interface.  The return
253is a complex nested structure, and Data::Dumper is your friend.
254
255 $got = { answer => { price => 16.3 } }
256
257To access the value use
258
259 printf "%.2f US\$\n", $got->{answer}->{price};
260 printf "%.2f US\$\n", $got->{answer}{price};   # same
261
262or
263
264 my $answer = $got->{answer};
265 printf "%.2f US\$\n", $answer->{price};
266
267=head3 Calling the server (SOAP-RPC style literal)
268
269SOAP-RPC style messages which have C<<use=literal>> cannot be used
270without a little help.  However, one extra definition per procedure
271call suffices.
272
273This a complete code example, although you need to fill in some
274specifics about your environment.  If you have a WSDL file, then it
275will be a little simpler, see L<XML::Compile::WSDL11::compileClient()|XML::Compile::WSDL11/"Extension">.
276
277 # You probably need these
278 use XML::Compile::SOAP11::Client;
279 use XML::Compile::Transport::SOAPHTTP;
280 use XML::Compile::Util  qw/pack_type/;
281
282 # Literal style RPC
283 my $outtype = pack_type $MYNS, 'myFunction';
284 my $intype  = pack_type $MYNS, 'myFunctionResponse';
285
286 # Encoded style RPC (see next section on these functions)
287 my $outtype = \&my_pack_params;
288 my $intype  = \&my_unpack_params;
289
290 # For all RPC calls, you need this only once (or have a WSDL):
291 my $transp  = XML::Compile::Transport::SOAPHTTP->new(...);
292 my $http    = $transp->compileClient(...);
293 my $soap    = XML::Compile::SOAP11::Client->new(...);
294 my $send    = $soap->compileMessage('SENDER',   style => $style, ...);
295 my $get     = $soap->compileMessage('RECEIVER', style => $style, ...);
296
297 # Per RPC procedure
298 my $myproc = $soap->compileClient
299   ( name   => 'MyProc'
300   , encode => $send, decode => $get, transport => $http
301   );
302
303 my $answer = $myproc->(@parameters);   # as document style
304
305Actually, the C<< @paramers >> are slightly less flexible as in document
306style SOAP.  If you use header blocks, then the called CODE reference
307will not be able to distinguish between parameters for the RPC block and
308parameters for the header blocks.
309
310  my $answer = $trade_price
311    ->( {symbol => 'IBM'}    # the RPC package implicit
312      , transaction => 5     # in the header
313      );
314
315When the number of arguments is odd, the first is indicating the RPC
316element, and the other pairs refer to header blocks.
317
318The C<$answer> structure may contain a C<Fault> entry, or a decoded
319datastructure with the results of your query.  One call using
320Data::Dumper will show you more than I can explain in a few hundred
321words.
322
323=head3 Calling the server (SOAP-RPC style, encoded)
324
325SOAP-RPC is a simplification of the interface description: basically,
326the interface is not described at all, but left to good communication
327between the client and server authors.  In strongly typed languages,
328this is quite simple to enforce: the client side and server side use
329the same method prototypes.  However, in Perl we are blessed to go
330without these strongly typed prototypes.
331
332The approach of SOAP::Lite, is to guess the types of the passed
333parameters.  For instance, "42" will get passed as Integer.  This
334may lead to nasty problems: a float parameter "2.0" will get passed
335as integer "2", or a string representing a house number "8" is passed
336as an number.  This may not be accepted by the SOAP server.
337
338So, using SOAP-RPC in L<XML::Compile::SOAP|XML::Compile::SOAP> will ask a little more
339effort from you: you have to state parameter types explicitly.  In
340the F<examples/namesservice/> directory, you find a detailed example.
341You have to create a CODE ref which produces the message, using
342methods defined provided by L<XML::Compile::SOAP11::Encoding|XML::Compile::SOAP11::Encoding>.
343
344=head3 Faults (Document and RPC style)
345
346Faults and headerfaults are a slightly different story: the type which
347is specified with them is not of the fault XML node itself, but of the
348C<detail> sub-element within the standard fault structure.
349
350When producing the data for faults, you must be aware of the fact that
351the structure is different for SOAP1.1 and SOAP1.2.  When interpreting
352faults, the same problems are present, although the implementation
353tries to help you by hiding the differences.
354
355Check whether SOAP1.1 or SOAP1.2 is used by looking for a C<faultcode>
356(SOAP1.1) or a C<Code> (SOAP1.2) field in the data:
357
358  if(my $fault = $got->{Fault})
359  {  if($fault->{faultcode}) { ... SOAP1.1 ... }
360     elsif($fault->{Code})   { ... SOAP1.2 ... }
361     else { die }
362  }
363
364In either protocol case, the following will get you at a compatible
365structure in two steps:
366
367  if(my $fault = $got->{Fault})
368  {   my $decoded = fault->{_NAME}};
369      print $got->{$decoded}->{code};
370      ...
371  }
372
373See the respective manuals L<XML::Compile::SOAP11|XML::Compile::SOAP11> and
374L<XML::Compile::SOAP12|XML::Compile::SOAP12> for the hairy details.  But one thing can be said:
375when the fault is declared formally, then the C<_NAME> will be the name
376of that part.
377
378=head2 SOAP without WSDL (Document style)
379
380See the manual page of L<XML::Compile::WSDL11|XML::Compile::WSDL11> to see how simple you
381can use this module when you have a WSDL file at hand.  The creation of
382a correct WSDL file is NOT SIMPLE.
383
384When using SOAP without WSDL file, it gets a little bit more complicate
385to use: you need to describe the content of the messages yourself.
386The following example is used as test-case C<t/10soap11.t>, directly
387taken from the SOAP11 specs section 1.3 example 1.
388
389 # for simplification
390 my $TestNS   = 'http://test-types';
391 use XML::Compile::Util qw/SCHEMA2001/;
392 my $SchemaNS = SCHEMA2001;
393
394First, the schema (hopefully someone else created for you, because they
395can be quite hard to create correctly) is in file C<myschema.xsd>
396
397 <schema targetNamespace="$TestNS"
398   xmlns="$SchemaNS">
399
400 <element name="GetLastTradePrice">
401   <complexType>
402      <all>
403        <element name="symbol" type="string"/>
404      </all>
405   </complexType>
406 </element>
407
408 <element name="GetLastTradePriceResponse">
409   <complexType>
410      <all>
411         <element name="price" type="float"/>
412      </all>
413   </complexType>
414 </element>
415
416 <element name="Transaction" type="int"/>
417 </schema>
418
419Ok, now the program you create the request:
420
421 use XML::Compile::SOAP11;
422 use XML::Compile::Util  qw/pack_type/;
423
424 my $soap   = XML::Compile::SOAP11->new;
425 $soap->schemas->importDefinitions('myschema.xsd');
426
427 my $get_price = $soap->compileMessage
428   ( 'SENDER'
429   , header =>
430      [ transaction => pack_type($TestNS, 'Transaction') ]
431   , body  =>
432      [ request => pack_type($TestNS, 'GetLastTradePrice') ]
433   , mustUnderstand => 'transaction'
434   , destination    => [ transaction => 'NEXT http://actor' ]
435   );
436
437C<INPUT> is used in the WSDL terminology, indicating this message is
438an input message for the server.  This C<$get_price> is a WRITER.  Above
439is done only once in the initialization phase of your program.
440
441At run-time, you have to call the CODE reference with a
442data-structure which is compatible with the schema structure.
443(See L<XML::Compile::Schema::template()|XML::Compile::Schema/"Compilers"> if you have no clue how it should
444look)  So: let's send this:
445
446 # insert your data
447 my %data_in = (transaction => 5, request => {symbol => 'DIS'});
448 my %data_in = (transaction => 5, symbol => 'DIS'); # alternative
449
450 # create a XML::LibXML tree
451 my $xml  = $get_price->(\%data_in, 'UTF-8');
452 print $xml->toString;
453
454And the output is:
455
456 <SOAP-ENV:Envelope
457    xmlns:x0="http://test-types"
458    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
459   <SOAP-ENV:Header>
460     <x0:Transaction
461       mustUnderstand="1"
462       actor="http://schemas.xmlsoap.org/soap/actor/next http://actor">
463         5
464     </x0:Transaction>
465   </SOAP-ENV:Header>
466   <SOAP-ENV:Body>
467     <x0:GetLastTradePrice>
468       <symbol>DIS</symbol>
469     </x0:GetLastTradePrice>
470   </SOAP-ENV:Body>
471 </SOAP-ENV:Envelope>
472
473Some transport protocol will sent this data from the client to the
474server.  See L<XML::Compile::Transport::SOAPHTTP|XML::Compile::Transport::SOAPHTTP>, as one example.
475
476On the SOAP server side, we will parse the message.  The string C<$soap>
477contains the XML.  The program looks like this:
478
479 my $server = $soap->compileMessage # create once
480  ( 'RECEIVER'
481  , header => [ transaction => pack_type($TestNS, 'Transaction') ]
482  , body   => [ request => pack_type($TestNS, 'GetLastTradePrice') ]
483  );
484
485 my $data_out = $server->($soap);   # call often
486
487Now, the C<$data_out> reference on the server, is stucturally exactly
488equivalent to the C<%data_in> from the client.
489
490=head1 SEE ALSO
491
492This module is part of XML-Compile-SOAP distribution version 3.27,
493built on April 07, 2021. Website: F<http://perl.overmeer.net/CPAN/>
494
495=head1 LICENSE
496
497Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog.
498
499This program is free software; you can redistribute it and/or modify it
500under the same terms as Perl itself.
501See F<http://dev.perl.org/licenses/>
502
503