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
