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

3230Re: [soaplite] Soaplite server, Axis client, no deserializer for SoapStruct

Expand Messages
  • Scott Ellsworth
    Dec 12, 2003
    • 0 Attachment
      Byrne,

      Thanks much for the reply. I have two followup questions, that I hope
      are easy to answer.

      On Dec 12, 2003, at 8:53 AM, Byrne Reese wrote:

      > SOAP::Lite wants to (be default) use SOAP Encoding to encode perl data
      > structures - and this works remarkably poorly. It is always a good
      > idea to
      > encode complex types by hand.

      Ok - I have read the articles again, and they make more sense.

      Unfortunately, I have limited ability to change what is on the server
      side. I can change the SOAP implementer module, but not the routines
      under it. Right now, the soap implementer just dispatches to the end
      user routines with very little intervention.

      Before asking further questions, here is some code that may make this
      make more sense.

      Alodar::GBIB::SOAPUtils.pm, called by the mod_perl module on urls
      ending in gbib-soap. (It actually dispatches 22 routines, but I have
      deleted all but the three in my example. If I get those to work, I can
      get the others to work.)

      package Alodar::GBIB::SOAPUtils;

      require Exporter;

      use strict;
      use SOAP::Transport::HTTP;

      our @ISA = qw(Exporter);

      our @EXPORT_OK = qw(
      handler
      );

      sub handler {
      SOAP::Transport::HTTP::Apache -> dispatch_to(
      qw(
      Alodar::GBIB::ListUtils::get_public_lists
      Alodar::GBIB::UserUtils::get_id_for_username
      Alodar::GBIB::UserUtils::get_user_ids_by_name
      Alodar::GBIB::UserUtils::get_username_for_id
      )
      ) ->handler(@_)
      # ) ->handler(%args)
      }

      1;
      # $Id: SOAPUtils.pm,v 1.6 2003/11/12 23:18:07 scott Exp $
      # Local Variables:
      # mode: perl
      # End:

      Here is the implementation of get_user_ids_by_name. It returns a hash
      whose keys are usernames, and whose values are integer ids. Assume I
      cannot modify this, as it is used by other functions.

      sub get_user_ids_by_name {
      if ($#_ >= 0) {
      shift if $_[0] eq __PACKAGE__;
      }
      my %args = (
      config_name => '',
      @_, # push key-value pairs into args
      );
      my $config_name = $args{config_name};

      $config_name or die "Alodar::GBIB::UserUtils::get_user_ids_by_name:
      you must supply a configuration name";

      my $configs = get_configs($config_name);

      my $dbh = getdbh($$configs{configname}, '', '');

      my $sth = $dbh->prepare('SELECT id, username FROM users');

      $sth->execute() || die
      "Alodar::GBIB::UserUtils::get_user_ids_by_name: Error: $dbh->errstr";

      my %user_ids_by_name = ();
      while (my @row = $sth->fetchrow_array) {
      my ($id, $username) = @row;
      $user_ids_by_name{$username} = $id;
      }
      $sth->finish();
      $dbh->disconnect();

      return \%user_ids_by_name;
      }

      Note that it returns the hash by reference.

      So, what I seek is either some WSDL that would let Axis handle
      SOAP::Lite sends, or a way to add types to the above SOAPUtils
      dispatcher, without having to change get_user_ids_by_name. Are either
      of these reasonable? Use small words - I am new at Perl and SOAP, but
      have read many perldocs, manpages, and W3C specs.

      Here is what I have as WSDL - it is incomplete, but does work for
      anything not returning a Map.

      <?xml version="1.0" encoding="utf-8"?>
      <definitions name="GBIB"
      targetNamespace="http://feature.alodar.com/Alodar/GBIB/"
      xmlns:schema="http://www.w3.org/2001/XMLSchema"
      xmlns:tns="http://feature.alodar.com/Alodar/GBIB/"
      xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
      xmlns:xml-soap="http://xml.apache.org/xml-soap"
      xmlns="http://schemas.xmlsoap.org/wsdl/"
      >

      <types>
      <schema
      xmlns="http://www.w3.org/2001/XMLSchema"
      targetNamespace="http://feature.alodar.com/Alodar/GBIB/"
      >
      <complexType name="idNameMap">
      <element name="elementData" type="string" />
      <element name="elementCount" type="int" />
      </complexType>
      <complexType name="SOAPStruct">
      <all>
      <element name="varString" type="string"/>
      <element name="varInt" type="int"/>
      <element name="varFloat" type="float"/>
      </all>
      </complexType>
      </schema>
      </types>

      <message name="config_nameRequest">
      <part name="arg1Name" type="schema:string" />
      <part name="arg1Value" type="schema:string" />
      </message>
      <message name="stringStringRequest">
      <part name="arg1Name" type="schema:string" />
      <part name="arg1Value" type="schema:string" />
      <part name="arg2Name" type="schema:string" />
      <part name="arg2Value" type="schema:string" />
      </message>
      <message name="stringIntRequest">
      <part name="arg1Name" type="schema:string" />
      <part name="arg1Value" type="schema:string" />
      <part name="arg2Name" type="schema:string" />
      <part name="arg2Value" type="schema:int" />
      </message>
      <message name="idNameMapResponse">
      <!-- part name="idNameMapReturnValue" type="xml-soap:Map" / -->
      <part name="idNameMapReturnValue" type="tns:idNameMap" />
      </message>
      <message name="stringResponse">
      <part name="stringReturnValue" type="schema:string" />
      </message>
      <message name="intResponse">
      <part name="stringReturnValue" type="schema:int" />
      </message>
      <message name="get_public_listsResponse">
      <part name="get_public_listsReturnValue" type="schema:anyType" />
      </message>

      <porttype name="UserUtilsPort">
      <!-- ports are analogous to method calls. SR says analogous to
      library/module/class -->
      <!-- name must match some binding's type -->
      <operation name="get_user_ids_by_name">
      <input message="tns:config_nameRequest" />
      <output message="tns:idNameMapResponse" />
      </operation>
      <operation name="get_id_for_username">
      <input message="tns:stringStringRequest" />
      <output message="tns:intResponse" />
      </operation>
      <operation name="get_username_for_id">
      <input message="tns:stringIntRequest" />
      <output message="tns:stringResponse" />
      </operation>
      </porttype>

      <porttype name="ListUtilsPort">
      <!-- ports are analogous to method calls. -->
      <!-- name must match some binding's type -->
      <operation name="get_public_lists">
      <input message="tns:config_nameRequest" />
      <output message="tns:stringResponse" />
      </operation>
      </porttype>

      <binding name="UserUtils" type="tns:UserUtilsPort">
      <!-- binding elements tell code how to move data. We are using SOAP
      -->
      <!-- These are analagous to classes -->
      <!-- type matches name of some port -->
      <soap:binding style="rpc"
      transport="http://schemas.xmlsoap.org/soap/http" />
      <operation name="get_id_for_username">
      <soap:operation style="rpc" />
      <input>
      <soap:body use="encoded"
      namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
      <soap:body use="encoded"
      namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
      </operation>
      <operation name="get_user_ids_by_name">
      <soap:operation style="rpc" />
      <input>
      <soap:body use="encoded"
      namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
      <soap:body use="encoded"
      namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
      </operation>
      <operation name="get_username_for_id">
      <soap:operation style="rpc" />
      <input>
      <soap:body use="encoded"
      namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
      <soap:body use="encoded"
      namespace="http://feature.alodar.com/Alodar/GBIB/UserUtils"
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
      </operation>
      </binding>

      <binding name="ListUtils" type="tns:ListUtilsPort">
      <!-- binding elements tell code how to move data. We are using SOAP
      -->
      <!-- These are analagous to classes -->
      <!-- type matches name of some port -->
      <soap:binding style="rpc"
      transport="http://schemas.xmlsoap.org/soap/http" />
      <operation name="get_public_lists">
      <soap:operation style="rpc" />
      <input>
      <soap:body use="encoded"
      namespace="http://feature.alodar.com/Alodar/GBIB/ListUtils"
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
      <soap:body use="encoded"
      namespace="http://feature.alodar.com/Alodar/GBIB/ListUtils"
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
      </operation>
      </binding>

      <service name="GBIBService">
      <!-- service tells us what bindings to use. These give actual
      machines that implement the protocol. -->
      <!-- document>
      For a complete description of this service, go to the following URL:
      <a href="http://feature.alodar.com/">
      http://feature.alodar.com/
      </a>
      </document -->
      <port name="UserUtils" binding="tns:UserUtils">
      <soap:address location="http://feature.alodar.com/gbib-soap" />
      </port>
      <port name="ListUtils" binding="tns:ListUtils">
      <soap:address location="http://feature.alodar.com/gbib-soap" />
      </port>
      </service>
      </definitions>

      I may well be missing something due to lack of experience - please let
      me know if this is so.

      > It is a pain - I think everyone on this group will agree with me there.
      > The good news is that wsdl2perl will be making its way to market
      > relatively soon (January or February timeframe) - which will make
      > creating
      > these structures substantially easier.

      I am not sure this will help - does it actually take a WSDL file, and
      produce a perl dispatch module that calls underlying routines?

      > For the time being it is a relatively manual process. Here are some
      > articles that are routinely referenced that will help you compose
      > complex
      > types using SOAP::Lite:

      Thank you. I have read them again, and I think they would apply if I
      were able to rewrite the underlying Perl code. I cannot, really, save
      the SOAPUtils module that gets called directly by apache's mod_perl.

      Scott
      >>
      >>
      >>
      >>
      >> Hi, all.
      >>
      >> I am having a problem, and I have not been able to solve it. I have
      >> read
      >> the docs
      >> extensively, but I am a perl newbie, and thus probably missed some
      >> important stuff.
      >>
      >> I have a server running SOAP::Lite, and it is working well. I can
      >> call my
      >> methods from
      >> a SOAP::Lite client using either the direct call, or via a hand
      >> crafted
      >> WSDL file, and they
      >> work great! In general, they all take a hash containing a config
      >> name,
      >> and perhaps
      >> other stuff. They return hashrefs, integers, or strings. The one I
      >> am
      >> trying to get to
      >> work first takes just configname =< $configname and returns a hashref
      >> of
      >> names
      >> keyed by values.
      >>
      >> When I try to use Axis either directly or with my hand generated wsdl
      >> file, it dies,
      >> complaining that it cannot find an unserializer for a SOAPStruct. (I
      >> would have been
      >> willing to accept a map, myself.
      >>
      >> I would rather do my calls using the WSDL file, so here is the one I
      >> hand
      >> crafted. The
      >> method we want to call is get_user_ids_by_name:
      >>
      >>> ?xml version="1.0" encoding="utf-8"?definitions
      >>> name="GBIB"
      >> targetNamespace="http://feature.alodar.com/Alodar/GBIB/"
      >> xmlns:schema="http://www.w3.org/2001/XMLSchema"
      >> xmlns:tns="http://feature.alodar.com/Alodar/GBIB/"
      >> xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
      >> xmlns="http://schemas.xmlsoap.org/wsdl/"
      >> types!-- I could use the following by defining the type returned
      >> from a
      >> part of a message as
      >>> message name="ListOfUsers"part
      >> name="models"
      >> type="tns:Vector"/messagexsd:schema
      >> targetNamespace="http://feature.alodar.com/Alodar/GBIB/"
      >> xmlns="http://www.w3.org/2001/XMLSchema/"schema:complexType
      >> name="Vector"xsd:element name="elementData"
      >> type="schema:String" /<
      >>> xsd:element name="elementCount"
      >> type="schema:int" /<
      >>> /schema:complexType/xsd:schema
      >>
      >>
      >>
      >>
      >> To unsubscribe from this group, send an email to:
      >> soaplite-unsubscribe@yahoogroups.com
      >>
      >>
      >>
      >>
      >>
      >> Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service.
      >>
      >>
      >>
      >>
      >>
      >
      >
      > ^byrne :/
      >
      > ------------------------ Yahoo! Groups Sponsor
      > ---------------------~-->
      > Buy Ink Cartridges or Refill Kits for your HP, Epson, Canon or Lexmark
      > Printer at MyInks.com. Free s/h on orders $50 or more to the US &
      > Canada.
      > http://www.c1tracking.com/l.asp?cid=5511
      > http://us.click.yahoo.com/mOAaAA/3exGAA/qnsNAA/W6uqlB/TM
      > ---------------------------------------------------------------------
      > ~->
      >
      > To unsubscribe from this group, send an email to:
      > soaplite-unsubscribe@yahoogroups.com
      >
      >
      >
      > Your use of Yahoo! Groups is subject to
      > http://docs.yahoo.com/info/terms/
      >
      >
    • Show all 6 messages in this topic