Loading ...
Sorry, an error occurred while loading the content.

2665Problem when passing array of hashes from SOAP::Lite to Java SOAPRMI

Expand Messages
  • Bruno Grossmann
    May 28, 2003
      I know that quite a few people have been discussing the issue of passing hashes from SOAP::Lite, but I have
      not been able to find an answer to my question, hence my posting.
      I have written a SOAP cgi script which performs search and returns an array of hashes as the results (Since I
      come from a directory background, I wanted to mimic the LDIF format when returning the data). Of course,
      my SOAP::Lite client nearly worked the first time around. However, things got more difficult when I started
      testing with Java. Below is the trace of SOAP query and response and my server scripts. I can also provide
      the Java code if needed. Any help is appreciated. Also, from a miore general point of view, I would like to know
      what strategies other people have adopted to deal with such cases. After all, if SOAP is going to be the
      transport of the future, I am sure that many languages will have to be able to exchange complex data

      Here is the trace:

      Logger $Revision: 1.19 $ $Date: 2003/04/06 00:04:04 $ (GMT) configured as 'soaprmi.trace'
      [ 12:13:11.224 main: soaprmi.trace.invoke.out soaprmi.soaprpc.MethodInvoker.java:308 sendRequest ] TRACE sending len=470:---
      <SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
      <m:get_dds xmlns:m='http://soapinterop.org/dds'>
      <get_dds xsi:type='xsd:string'>grossman</get_dds>

      [ 12:13:14.208 main: soaprmi.trace.invoke.in soaprmi.soaprpc.MethodInvoker.java:321 receiveResponse ] TRACE reading response to buffer
      [ 12:13:14.208 main: soaprmi.trace.invoke.in soaprmi.soaprpc.MethodInvoker.java:331 receiveResponse ] TRACE received: len=2377
      <?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:namesp2="http://xml.apache.org/xml-soap" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <namesp1:get_ddsResponse xmlns:namesp1="http://soapinterop.org/dds">
      <SOAP-ENC:Array SOAP-ENC:arrayType="namesp2:SOAPStruct[2]" xsi:type="SOAP-ENC:Array">
      <item xsi:type="namesp2:SOAPStruct">
      <country xsi:type="xsd:string">Canada</country>
      <mail xsi:type="xsd:string">dennis.grossman@...</mail>
      <roomnumber xsi:type="xsd:string">500/500</roomnumber>
      <postalcode xsi:type="xsd:string">S4P 4K8 </postalcode>
      <city xsi:type="xsd:string">Regina</city>
      <faxnumber xsi:type="xsd:string">(306) 780-7242</faxnumber>
      <name xsi:type="xsd:string">Grossman, Dennis</name>
      <telephonenumber xsi:type="xsd:string">(306) 780-5032</telephonenumber>
      <province xsi:type="xsd:string">Saskatchewan</province>
      <position xsi:type="xsd:string">Asset Manager</position>
      <streetaddress xsi:type="xsd:string">Sherwood Place, 1900 Albert Street, Suite 500</streetaddress>
      <item xsi:type="namesp2:SOAPStruct">
      <country xsi:type="xsd:string">Canada</country>
      <mail xsi:type="xsd:string">bruno.grossmann@...</mail>
      <roomnumber xsi:type="xsd:string">24R</roomnumber>
      <postalcode xsi:type="xsd:string">K1A 0S5 </postalcode>
      <city xsi:type="xsd:string">Hull</city>
      <faxnumber xsi:type="xsd:string">(819) 956-6476</faxnumber>
      <name xsi:type="xsd:string">Grossmann, Bruno</name>
      <telephonenumber xsi:type="xsd:string">(819) 956-1224</telephonenumber>
      <province xsi:type="xsd:string">Quebec</province>
      <position xsi:type="xsd:string">Consultant</position>
      <streetaddress xsi:type="xsd:string">Portage III, 2A1, 11 Laurier Street</streetaddress>

      SOAP exception; nested exception is:
      problem with xml-java mapping at line 1 and column 556 seen ...yType="namesp2:SOAPStruct[2]" xsi:type="SOAP-ENC:Array">... (parser state START_TAG); nested exception is:
      soaprmi.mapping.XmlMapException: no mapping for encodingStyle=http://schemas.xmlsoap.org/soap/encoding/ uri=http://xml.apache.org/xml-soap localName=SOAPStruct
      at soaprmi.mapping.XmlJavaMapping.queryTypeMap(XmlJavaMapping.java:391)
      at soaprmi.mapping.XmlJavaMapping.queryTypeMap(XmlJavaMapping.java:345)
      at soaprmi.soap.SoapDeserializeContextImpl.queryTypeMap(SoapDeserializeContextImpl.java:278)
      at soaprmi.soapenc.ArrayDeserializer.readObject(ArrayDeserializer.java:119)
      at soaprmi.soapenc.SoapEnc.readObject(SoapEnc.java:479)
      at soaprmi.soaprpc.MethodInvoker.receiveResponse(MethodInvoker.java:471)
      at soaprmi.soaprpc.HttpSocketSoapInvocationHandler.invokeTransport(HttpSocketSoapInvocationHandler.java:134)
      at soaprmi.soaprpc.SoapDynamicStub.invoke(SoapDynamicStub.java:118)
      at $Proxy0.get_dds(Unknown Source)
      at testc.main(testc.java:112)
      Exception in thread "main"

      Here are the two server scripts:

      use SOAP::Transport::HTTP;

      # specify path to My/Examples.pm here
      -> dispatch_to('/home/bruno/soap/','dds')
      -> handle;

      package dds;
      #These two lines allow this module to be used as a standalone module or as a subroutine
      #use strict;
      use vars qw/$filename/;
      (my $package,$filename,my $line)=caller;
      if (! $filename)
      my $call=shift;
      my $filter=shift;
      my $lang=shift;

      sub get_dds
      my @buf;
      my @res_dds;
      my @url;
      my $key=0;
      my $key2;
      my $point;
      my ($discard,$discard1,$discard2,$keep,$keep1,$keep2);
      my ($i,$j,$k);
      use HTTP::Headers;
      use HTTP::Request;
      use LWP::UserAgent;

      # Grab parameters from called subroutine
      (my $self,my $filter,my $lang)=@_;
      $lang="e" if ! defined $lang;
      $lang = lc($lang);
      if (($lang eq "e")||($lang eq "en")||($lang eq "english"))
      elsif (($lang eq "f")||($lang eq "fr")||($lang eq "francais")||($lang eq "français"))
      # URL for DDS
      # $www="directory.pwgsc.gc.ca";
      # Use IP to make it work on the lab side
      my $www="";
      # Transform it for the HTPP POST request
      my $http_filter = $filter;
      $http_filter =~ s/\,/\%2C/;
      $http_filter =~ s/\ /\+/;
      # Transform it for the regular expression match
      my $regexp_filter = $filter;
      $regexp_filter =~ s/\ +/\ <wbr> /;
      # Specify header for POST
      my $header = new HTTP::Headers
      'Referer' => "http://$www/dds/search.asp?$lang",
      'Connection' => 'Keep-Alive',
      'content_type' => 'application/x-www-form-urlencoded'

      # Formulate request
      my $req = new HTTP::Request('POST',

      # Create user agent
      my $ua = LWP::UserAgent->new;
      # Get POST operation result, put it in hash
      my $rep=$ua->request($req);
      # Split hash on newline
      (my @rep)=split(/\n/,${$rep}{'_content'});
      my $count=0;
      # Loop to grab URL for GET operation
      # On DDS Web site, even if there is only one match for the
      # filter specified, we still need to click another time to
      # get the detailed info
      # This loop over possible multiple occurences (e.g., Smith, John)
      for ($i=0;$i < scalar @rep; $i++)
      # Grab URL (very format specific, assumes anchor to be on
      # a single line)
      if ($rep[$i] =~ /<a href=\"frload.html\?pg/i)
      $point= $rep[$i];
      # If match filter, store
      if (($rep[$i] =~ /[ |\t]$regexp_filter/i)&&
      ($rep[$i] !~ /search results for/i)&&
      ($rep[$i] !~ /résultats pour/i))
      $url[$count] = $point;
      # Loop on stored URLs, perform GET operation for each
      for ($i=0;$i < scalar @url; $i++)
      my $dum=$url[$i];
      (my $dum0,$url[$i],my $dum1)=split(/"/,$dum);
      $url[$i] =~ s/&/&/g;
      my $header2 = new HTTP::Headers 'Referer' => "http://$www/dds/$url[$i]";
      $url[$i] =~ s/frload.html\?pg=//;
      $url[$i] =~ s/branch=\d+&//;
      $url[$i] =~ s/person\.asp&/person\.asp\?/;
      # print "$url[$i]\n";
      my $req2=HTTP::Request->new('GET',"http://$www/dds/$url[$i]",$header2);
      my $rep2=$ua->request($req2);
      # print "$i $url[$i] $rep2->content\n";
      # Now grab results in an orderly fashion
      (my @rep2)=split(/\n/,${$rep2}{'_content'});
      my $frame_num=0;
      my $line_num=0;
      my $col_num=0;
      for (my $j=0;$j < scalar @rep2; $j++)
      $rep2[$j] =~ s/\r+//g;
      if ($rep2[$j] =~ /<tr>/i)
      $col_num++ if ($rep2[$j] =~ /<td>/i);
      # print "$line_num $buf[$line_num]\n" if ($rep2[$j] =~ /<\/tr>/i);
      if ($rep2[$j] =~ /<\/tr>/i)
      if ($line_num == 1)
      # First and last name, position
      (my $firstname,my $lastname)=split(/<wbr>/i,$keep1);
      (my $position,$discard)=split(/<\/h3>/i,$keep2);
      $firstname =~ s/ +//g;
      $firstname =~ s/\t+//g;
      $lastname =~ s/ +//g;
      $lastname =~ s/\t+//g;
      $position =~ s/^ +//g;
      $position =~ s/ +$//g;
      $position =~ s/\t+//g;
      $res_dds[$key]{'name'}="$lastname, $firstname";
      elsif ($line_num == 3)
      # Telephone and room number
      ($discard,my $telephonenumber)=split(/<td.*?>/i,$keep1);
      ($discard,my $roomnumber)=split(/<td.*?>/i,$keep2);
      elsif ($line_num == 5)
      # Fax number
      ($discard,my $faxnumber)=split(/<td.*?>/i,$keep1);
      elsif ($line_num == 7)
      # email address
      ($discard,my $mail)=split(/<a HREF=.+?>/i,$keep1);
      elsif ($line_num == 9)
      # Address
      (my $streetaddress,my $cityprovince,my $country,my $postalcode)=split(/<br>/i,$keep1);
      (my $city,my $province)=split(/,/,$cityprovince);
      $streetaddress =~ s/\t+//g;
      $streetaddress =~ s/ +$//g;
      $streetaddress =~ s/^ +//g;
      $city =~ s/ +$//g;
      $city =~ s/^ +//g;
      $province =~ s/ +$//g;
      $province =~ s/^ +//g;
      $country =~ s/\t+//g;
      $country =~ s/ +$//g;
      $country =~ s/^ +//g;
      $postalcode =~ s/ +$//g;
      $postalcode =~ s/^ +//g;
      elsif ($line_num == 11)
      # Position in the organization
      ($discard1,my @branch)=split(/<LI>/i,$buf[$line_num]);
      for ($k=0;$k < scalar @branch;$k++)
      $branch[$k] =~ s/<.+?>//g;
      $branch[$k] =~ s/\t+//g;
      $branch[$k] =~ s/^ +//g;
      $branch[$k] =~ s/ +$//g;
      # Concatenate to end with one multivalued field ($ separated)
      # Remove unused separator
      chop $res_dds[$key]{'branch'};
      if (! $filename)
      for ($key=0;$key < scalar @res_dds; $key++)
      print "\n";
      foreach $key2 (keys %{$res_dds[$key]})
      print "$key2: $res_dds[$key]{$key2}\n";

      sub get_geds
      use Net::LDAP;
      my @res_ldap;
      my $i;

      (my $self,my $filter,my $lang)=@_;
      $lang="e" if ! defined $lang;
      $lang = lc($lang);
      if (($lang eq "e")||($lang eq "en")||($lang eq "english"))
      elsif (($lang eq "f")||($lang eq "fr")||($lang eq "francais")||($lang eq "français"))
      my $ldap=Net::LDAP->new("hera.srv.gc.ca") or return ("LDAP server not responding");
      my $mesg = $ldap->search (base => "o=gc,c=ca",filter => $filter);

      my $max = $mesg->count;
      for($i = 0 ; $i < $max ; $i++)
      my $entry = $mesg->entry($i);
      foreach my $attr ($entry->attributes)
      my $value=join('$',$entry->get_value($attr));
      next if (($attr =~ /$lang/i)||($value =~ /[^ -\x7E]/));
      print "$attr: $value\n" if (! $filename);
      # foreach my $value (@{$entry->get_value($attr, asref => 1)})
      # {
      # next if ($value =~ /[^ -\x7E]/);
      # print "$attr: ",$value,"\n";
      # }
      return (\@res_ldap);

      sub tr_filter
      (my $package,my $filename,my $line,my $sub,my $hasarg,my $wantarray)=caller(1);
      (my $filter)=@_;
      if ($sub eq "dds::get_geds")
      if ($filter !~ /,/)
      (my @filter)=split(/ +/,$filter);
      if (scalar @filter > 1)
      $filter="cn=\*$filter[0], $filter[1]\*";
      $filter =~ s/ +//g;
      (my @filter)=split(/,/,$filter);
      if (scalar @filter > 1)
      $filter="cn=\*$filter[0], $filter[1]\*";
      elsif ($sub eq "dds::get_dds")
      if ($filter !~ /,/)
      (my @filter)=split(/ +/,$filter);
      if (scalar @filter > 1)
      $filter="$filter[0], $filter[1]";
      $filter =~ s/ +//g;
      return ($filter);
      sub test
      my $return="Ca marche!";
      (my $self,my $input)=@_;
      $return="J'ai bien recu $input,".$return if (defined $input) ;

      Bruno Grossmann
      SSD - Federated Directory Infrastructure Services
      Place du Portage, Phase III - 2A1
      11 rue Laurier, Hull, Québec, Canada (K1A 0S5)
      Télephone: 819-956-1224 Télecopieur: 819-956-6476