kaushik km
kaushik km

Reputation: 39

SOAP client using perl - WSDL URL is available

I have a powershell script which will make a soap call, and perform the following operations: 1.Connects to the server hosting the WSDL (called cell in application terminology) 2.Creates an event(alert) in it. 3.Disconnects from the server hosting the WSDL(called cell in application terminology) I want to create perl version of this script.. which does the same exact operations,Please help me with functions and examples. or if possible by rewriting the below script in perl. Thank you so much in advance:

the PS script is as below:

===============================================================================

$severity = "MAJOR"

$msg = "Test event from Powershell"
$cellname = "mycell"

$url = "http://iiwshostname:9080/imws/services/ImpactManager/"
$headers = @{ "SOAPAction" = "Connect"}
$soap = [xml]@"
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:imap="http://blueprint.bmc.com/ImapiElems">
   <soapenv:Header/>
   <soapenv:Body>
      <imap:Connect>
         <imap:userName>admin</imap:userName>
         <imap:password>admin</imap:password>
         <imap:imname>$cellname</imap:imname>
         <imap:bufferType>BMCII_BUFFER_MODE_DEFAULT</imap:bufferType>
      </imap:Connect>
   </soapenv:Body>
</soapenv:Envelope>
"@
[xml]$ret = Invoke-WebRequest $url -Method post -ContentType 'text/xml' -Body $soap -Headers $headers
$connectionId = $ret.GetElementsByTagName("imap:connectionId").'#text'

$headers = @{ "SOAPAction" = "SendEvent"}
$soap = [xml]@"
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:imap="http://blueprint.bmc.com/ImapiElems" xmlns:bas="http://blueprint.bmc.com/BasicTypes" xmlns:even="http://blueprint.bmc.com/Event">
   <soapenv:Header/>
   <soapenv:Body>
      <imap:SendEvent>
         <imap:connection>$connectionId</imap:connection>
         <imap:message>    
            <bas:NameValue_element>    
               <bas:name>msg</bas:name>    
               <bas:value>    
                  <bas:string_value>$msg</bas:string_value>    
               </bas:value>    
               <bas:value_type>STRING</bas:value_type>    
            </bas:NameValue_element>    
            <bas:NameValue_element>    
               <bas:name>severity</bas:name>    
               <bas:value>    
                  <bas:string_alue>$severity</bas:string_value>    
               </bas:value>   
               <bas:value_type>STRING</bas:value_type>    
            </bas:NameValue_element>              
            <even:subject></even:subject>    
         </imap:message>    
         <imap:timeout>60</imap:timeout>    
         <imap:messageClass>EVENT</imap:messageClass>    
         <imap:messageType>MSG_TYPE_NEW_EVENT</imap:messageType>    
      </imap:SendEvent>    
   </soapenv:Body>    
</soapenv:Envelope>    
"@    
[xml]$ret = Invoke-WebRequest $url -Method post -ContentType 'text/xml' -Body $soap -Headers $headers    

$mc_ueid = $ret.GetElementsByTagName("imap:response").'#text'    

$headers = @{ "SOAPAction" = "Disconnect"}    
$soap = [xml]@"    
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soapenvelope/" xmlns:imap="http://blueprint.bmc.com/ImapiElems">
       <soapenv:Header/>
       <soapenv:Body>
          <imap:Disconnect>
             <imap:connection>$connectionId</imap:connection>
             <imap:deleteBuffer>No</imap:deleteBuffer>    
      </imap:Disconnect>    
   </soapenv:Body>    
</soapenv:Envelope>    
"@    
$ret = Invoke-WebRequest $url -Method post -ContentType 'text/xml' -Body $soap -Headers $headers    

write-host $mc_ueid

===============================================================================

Upvotes: 2

Views: 999

Answers (1)

GMB
GMB

Reputation: 222492

As commented by @Grinnz : please don’t use SOAP::Lite, it’s ugly. The de facto standard to run SOAP operations over HTTP in Perl is XML::Compile::SOAP, which is quite complete, well maintained and thoroughly documented. However it can be a little complicated to get your head around it, due to the inherent complexity of the SOAP protocol. The following explanation should get you started.

Before all you have to load the modules :

use XML::Compile::SOAP11;
use XML::Compile::WSDL11;

Then the first step is to create a WSDL object and load the WSDL file :

my $wsdl = XML::Compile::WSDL11->new;
$wsdl->addWSDL($wsdl_file);

If your WSDL file depends on some XSD files, then you have to load them first, before the WSDL, by calling :

$wsdl->importDefinitions($xsd_file);

Please note that for security reasons, XML::Compile will never try to load online resources ; you have to download them manually and then load them from disk.

The second step is to compile the object. This will actually create persistent code references in the object, that you can invoke repeatedly afterwards to perform operations. You pass the url of the target service as an argument to the compiler. For example, the following call compiles all available operations :

$wsdl->compileCalls( address => $url);

At compile time, you also have the possibility of passing your own HTTP transport object instead of relying on XML::Compile defaults. This is useful when you want fine-grained control on the transport layer (like setting a HTTP proxy, ...). For example with LWP::UserAgent :

my $ua = LWP::UserAgent->new( show_progress => 1 );
$wsdl->compileCalls( address => $self->url, user_agent => $ua );

Now you are ready to invoke the webservice. You pass the name of the operation and a data structure, as follows :

my ( $answer, $trace ) = $wsdl->call( $ope, $data );

If anything goes wrong, the call dies. On success, it returns a Perl data structure that represents the parsed response. That’s it !

XML::Compile provides a lot of useful introspection and debugging methods. For example, after compilation, you can print the list all available operations with :

$wsdl->printIndex;

To display the details of the input data structure of a given operation :

$wsdl->explain( $ope, PERL => "INPUT", recurse => 1 );

After an operation was executed, the trace object can be used to obtain many internal details about how things happened, for example :

$trace->printRequest;
$trace->printResponse;
$trace->printTimings;

Upvotes: 2

Related Questions