in reply to Re: Problem with SOAP::Lite module
in thread Problem with SOAP::Lite module

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.

Replies are listed 'Best First'.
Re^3: Problem with SOAP::Lite module
by Anonymous Monk on Jun 07, 2012 at 22:28 UTC

    It was a sort of steep learning curve, but I am now partial to the XML::Compile* libraries ...

    Do you have tips to share? What helped you get a handle on it?

      I don't think it was any more steep than SOAP::Lite (in fact probably easier), but...

      Some of the problem came from looking at some example requests and responses, not seeing some of the elements in the wsdl, wading through all the docs, figuring out which libraries in the XML::Compile::SOAP distribution to use, and figuring out that I needed in addition to XML::Compile::SOAP11:

      XML::Compile::SOAP::WSA XML::Compile::SOAP::WSS Data::UUID (for a bit in *::SOAP::WSA)</p>
      And figuring out which objects get plugged into which elements of which methods of the other objects. You may or may not need WSA and WSS, but if you do , it was kind of a pain to get working. I can post an outline of what I did. But once it did work, it was like magic, returning nice data structures of results.
Re^3: Problem with SOAP::Lite module
by oldwarrior32 (Sexton) on Jun 08, 2012 at 13:53 UTC

    It look like chinese for me. At least I just did the thing manually IP by IP. Anyway I'll keep investigating the issue.

    Thanks four your help.