Thread

Posted on Tue Apr 29 13:30:15 2008 by oly
Single element arrays not passed from client to server
Hello,

Since I updated SOAP::WSDL to 2.0 on the client side, and adapted my clients to work with it, the following problem appeared:

Some parameters I send to the server are lists of strings. As long as there are at least two elements in the list, all elements are passed to the server. But if there is only one element in the list, it is not passed to the server.

Our wsdl can be found here: http://rsat.bigre.ulb.ac.be/rsat/web_services/RSATWS.wsdl

Here is a minimalist client which is working with the "old" SOAP::WSDL:

#!/usr/bin/perl -w # retrieve-seq_client_soap-wsdl.pl - Client retrieve-seq using the SOAP::WSDL module ################################################################ ## ## This script runs a simple demo of the web service interface to the ## RSAT tool retrieve-seq. It sends a request to the server for ## obtaining the start codon of one E.coli gene. ## ################################################################ use strict; use SOAP::WSDL; ## WSDL location my $server = 'http://rsat.scmbb.ulb.ac.be/rsat/web_services'; my $WSDL = $server.'/RSATWS.wsdl'; my $proxy = $server.'/RSATWS.cgi'; ## Service call my $soap=SOAP::WSDL->new(wsdl => $WSDL)->proxy($proxy); $soap->wsdlinit; ## Retrieve-seq parameters my $organism = 'Escherichia_coli_K12'; ## Name of the query organism my @query_genes = ("metA"); ## List of query genes my $from = 0; ## Start position of the sequence my $to = 2; ## End position of the sequence warn "\nThis demo script retrieves the start codons for a set of query genes\n\n"; my %args = ( 'organism' => $organism, 'query' => \@query_genes, 'from' => $from, 'to' => $to ); ## Send the request to the server print "Sending request to the server $server\n"; my $som = $soap->call('retrieve_seq' => 'request' => \%args); ## Get the result if ($som->fault){ ## Report error if any printf "A fault (%s) occured: %s\n", $som->faultcode, $som->faultstring; } else { my $results_ref = $som->result; ## A reference to the result hash table my %results = %$results_ref; ## Dereference the result hash table ## Report the remote command my $command = $results{'command'}; print "Command used on the server: ".$command, "\n"; ## Report the result my $server_file = $results{'server'}; my $result = $results{'client'}; print "Result file on the server: ".$server_file, "\n"; print "Retrieved sequence(s): \n".$result; }

Here is a minimalist client working with SOAP::WSDL 2.0:

#!/usr/bin/perl -w # retrieve-seq_client_soap-wsdl.pl - Client retrieve-seq using the SOAP::WSDL module ################################################################ ## ## This script runs a simple demo of the web service inerface to the ## RSAT tool retrieve-seq. It sends a request to the server for ## obtaining the start codons of 3 E.coli genes. ## ################################################################ use strict; use SOAP::WSDL; use lib 'RSATWS'; use MyInterfaces::RSATWebServices::RSATWSPortType; warn "\nThis demo script retrieves the start codons for a set of query genes\n\n"; ## WSDL location my $server = 'http://rsat.scmbb.ulb.ac.be/rsat/web_services'; ## Service call my $soap=MyInterfaces::RSATWebServices::RSATWSPortType->new(); ## Retrieve-seq parameters my $organism = 'Escherichia_coli_K12'; ## Name of the query organism my @gene = ("metA", "metB"); ## List of query genes my $from = 0; ## Start position of the sequence my $to = 2; ## End position of the sequence my %args = ( 'organism' => $organism, 'query' => \@gene, ## An array in a hash has to be referenced (always?) 'from' => $from, 'to' => $to ); ## Send the request to the server print "Sending request to the server $server\n"; my $som = $soap->retrieve_seq({'request' => \%args}); ## Get the result unless ($som) { #if ($som->get_faultstring()){ printf "A fault (%s) occured: %s\n", $som->get_faultcode(), $som->get_faultstring(); } else { my $results = $som->get_response(); ## Report the remote command my $command = $results -> get_command(); print "Command used on the server: ".$command, "\n"; ## Report the result my $server_file = $results -> get_server(); my $result = $results -> get_client(); print "Result file on the server: ".$server_file."\n"; print "Retrieved sequence(s): \n".$result; }

If I replace the line:

my @gene = ("metA", "metB"); ## List of query genes

by

my @gene = ("metA"); ## List of query genes

The client does not work anymore.

Is it something I do wrong? Any help would be welcome...

Thanks,

Olivier

Direct Responses: 7793 | 7795 | Write a response
Posted on Tue Apr 29 21:32:09 2008 by mkutter in response to 7790
Re: Single element arrays not passed from client to server
Hi Olivier,
what's the exact version you are using? I remember having seen this error in one of the pre-releases - maybe it has survived somewhere.

Martin
Direct Responses: 7794 | Write a response
Posted on Tue Apr 29 21:37:47 2008 by oly in response to 7793
Re: Single element arrays not passed from client to server
Hi Martin, Thanks for your quick answer! It is 2.00.01. It's the one I get from cpan (command line). Olivier
Write a response
Posted on Tue Apr 29 23:15:31 2008 by mkutter in response to 7790
Re: Single element arrays not passed from client to server
Hi Olivier,

this is a rather weird error. It's actually an error in the server, which has been compensated by an error in the 1.2x client.

The 1.27 client actually sends over the data in rpc/encoded form (try adding "use SOAP::Lite +trace;" at top - you'll have to remove the "use strict" for this to work). You'll see the data passed as something like
<query soapenc:arrayType="xsd:string[1]" xsi:type="xsd:string"> <item xsi:type="xsd:string">metA</item> </query>

This is actually wrong, as the interface is document/literal, and query is defined to be a string with multiple occurances allowed, not a SOAP array type. However, SOAP::Lite (which is used behind the scenes in the 1.2x SOAP::WSDL) uses rpc/encoded with arraytype encodings as a default because your script passes a list ref as parameter.

If you add the line
$soap->autotype(0);
to the "old" client just below the wsdlinit() call, you'll see something like this:
<request> <organism>Escherichia_coli_K12</organism> <query>metA</query> <from>0</from> <to>2</to> </request>


SOAP::WSDL 2.00.01 issues the same request. This request snippet is correct - query is defined as a string type with one or multiple occurances, so a single query string is perfectly OK.
However, the server does not seem to recognize a single string as a list, and thus treats it as empty query. If the server is in perl and under your command, something like below could help at an appropriate place:
$query = [ $query ] if not ref $query eq 'ARRAY';


As a workaround, you can also just add a undef element to the query list, so that it always has at least two elements. This adds a -q '' to the reported server query - I don't know whether it does any harm.

I hope this helps,

Martin
Direct Responses: 7798 | Write a response
Posted on Wed Apr 30 16:43:57 2008 by oly in response to 7795
Re: Single element arrays not passed from client to server
Thanks! Your server side solution works very well.

Olivier
Write a response