Just a word of warning.  Hash tables are not a standard interop type.  You will loose 
compatibility between SOAP implementations.  I suggest you use an array of Java Beans 
with key/value pair concept.

Good luck,
Rick Kellogg
> Have you tried using the built-in HashMap type provided by apachesoap:
> 
> 
> Types definition:
> <schema targetNamespace="http://xml.apache.org/xml-soap";
> xmlns="http://www.w3.org/2001/XMLSchema";>
>   <import namespace="http://schemas.xmlsoap.org/soap/encoding/"; /> 
>   <complexType name="mapItem">
>    <sequence>
>     <element name="key" nillable="true" type="xsd:string" /> 
>     <element name="value" nillable="true" type="xsd:string" /> 
>    </sequence>
>   </complexType>
>   <complexType name="Map">
>    <sequence>
>     <element maxOccurs="unbounded" minOccurs="0" name="item"
> type="apachesoap:mapItem" /> 
>    </sequence>
>   </complexType>
> </schema>
> 
> Message definition:
> <wsdl:message name="authorizeToAuctionResponse">
>   <wsdl:part name="authorizeToAuctionReturn" type="apachesoap:Map" /> 
> </wsdl:message>
> 
> Works like a charm from SOAP::Lite!
> 
> -----Original Message-----
> From: Scott Ellsworth [mailto:[EMAIL PROTECTED] 
> Sent: Friday, December 12, 2003 2:55 PM
> To: [EMAIL PROTECTED]
> Subject: Proper WSDL allowing Axis to interpret a SOAP::Lite hash ref
> 
> 
> Hi, all.
> 
> I have searched the archives, but have not gotten quite enough of a  
> clue to solve the problem I face.  I wish to use Java to get the  
> results from a call to a SOAP server running Perl SOAP::Lite.  The  
> function returns a hash ref, encoded as SOAP::Lite encodes.  (raw soap  
> call/return below.)
> 
> I apologize for the long message, but I have found that God is in the  
> details in this space, and if it is just a simple typo in some routine,  
> the real source is required.
> 
> The server is running SOAP::Lite 0.55.  It is sending back a hashref,  
> and I have not been able to create the proper WSDL to see it, possibly  
> because of how SOAP::Lite is sending back that hashref.  I can handle  
> simple types like ints and strings, but this is not working.
> 
> I am using stubs created by wsdl2java, so clearly I need to express  
> this soap-struct in my WSDL, but I do not seem to be able to create the  
> proper type in the WSDL, or at least, it is not being used.
> 
> I cannot really change the underlying routines on the server, as they  
> are used for many things, but I can modify the dispatch function called  
> by mod_perl.  I have attached it at the end.
> 
> The request:
> 
> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
> <!--
>    URL: http://feature.alodar.com/gbib-soap/
>    -->
> <soap:Envelope
>            xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/";
>            soap:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/";
>            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
>            xmlns:xsd="http://www.w3.org/2001/XMLSchema";>
>    <soap:Body>
>      <s0:get_user_ids_by_name  
> xmlns:s0="http://feature.alodar.com/Alodar/GBIB/UserUtils";>
>        <s0:arg1Name>config_name</s0:arg1Name>
>        <s0:arg1Value>feature</s0:arg1Value>
>      </s0:get_user_ids_by_name>
>    </soap:Body>
> </soap:Envelope>
> 
> The response:
> 
> <?xml version="1.0" encoding="UTF-8"?>
> <soap-env:envelope  
> xmlns:xsi="http://www.w3.org/1999/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/1999/XMLSchema";  
> xmlns:namesp2="http://xml.apache.org/xml-soap";  
> soap-env:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/";>
>       <soap-env:body>
>               <namesp1:get_user_ids_by_nameresponse  
> xmlns:namesp1="http://feature.alodar.com/Alodar/GBIB/UserUtils";>
>                       <s-gensym3 xsi:type="namesp2:SOAPStruct">
>                               <admin xsi:type="xsd:int">
>                                       1
>                               </admin>
>                               <guest xsi:type="xsd:int">
>                                       2
>                               </guest>
>                       </s-gensym3>
>               </namesp1:get_user_ids_by_nameresponse>
>       </soap-env:body>
> </soap-env:envelope>
> 
> my WSDL:
> 
> <?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>
>        <!-- 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">
>             </message>
>        <xsd: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>
>        -->
>        <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"/>
>             </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>
> 
> The java code:
> 
>     public void callFeatureStub() {
>               try{
>                       String endpoint =
> "http://feature.alodar.com/gbib-soap/";;
> 
>          UserUtilsPort userUtilsPort = new  
> GBIBServiceLocator().getUserUtils(new URL(endpoint));
>          ((UserUtilsStub)userUtilsPort).setTimeout(60000);
>          ListUtilsPort listUtilsPort = new  
> GBIBServiceLocator().getListUtils(new URL(endpoint));
>          ((ListUtilsStub)listUtilsPort).setTimeout(60000);
> 
> // works great!
> 
>           int  
> get_id_for_usernameResult=userUtilsPort.get_id_for_username("config_name 
> ", config_name, "username", "admin");
>                       printResult("get_id_for_username",
> get_id_for_usernameResult);
> 
> //works great!
> 
>           String  
> get_username_for_idResult=userUtilsPort.get_username_for_id("config_name 
> ", config_name, "user_id", 1);
>                       printResult("get_username_for_id",
> get_username_for_idResult);
> 
> // throws exception
>                       Object get_user_ids_by_nameResult =  
> userUtilsPort.get_user_ids_by_name("config_name", config_name);
>                       printResult("get_user_ids_by_name",
> get_user_ids_by_nameResult);
> 
>         } catch (Exception e) {
>             System.err.println("Error: "+e.toString());
>         }
>     }
> 
> The dispatcher is very simple:
> 
> 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(@_)
> 
> I can add more things to this, as long as they can go here.
> 
> The exception is:
> 
>       [java] Result of get_id_for_username was type int, value 1
>       [java] Result of get_username_for_id was type java.lang.String,  
> value admin
>       [java] - Exception:
>       [java] org.xml.sax.SAXException: Deserializing parameter  
> 's-gensym39':  could not find deserializer for type  
> {http://xml.apache.org/xml-soap}SOAPStruct
>       [java]     at  
> org.apache.axis.message.RPCHandler.onStartChild(RPCHandler.java:302)
>       [java] Error: org.xml.sax.SAXException: Deserializing parameter  
> 's-gensym39':  could not find deserializer for type  
> {http://xml.apache.org/xml-soap}SOAPStruct
>       [java]     at  
> org.apache.axis.encoding.DeserializationContextImpl.startElement(Deseria 
> lizationContextImpl.java:963)
>       [java]     at  
> org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java: 
> 198)
>       [java]     at  
> org.apache.axis.message.MessageElement.publishToHandler(MessageElement.j 
> ava:722)
>       [java]     at  
> org.apache.axis.message.RPCElement.deserialize(RPCElement.java:233)
>       [java]     at  
> org.apache.axis.message.RPCElement.getParams(RPCElement.java:347)
>       [java]     at org.apache.axis.client.Call.invoke(Call.java:2272)
>       [java]     at org.apache.axis.client.Call.invoke(Call.java:2171)
>       [java]     at org.apache.axis.client.Call.invoke(Call.java:1691)
>       [java]     at  
> com.alodar.feature.Alodar.GBIB.UserUtilsStub.get_user_ids_by_name(UserUt 
> ilsStub.java:187)
>       [java]     at axisTest.callFeatureStub(axisTest.java:71)
>       [java]     at axisTest.main(axisTest.java:46)
> 
> Scott

Reply via email to