It was a sort of steep learning curve, but I am now partial to the XML::Compile* libraries. Especially since I was interacting with a .NET SOAP service that had WSDL files available.

Update:

I've also been figuring out the best way to throw exceptions from this library. XML::Compile internally catches and logs errors, but wasn't throwing errors. The framework I've settled on is:

sub wsdl { my $self = shift; return $self->{WSDL} if $self->{WSDL}; $self->{WSDL} = XML::Compile::WSDL11->new($wsdl_file); return $self->{WSDL}; } sub cc { my ( $self, $op, $full_response ) = @_; return $self->{$op} if $self->{$op}; my $f = $self->wsdl()->compileClient( operation => $op, port => $port, @dbug, ); $self->{$op} = sub { my $r = eval { $f->( @_ ) }; unless ($r) { my $err = $@; confess "Error calling SOAP method $op: $err"; } my $fault = $r->{Fault}; confess "$fault->{faultcode}: $fault->{faultstring}" if $fault +; return $full_response ? $r : $r->{parameters}; }; }
Then to call a SOAP method, it's:
$self->cc($method_name)->(%args);

Advantages? One place (per service) to maintain all SOAP calls. One place to insert certain auth parameters or put certain behavior. E.g., in one service I need to insert wsa and wsse headers. In another, I can not make two simultaneous SOAP calls (with the same account), so I wrap the call with lock file code, and in the same service I get a certain sort of common error so I wrap the whole SOAP call with some retry logic.

And I need the $full_response parameter in one service because I have to use data in the header of the response from the first call (basically a 'Login' sort of call) in all subsequent calls. I don't need the header after that so I just return the 'parameters' part of the response.

Update: I've replaced:

my $r = eval { $f->( @_ ) }; unless ($r) { my $err = $@; confess "Error calling SOAP method $op: $err"; }
with:
my $r = eval { my $tmp = $f->( @_ ); $eval_err = $@; $tmp; }; my $err = $@; close $fh; unless ($r) { no warnings 'uninitialized'; # Retry these errors if ( $eval_err =~ /answer is not xml/ ) { if ( $retry-- > 0 ) { Print("[$$] Recieved text/html response. Will retr +y $op request."); sleep 2; next; } } confess "Error calling SOAP method $op: [$err][$eval_e +rr]"; }
There are non-fatal errors that cause undef to be returned from the SOAP call, and this catches them. There are evals inside XML::Compile, so catching $@ at that level catches the error message, and I can retry based on that error message.

In reply to Re^2: Problem with SOAP::Lite module by runrig
in thread Problem with SOAP::Lite module by oldwarrior32

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.