Posted on 2008-04-23 01:21:25-07 by rhumbliner

I'm sorry, but after my interface call, I just don't know how to retrieve the returned data. my code is as follows:

my $response = $interface->fsPublic_SQL( { # MyTypes::fsPublic_SQLInput
    QryIn =>  {
        StrQuery =>  $q,
        option =>  'XML',
        keepRowHeader =>  'false',
        },
    },,
);
die $response if not $response;

print Dumper($response);

the output of the print is:

$response = bless( do{\(my $o = 19)}, 'MyElements::fsPublic_SQLOutput' );

the docs for MyElements::fsPublic_SQLOutput follows:

[~] perldoc MyElements::fsPublic_SQLOutput

DESCRIPTION
   Perl data type class for the XML Schema defined element fsPublic_SQLOutput from the namespace http://infraweb-dev.fs.usda.gov/fs_public.Services.

METHODS
       new

        my $element = MyElements::fsPublic_SQLOutput->new($data);

       Constructor. The following data structure may be passed to new():

        { # MyTypes::fsPublic_SQLOutput
          QryResult =>  { # MyTypes::QryResult
            StrHTML =>  $some_value, # string
            StrCsv =>  $some_value, # string
            StrXML =>  $some_value, # string
          },
        },

AUTHOR
       Generated by SOAP::WSDL

i'm stumped as to how to recover the output.

thanks for your patience, tom

Posted on 2008-04-23 11:18:49-07 by mkutter in response to 7724

Use the $obj->get_FOO methods. Just try a name of your choice, and it'll tell you what names are there.

If you need all as a hash ref, you can just use $obj->as_hash_ref()

Martin

Posted on 2008-04-23 15:17:32-07 by rhumbliner in response to 7727

i'm sorry. i must be really obtuse. i've read every line of code generated by wsdl2perl and studied the pod's. i just can't figure out which $obj you're referring to. the main pod shows only 2 objects: $interface and $response.

[~] perldoc MyInterfaces::WSfsPublicQuery::Services_WSfsPublicQuery_Port

NAME
  MyInterfaces::WSfsPublicQuery::Services_WSfsPublicQuery_Port - SOAP Interface for the
  WSfsPublicQuery Web Service

SYNOPSIS
  use MyInterfaces::WSfsPublicQuery::Services_WSfsPublicQuery_Port;
  my $interface = MyInterfaces::WSfsPublicQuery::Services_WSfsPublicQuery_Port->new();

  my $response;
  $response = $interface->fsPublic_SQL();

DESCRIPTION
  SOAP Interface for the WSfsPublicQuery web service located at
  http://infrawebdev.fs.usda.gov:5556/ws/fs_public.webService:WSfsPublicQuery.

but when i access $response->get_all() no methods are listed:

Can't locate object method "get_all" via package "MyElements::fsPublic_SQLOutput".
Valid methods are:
 at /usr/lib64/perl5/site_perl/5.8.8/SOAP/WSDL/XSD/Typelib/ComplexType.pm line 42

if i dump $response it tells me i've got the object i think it want. the code print Dumper($response); tells me i've got an object of type fsPublic_SQLOutput but there are no methods to access this object:

$response = bless( do{\(my $o = 19)}, 'MyElements::fsPublic_SQLOutput' );

i'm pretty certain the data is being returned from the server, because if i replace the simple hash in the fsPublic_SQL() call with a MyTypes::fsPublic_SQLInput object the call generates a fault and dumps the entire dataset i'm expecting.

i'm sorry to be a pain, but i'm at a loss to figure this out.

thanks, tom

Posted on 2008-04-23 17:06:05-07 by mkutter in response to 7730

Try $response->_DUMP to get the content of the output object.

You can also look up the class' doc: "perldoc MyElements::fsPublic_SQLOutput" Maybe there just is no content, or it has text content which you can access via ->value();

If there's nothing, but should be, try passing the option "outputxml => 1" to the constructor of the interface class - it should return XML then instead of a response object.

Martin

Posted on 2008-04-23 17:37:52-07 by rhumbliner in response to 7733

the output of `print "_DUMP: ",$response-<_DUMP();` is:

_DUMP: {
  'MyTypes::fsPublic_SQLOutput' => {
                     'QryResult' => bless( do{\(my $o = 20)}, 'MyTypes::QryResult' )
                                   }
};

the output of perldoc MyElements::fsPublic_SQLOutput is:

NAME
       MyElements::fsPublic_SQLOutput

DESCRIPTION
      Perl data type class for the XML Schema defined element fsPublic_SQLOutput from the namespace http://infraweb-dev.fs.usda.gov/fs_public.Services.

METHODS
       new

        my $element = MyElements::fsPublic_SQLOutput->new($data);

       Constructor. The following data structure may be passed to new():

        { # MyTypes::fsPublic_SQLOutput
          QryResult =>  { # MyTypes::QryResult
            StrHTML =>  $some_value, # string
            StrCsv =>  $some_value, # string
            StrXML =>  $some_value, # string
          },
        },

AUTHOR
       Generated by SOAP::WSDL

which, incidently, puzzles me because why would i want a method to create something that i am expecting as output. shouldn't the pod describe methods to retrieve data from the object?

passing "{outputxml =>1}" as an option to the interface constructor produces xml with the dataset i'm expecting:

$response = '<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
</SOAP-ENV:Header><SOAP-ENV:Body>
<ser-root:fsPublic_SQLOutput
xmlns:ser-root="http://infrawebdev.fs.usda.gov/fs_public.Services"><QryResult>
<StrHTML></StrHTML>
<StrCsv></StrCsv>
<StrXML>
<qryResults>
  <rows>
    <ID>04</ID>
    <NAME>R4, INTERMOUNTAIN REGION</NAME>
  </rows>
... snip ...
</qryResults></StrXML></QryResult></ser-root:fsPublic_SQLOutput></SOAP-ENV:Body>
</SOAP-ENV:Envelope>

thanks for walking me thru this, tom

Posted on 2008-04-23 23:50:55-07 by noah in response to 7734

You've already got your response object; in the example from your first post it's '$response'. From this you've got two primary options for mucking with the data;

1) As martin said, call $response->as_hash_ref() which will return a traditional hash reference with which you can work;

2) use the get_-prefixed called your $response object has available. To see which calls it exposes, examine the full error text returned when you call $response->get_nosuchmethod(). Each get_-prefixed call returns an object which references the corresponding tag in the SOAP response. Once you figure out what the first call is, working your way down the tree is just a matter of examining the objects returned from get_(whatever) with _DUMP(). It's a bit hairy the first time through, especially if you're not familiar with how Class::Std(::Fast)? works, but it makes sense.

Noah

Posted on 2008-04-24 03:04:20-07 by rhumbliner in response to 7741

Well i certainly agree with the "hairy" part. ;-)

The problem i'm running into is that i *know* data is coming back because when i create the interface object with {outputxml => 1} i see the data i'm expecting. But when i create $interface normally, then $response->as_hash_ref() returns an empty hash. and $response->get_foo() doesn't return a list of valid calls so i'm stuck there -- i don't have any idea of what methods are available to me. and $response->_DUMP() returns:

{
 'MyTypes::fsPublic_SQLOutput' => {
  'QryResult' => bless( do{\(my $o = 20)}, 'MyTypes::QryResult' )
 }
};

and this still gives me no hints of any methods to use on these objects.

if it was as simple as following objects and their methods down a tree i wouldn't be stuck like this. :-(

is it possible that something is lacking the the wsdl definition? i find it hard to believe that getting a list of valid methods is so difficult.

still grateful for your help,

tom

Posted on 2008-04-25 08:30:39-07 by mkutter in response to 7745

Hi Tom,

actually, it is as simple as following methods down a tree, but you probably just got confused by not seeing anything reasonable in the Data::Dumper output. SOAP::WSDL uses Inside-Out objects, which have several nice features like a memory overhead proportional to the number of class properties, not to the number of objects created (like hash-based objects). However, they're a bit different: They don't show their values in Dumper output, and the _DUMP output is a bit different to read.

$response->get_QryResult();

Should give you the first level response object. And - if nothing has gone wrong - calling any get_FOO method on a object should die with a message like

Can't locate object method "get_FOO" via package "MyTypes::testComplexTypeAll".
Valid methods are: get_Test_2, set_Test_2, get_Test_1, set_Test_1
 at lib/SOAP/WSDL/XSD/Typelib/ComplexType.pm line 52
     SOAP::WSDL::XSD::Typelib::ComplexType::AUTOMETHOD('MyTypes::testComplexTypeAll=SCALAR(0x85bacb4)', 140225716)
       called at /usr/local/share/perl/5.8.8/Class/Std.pm line 546
     Class::Std::AUTOLOAD('MyTypes::testComplexTypeAll=SCALAR(0x85bacb4)')
       called at t/SOAP/WSDL/Generator/XSD_dot_names.t line 106

The stuff listed in "Valid methods" should give you a hint what to call.

You can also find the list of properties in the pod of the generated classes - the section should read something like this:

 PROPERTIES

The following properties may be accessed using get_PROPERTY / set_PROPERTY
methods:

  * Test_1
  * Test_2

However, you might also have found a bug in SOAP::WSDL, triggering incomplede code generation. But this is - unfortunately - something I cannot tell without examining the WSDL.

Martin

Posted on 2008-04-25 19:55:16-07 by rhumbliner in response to 7764

Now we're getting somewhere! :-) i admit i know next to nothing about Class::Std so I guess I need to read up on that. as i pointed out earlier, calling get_FOO() never returns a list of valid methods, so your example:

Can't locate object method "get_FOO" via package "MyTypes::testComplexTypeAll". Valid methods are: get_Test_2, set_Test_2, get_Test_1, set_Test_1

doesn't apply to me. all i get is a null list:

Can't locate object method "get_FOO" via package "MyTypes::testComplexTypeAll". Valid methods are:

whether this is a bug in SOAP::WSDL or the wsdl i'm using is beyond my capabilities, but i'm happy to let you analyze the wsdl. it's only 79 lines long.

anway, i don't know how you figured out to try the call get_QryResult() but that started me down the path. $response gives me a QryResult object which gives me a StrXML object which gives me a SOAP::WSDL::XSD::Typelib::Builtin::string (i realize QryResult and StrXML are unique to my wsdl). i then just print the string.

so, basically, i think i'm up and running. thanks so much for your help. Drinks are on me next time you're in vegas.

tom

(This article is based on a thread on the CPAN::Forum.)