Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

I'm trying to convert this known working SOAP call to SOAP::Lite in Perl and having difficulty doing so. The examples and tutorials I'm seeing are all for simpler use cases, and I haven't found what I need in the perldoc. So many options... I have a WSDL available to use, and the method to call seems to be RunLocator. This is an example of a request I would make in SoapUI:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envel +ope/" xmlns:was="http://tempuri.org/AWEService/API/WASAPI"> <soapenv:Header/> <soapenv:Body> <was:RunLocator> <was:userIdentification> <was:WAS_userName>WS_Decom</was:WAS_userName> <was:WAS_password>PASSWORD</was:WAS_password> </was:userIdentification> <was:locatorSearchFieldsIdentification> <was:DEVICE_NAME>prodh20</was:DEVICE_NAME> </was:locatorSearchFieldsIdentification> </was:RunLocator> </soapenv:Body> </soapenv:Envelope>

Note that in SoapUI (or sending that request body with curl), I would fill out the authentication and DEVICE_NAME and leave the rest empty. It will send back a response in the format:

<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envel +ope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http:// +www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:RunLocatorResponse xmlns="urn:RunLocator" xmlns:ns1="http://tempu +ri.org/AWEService/API/WASAPI" xmlns:xsd="http://www.w3.org/2001/XMLSc +hema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ns1:RunLocatorResult> <ns1:DEVICE_NAME>prodh20</ns1:DEVICE_NAME> <ns1:MANUFACTURER>HEWLETT PACKARD</ns1:MANUFACTURER> <ns1:MODEL>PROLIANT DL380P GEN8</ns1:MODEL> <ns1:ASSET_NUMBER></ns1:ASSET_NUMBER> <ns1:BARCODE_NUMBER></ns1:BARCODE_NUMBER> <ns1:SERIAL_NUMBER>(SERIAL)</ns1:SERIAL_NUMBER> <ns1:BUILDING>(BUILDING)</ns1:BUILDING> <ns1:FLOOR>(FLOOR)</ns1:FLOOR> <ns1:SPACE_ID>(SPACE_ID)</ns1:SPACE_ID> <ns1:GRID_LOCATION>(LOC)/ns1:GRID_LOCATION> <ns1:RACK_NAME>(RACK)</ns1:RACK_NAME> <ns1:RACK_MOUNT_SIDE>FRONT</ns1:RACK_MOUNT_SIDE> <ns1:BOTTOM_RACK_UNIT>7</ns1:BOTTOM_RACK_UNIT> <ns1:HEIGHT>3.5</ns1:HEIGHT> </ns1:RunLocatorResult> </ns1:RunLocatorResponse> </soapenv:Body> </soapenv:Envelope>

Parenthesized fields contain values which I've removed for posting here. I've tried many different techniques with SOAP::Lite adapted from examples online, the latest involving SOAP::Header and SOAP::Data. Can someone please point me in the right direction for how I should be approaching this? And I presume I'm going to need SOM to parse the result, if I can get that far.

Here is the WSDL, with the actual server name replaced by www.example.com:

<definitions xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns: +soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.o +rg/2001/XMLSchema" xmlns:s0="http://tempuri.org/AWEService/API/WASAPI +" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tm= +"http://microsoft.com/wsdl/mime/textMatching/" xmlns:mime="http://sch +emas.xmlsoap.org/wsdl/mime/" xmlns="http://schemas.xmlsoap.org/wsdl/" + targetNamespace="http://tempuri.org/AWEService/API/WASAPI"> <types> <s:schema elementFormDefault="qualified" targetNamespace="http://tempu +ri.org/AWEService/API/WASAPI"> <s:element name="RunLocator"> <s:complexType> <s:sequence> <s:element minOccurs="1" maxOccurs="1" name="userIdentification" type= +"s0:UserIdentificationStructure"/> <s:element minOccurs="1" maxOccurs="1" name="locatorSearchFieldsIdenti +fication" type="s0:LocatorSearchFieldsStructure"/> </s:sequence> </s:complexType> </s:element> <s:complexType name="UserIdentificationStructure"> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="WAS_userName" type="s:str +ing"/> <s:element minOccurs="0" maxOccurs="1" name="WAS_password" type="s:str +ing"/> </s:sequence> </s:complexType> <s:complexType name="LocatorSearchFieldsStructure"> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="RACK_NAME" type="s:string +"/> <s:element minOccurs="0" maxOccurs="1" name="DEVICE_NAME" type="s:stri +ng"/> <s:element minOccurs="0" maxOccurs="1" name="MANUFACTURER" type="s:str +ing"/> <s:element minOccurs="0" maxOccurs="1" name="MODEL" type="s:string"/> <s:element minOccurs="0" maxOccurs="1" name="ASSET_NUMBER" type="s:str +ing"/> <s:element minOccurs="0" maxOccurs="1" name="BARCODE_NUMBER" type="s:s +tring"/> <s:element minOccurs="0" maxOccurs="1" name="SERIAL_NUMBER" type="s:st +ring"/> <s:element minOccurs="0" maxOccurs="1" name="BUILDING" type="s:string" +/> <s:element minOccurs="0" maxOccurs="1" name="FLOOR" type="s:string"/> <s:element minOccurs="0" maxOccurs="1" name="SPACE_ID" type="s:string" +/> <s:element minOccurs="0" maxOccurs="1" name="GRID_LOCATION" type="s:st +ring"/> </s:sequence> </s:complexType> <s:element name="RunLocatorResponse"> <s:complexType> <s:sequence> <s:element minOccurs="1" maxOccurs="10000" name="RunLocatorResult" typ +e="s0:LocatorResultInfo"/> </s:sequence> </s:complexType> </s:element> <s:complexType name="LocatorResultInfo"> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="DEVICE_NAME" type="s:stri +ng"/> <s:element minOccurs="0" maxOccurs="1" name="MANUFACTURER" type="s:str +ing"/> <s:element minOccurs="0" maxOccurs="1" name="MODEL" type="s:string"/> <s:element minOccurs="0" maxOccurs="1" name="ASSET_NUMBER" type="s:str +ing"/> <s:element minOccurs="0" maxOccurs="1" name="BARCODE_NUMBER" type="s:s +tring"/> <s:element minOccurs="0" maxOccurs="1" name="SERIAL_NUMBER" type="s:st +ring"/> <s:element minOccurs="0" maxOccurs="1" name="BUILDING" type="s:string" +/> <s:element minOccurs="0" maxOccurs="1" name="FLOOR" type="s:string"/> <s:element minOccurs="0" maxOccurs="1" name="SPACE_ID" type="s:string" +/> <s:element minOccurs="0" maxOccurs="1" name="GRID_LOCATION" type="s:st +ring"/> <s:element minOccurs="0" maxOccurs="1" name="RACK_NAME" type="s:string +"/> <s:element minOccurs="0" maxOccurs="1" name="RACK_MOUNT_SIDE" type="s: +string"/> <s:element minOccurs="0" maxOccurs="1" name="BOTTOM_RACK_UNIT" type="s +:double"/> <s:element minOccurs="0" maxOccurs="1" name="HEIGHT" type="s:double"/> </s:sequence> </s:complexType> </s:schema> </types> <message name="RunLocatorSoapIn"> <part name="parameters" element="s0:RunLocator"/> </message> <message name="RunLocatorSoapOut"> <part name="parameters" element="s0:RunLocatorResponse"/> </message> <portType name="RunLocatorSoap"> <operation name="RunLocator"> <documentation> This function provides the XML interface to create a form </documentation> <input message="s0:RunLocatorSoapIn"/> <output message="s0:RunLocatorSoapOut"/> </operation> </portType> <binding name="RunLocatorSoap" type="s0:RunLocatorSoap"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style=" +document"/> <operation name="RunLocator"> <soap:operation soapAction="http://tempuri.org/AWEService/API/WASAPI/R +unLocator" style="document"/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="RunLocator"> <port name="RunLocator" binding="s0:RunLocatorSoap"> <soap:address location="https://www.example.com/WAS/API/AWEService.asm +x?w_v=1&w_s=VISTA&w_o=LocateDevice"/> </port> </service> </definitions>

EDIT: I think a big part of what's tripping me up is the two separate element areas under the RunLocator element. The method requires "userIdentification" and "locatorSearchFieldsIdentification" separately.

This is the current iteration of what I'm attempting:

my $wsdl = 'https://www.example.com/VISTA/wsdl/LocateDevi +ce_RunLocator.wsdl'; my $lite = SOAP::Lite ->service($wsdl) ->ns('was'); my @params = (SOAP::Data->name(WAS_userName => 'MY_USER'), +SOAP::Data->name(WAS_password => 'MY_PASSWD'), SOAP::Data->name(DEVIC +E_NAME => 'MY_SERVER')); SOAP::Lite->import(+trace => 'all'); my $result = $lite->RunLocator(@params);

Here's the trace:

SOAP::Transport::HTTP::Client::new: () SOAP::Lite::call: () SOAP::Serializer::envelope: () SOAP::Serializer::envelope: RunLocator SOAP::Data=HASH(0x2063270) SOAP +::Data=HASH(0x2063150) SOAP::Data=HASH(0x1b2a2a0) SOAP::Data::new: () SOAP::Data::new: () SOAP::Data::new: () SOAP::Data::new: () SOAP::Data::new: () SOAP::Transport::HTTP::Client::send_receive: HTTP::Request=HASH(0x2046 +3b8) SOAP::Transport::HTTP::Client::send_receive: POST https://www.example. +com/WAS/API/AWEService.asmx?w_v=1&w_s=VISTA&w_o=LocateDevice HTTP/1.1 Accept: text/xml Accept: multipart/* Accept: application/soap Content-Length: 832 Content-Type: text/xml; charset=utf-8 SOAPAction: "http://tempuri.org/AWEService/API/WASAPI/RunLocator" <?xml version="1.0" encoding="UTF-8"?><soap:Envelope soap:encodingStyl +e="http://schemas.xmlsoap.org/soap/encoding/" xmlns:http="http://sche +mas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/ws +dl/mime/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:s0="http:/ +/tempuri.org/AWEService/API/WASAPI" xmlns:soap="http://schemas.xmlsoa +p.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/enco +ding/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns: +xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body><s0:RunLoc +ator><userIdentification xsi:nil="true" xsi:type="s0:UserIdentificati +onStructure" /><locatorSearchFieldsIdentification xsi:nil="true" xsi: +type="s0:LocatorSearchFieldsStructure" /><DEVICE_NAME xsi:type="xsd:s +tring">prodh20</DEVICE_NAME></s0:RunLocator></soap:Body></soap:Envelo +pe> SOAP::Transport::HTTP::Client::send_receive: HTTP::Response=HASH(0x203 +6400) SOAP::Transport::HTTP::Client::send_receive: HTTP/1.1 500 Internal Ser +ver Error Cache-Control: private,no-cache, no-store, must-revalidate Date: Sat, 20 May 2017 19:56:56 GMT Server: Microsoft-IIS/7.5 Content-Length: 837 Content-Type: text/xml; charset=utf-8 ... <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http: +//schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/20 +01/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">< +soap:Header><soap12:Upgrade xmlns:soap12="http://www.w3.org/2003/05/s +oap-envelope"><soap12:SupportedEnvelope qname="soap:Envelope" xmlns:s +oap="http://schemas.xmlsoap.org/soap/envelope/" /><soap12:SupportedEn +velope qname="soap12:Envelope" xmlns:soap12="http://www.w3.org/2003/0 +5/soap-envelope" /></soap12:Upgrade></soap:Header><soap:Body><soap:Fa +ult><faultcode>soap:VersionMismatch</faultcode><faultstring>Possible +SOAP version mismatch: Envelope namespace http://schemas.xmlsoap.org/ +wsdl/soap/ was unexpected. Expecting http://schemas.xmlsoap.org/soap/ +envelope/.</faultstring><detail /></soap:Fault></soap:Body></soap:Env +elope> SOAP::Deserializer::deserialize: () SOAP::Parser::decode: () SOAP::SOM::new: () SOAP::SOM::DESTROY: () SOAP::Data::DESTROY: () SOAP::Data::DESTROY: () SOAP::Lite::DESTROY: () SOAP::Deserializer::DESTROY: () SOAP::Parser::DESTROY: () SOAP::Transport::DESTROY: () SOAP::Transport::HTTP::Client::DESTROY: () SOAP::Serializer::DESTROY: () SOAP::Data::DESTROY: () SOAP::Data::DESTROY: () SOAP::Data::DESTROY: () SOAP::Data::DESTROY: () SOAP::Data::DESTROY: () SOAP::Data::DESTROY: () SOAP::Data::DESTROY: () SOAP::Data::DESTROY: ()

Yes, I see the version mismatch messages, but I'm more concerned about the generated envelope not having the correct structure.

SOLVED thanks to poj. Code is below, slightly adapted for public posting:

#!/usr/bin/perl use strict; use warnings; use SOAP::Lite; use v5.16; my $client = SOAP::Lite ->proxy('https://www.example.com/WAS/API/AWEService.asmx?ENDPOINT' +) ->on_action(sub { join '/', @_ }) ->ns('http://tempuri.org/AWEService/API/WASAPI','was'); my %auth_parms = ( WAS_userName => 'USER', WAS_password => 'PASSWORD', ); my %search_parms = ( DEVICE_NAME => 'SERVER', ); my @auth_data; for (keys %auth_parms){ my $data = SOAP::Data->name( $_ => $auth_parms{$_} )->prefix('was'); push @auth_data, SOAP::Data->type('data' => $data); } my @search_data; for (keys %search_parms){ my $data = SOAP::Data->name( $_ => $search_parms{$_} )->prefix('was'); push @search_data, SOAP::Data->type('data' => $data); } my $auth = SOAP::Data->name( "userIdentification" => \@auth_data )->prefix('was'); my $search = SOAP::Data->name( "locatorSearchFieldsIdentification" => \@search_data )->prefix('was'); my $header = SOAP::Data->type('xml' => ''); my $response = $client->call("RunLocator", SOAP::Header->type('data' => $header), SOAP::Data->type('data' => $auth), SOAP::Data->type('data' => $search) ); if ($response->valueof('//RunLocatorResult')) { my $serial = $response->valueof('//SERIAL_NUMBER'); my $model = join(' ', scalar $response->valueof('//MANUFACTURER'), scalar $response->valueof('//MODEL') ); my $location = join(' ', scalar $response->valueof('//BUILDING'), scalar $response->valueof('//FLOOR'), scalar $response->valueof('//SPACE_ID'), scalar $response->valueof('//GRID_LOCATION'), scalar $response->valueof('//RACK_NAME') ); return ($serial, $model, $location); }

In reply to Using SOAP::Lite with a WSDL by lahfordie

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



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (7)
As of 2024-03-28 19:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found