File: SOAP.pod

package info (click to toggle)
libxml-compile-soap-perl 3.28%2Bds-1
  • links: PTS, VCS
  • area: non-free
  • in suites: bookworm, forky, sid, trixie
  • size: 616 kB
  • sloc: perl: 4,407; makefile: 7
file content (464 lines) | stat: -rw-r--r-- 16,077 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
=encoding utf8

=head1 NAME

XML::Compile::SOAP - base-class for SOAP implementations

=head1 INHERITANCE

 XML::Compile::SOAP is extended by
   XML::Compile::SOAP11
   XML::Compile::SOAP12

=head1 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

=head1 DESCRIPTION

This module handles the SOAP protocol.  The first implementation is
SOAP1.1 (F<http://www.w3.org/TR/2000/NOTE-SOAP-20000508/>), which is still
most often used.  The SOAP1.2 definition (F<http://www.w3.org/TR/soap12/>)
is provided via the separate distribution L<XML::Compile::SOAP12|XML::Compile::SOAP12>.

Be aware that there are three kinds of SOAP:

=over 4

=item 1.

Document style (literal) SOAP, where there is a WSDL file which explicitly
types all out-going and incoming messages.  Very easy to use.

=item 2.

RPC style SOAP literal.  The body of the message has an extra element
wrapper, but the content is also well defined.

=item 3.

RPC style SOAP encoded.  The sent data is nowhere described formally.
The data is constructed in some ad-hoc way.

=back

Don't forget to have a look at the examples in the F<examples/> directory
included in the distribution.

Please support my development work by submitting bug-reports, patches
and (if available) a donation.

=head1 METHODS

=head2 Constructors

=over 4

=item $obj-E<gt>B<new>(%options)

Create a new SOAP object.  You have to instantiate either the SOAP11 or
SOAP12 sub-class of this, because there are quite some differences (which
can be hidden for you)

 -Option    --Default
  media_type  application/soap+xml
  schemas     created internally

=over 2

=item media_type => MIMETYPE

=item schemas => C<XML::Compile::Cache> object

Use this when you have already processed some schema definitions.  Otherwise,
you can add schemas later with C<< $soap->schemas->importDefinitions() >>
The Cache object must have C<any_element> and C<any_attribute> set to
C<'ATTEMPT'>

=back

=item XML::Compile::SOAP-E<gt>B<register>($uri, $envns)

Declare an operation type, being an (WSDL specific) $uri and envelope
namespace.

=back

=head2 Accessors

=over 4

=item $obj-E<gt>B<mediaType>()

=item $obj-E<gt>B<schemas>()

Returns the L<XML::Compile::Cache|XML::Compile::Cache> object which contains the
knowledge about the types.

=item $obj-E<gt>B<version>()

=back

=head2 Single message

=over 4

=item $obj-E<gt>B<compileMessage>( <'SENDER'|'RECEIVER'>, %options )

The payload is defined explicitly, where all headers and bodies are
described in detail.  When you have a WSDL file, these ENTRIES are
generated automatically, but can be modified and extended (WSDL files
are often incomplete)

To make your life easy, the ENTRIES use a label (a free to choose key,
the I<part name> in WSDL terminology), to ease relation of your data with
the type where it belongs to.  The element of an entry (the value) is
defined as an C<any> element in the schema, and therefore you will need
to explicitly specify the element to be processed.

As %options, you can specify any listed here, but also anything which is
accepted by L<XML::Compile::Schema::compile()|XML::Compile::Schema/"Compilers">, like
C<< sloppy_integers => 1 >> and hooks.  These are applied to all header
and body elements (not to the SOAP wrappers)

 -Option        --Default
  body            []
  destination     []
  faults          []
  header          undef
  mustUnderstand  []
  procedure       undef
  role            ULTIMATE
  roles           []

=over 2

=item body => ENTRIES|HASH

ARRAY of PAIRS, defining a nice LABEL (free of choice but unique, also
w.r.t. the header and fault ENTRIES) and an element type name or CODE
reference.  The LABEL will appear in the Perl HASH only, to be able to
refer to a body element in a simple way.

=item destination => ARRAY-OF-PAIRS

Writers only.  Indicate who the target of the header entry is.
By default, the end-point is the destination of each header element.

The ARRAY contains a LIST of key-value pairs, specifying an entry label
followed by an I<actor> (soap1.1) or I<role> (soap1.2) URI.  You may use
the predefined actors/roles, like 'NEXT'.  See L<roleURI()|XML::Compile::SOAP/"Transcoding"> and
L<roleAbbreviation()|XML::Compile::SOAP/"Transcoding">.

=item faults => ENTRIES|HASH

The SOAP1.1 and SOAP1.2 protocols define fault entries in the
answer.  Both have a location to add your own additional
information: the type(-processor) is to specified here, but the
returned information structure is larger and differs per SOAP
implementation.

=item header => ENTRIES|HASH

ARRAY of PAIRS, defining a nice LABEL (free of choice but unique)
and an element type name.  The LABEL will appear in the Perl HASH, to
refer to the element in a simple way.

The element type is used to construct a reader or writer.  You may also
create your own reader or writer, and then pass a compatible CODE reference.

=item mustUnderstand => STRING|ARRAY-OF-STRING

Writers only.  The specified header entry labels specify which elements
must be understood by the destination.  These elements will get the
C<mustUnderstand> attribute set to C<1> (soap1.1) or C<true> (soap1.2).

=item procedure => TYPE

Required in rpc style, when there is no C<body> which contains the
procedure name (when the RPC info does not come from a WSDL)

=item role => URI|ARRAY-OF-URI

Readers only.
One or more URIs, specifying the role(s) you application has in the
process.  Only when your role contains C<ULTIMATE>, the body is
parsed.  Otherwise, the body is returned as uninterpreted XML tree.
You should not use the role C<NEXT>, because every intermediate
node is a C<NEXT>.

All understood headers are parsed when the C<actor> (soap1.1) or
C<role> (soap1.2) attribute address the specified URI.  When other
headers emerge which are not understood but carry the C<mustUnderstood>
attribute, an fault is returned automatically.  In that case, the
call to the compiled subroutine will return C<undef>.

=item roles => ARRAY-OF-URI

Alternative for option C<role>

=back

=item $obj-E<gt>B<messageStructure>($xml)

=item XML::Compile::SOAP-E<gt>B<messageStructure>($xml)

Returns a HASH with some collected information from a complete SOAP
message (XML::LibXML::Document or XML::LibXML::Element).  Currenty,
the HASH contains a C<header> and a C<body> key, with each an ARRAY
of element names which where found in the header resp. body.

=back

=head2 Helpers

=head2 Transcoding

=over 4

=item $obj-E<gt>B<replyMustUnderstandFault>($type)

Produce an error structure to be returned to the sender.

=item $obj-E<gt>B<roleAbbreviation>($uri)

Translate a role $uri into a simple string, if predefined.  See
L<roleURI()|XML::Compile::SOAP/"Transcoding">.

=item $obj-E<gt>B<roleURI>($uri|STRING)

Translates actor/role/destination abbreviations into URIs. Various
SOAP protocol versions have different pre-defined STRINGs, which can
be abbreviated for readibility.  Returns the unmodified $uri in
all other cases.

SOAP11 only defines C<NEXT>.  SOAP12 defines C<NEXT>, C<NONE>, and
C<ULTIMATE>.

=back

=head1 DETAILS

=head2 SOAP introduction

Although 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: B<document> style SOAP and B<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 C<any> schema
elements which require additional manual processing.

C<RPC Literal> behaves very much the same way as document style soap,
but has one extra wrapper inside the Body of the message.

C<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.

B<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.

=head2 Supported servers

Only 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
L<XML::Compile::SOAP::Operation::new(server_type)|XML::Compile::SOAP::Operation/"Constructors">,
L<XML::Compile::WSDL11::new(server_type)|XML::Compile::WSDL11/"Constructors">, or
[3.06] L<XML::Compile::WSDL11::operations(server_type)|XML::Compile::WSDL11/"Introspection">.

The following server types are currently understood:

=over 4

=item * C<BEA>, Oracle

=item * C<SharePoint>, MicroSoft

=item * C<XML::Compile::Daemon>

=back

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] B<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.

=head2 Naming types and elements

XML 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
C<targetNamespace> attribute of the C<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 L<XML::Compile::Util|XML::Compile::Util> module provides a helpful methods and constants,
as does the L<XML::Compile::SOAP::Util|XML::Compile::SOAP::Util>.

=head2 Client and Server implementations

To learn how to create clients in SOAP, read the DETAILS section in
L<XML::Compile::SOAP::Client|XML::Compile::SOAP::Client>.  The client implementation is platform
independent.

Servers can be created with the external L<XML::Compile::SOAP::Daemon|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 F<examples/> directory
included in the distribution.

=head2 Use of wildcards (any and anyAttribute)

Start reading about wildcards in L<XML::Compile|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, C<$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 C<$node>, an XML::LibXML::Element, as the value.

You see that the C<$doc> which is created to produce the special node
in the message is also passed to the C<$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 C<$doc>
it still works... but you may get into characterset problems and such.

=head1 SEE ALSO

This module is part of XML-Compile-SOAP distribution version 3.28,
built on August 01, 2022. Website: F<http://perl.overmeer.net/CPAN/>

=head1 LICENSE

Copyrights 2007-2022 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 F<http://dev.perl.org/licenses/>