Subsequent to the 2.3.1 release, I wrote a PropertyBagSerializer (http://cvs.apache.org/viewcvs.cgi/*checkout*/ws-soap/java/src/org/apache/soap/encoding/soapenc/PropertyBagSerializer.java?rev=1.3) that can be used for this. You would need to either get the last nightly build and use it instead of 2.3.1, or just grab the code from the CVS link above, compile it, and put the byte code in your classpath. Your client code would look like
SOAPMappingRegistry smrr = new SOAPMappingRegistry (); PropertyBagSerializer pbs = new PropertyBagSerializer (); smrr.mapTypes(Constants.NS_URI_SOAP_ENC, new QName("http://xml.apache.org/xml-soap", "SOAPStruct"), Hashtable.class, null, pbs); Scott Nichol Do not send e-mail directly to this e-mail address, because it is filtered to accept only mail from specific mail lists. ----- Original Message ----- From: "Chen, Donald" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Friday, August 06, 2004 5:08 PM Subject: How to deseralize a hashtable? Hi, All. I have a WS in Perl via SOAP::Lite. Via this WS, a client can call a method getAllInfo() which returns a Hashtable. I wrote a WS client in perl with success, but writing a WS client in Java via the Apache-Soap-2.3.1 is never successful. Specifically, the error I got is like this: Exception in thread "main" java.lang.IllegalArgumentException: No Deserializer found to deserialize a 'http://xml.apache.org/xml-soap:SOAPStruct' using encoding style 'http://schemas.xmlsoap.org/soap/encoding/'. at org.apache.soap.util.xml.XMLJavaMappingRegistry.queryDeserializer(XMLJav aMappingRegistry.java:206) at org.apache.soap.util.xml.XMLJavaMappingRegistry.unmarshall(XMLJavaMappin gRegistry.java:302) at org.apache.soap.encoding.soapenc.ParameterSerializer.unmarshall(Paramete rSerializer.java:206) at org.apache.soap.util.xml.XMLJavaMappingRegistry.unmarshall(XMLJavaMappin gRegistry.java:314) at org.apache.soap.rpc.RPCMessage.unmarshall(RPCMessage.java:417) at org.apache.soap.rpc.RPCMessage.extractFromEnvelope(RPCMessage.java:197) at org.apache.soap.rpc.Response.extractFromEnvelope(Response.java:142) at GetChemDef.main(GetChemDef.java:167) Here is the payload I got from the server: <?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"><SOAP-ENV:Body><namesp17:ge tAllInfoResponse xmlns:namesp17="http://johnny5:8002/ChemDefServices"><s-gensym68 xsi:type="namesp2:SOAPStruct"><delimilator xsi:type="xsd:string">|</delimilator><chemistry xsi:type="xsd:string">caffeine</chemistry><a xsi:type="xsd:string">aPiece</a><smiles xsi:type="xsd:string">c1ccccc1</smiles><b xsi:type="xsd:string">bPiece</b><syntaxOk xsi:type="xsd:int">1</syntaxOk></s-gensym68></namesp17:getAllInfoRespons e></SOAP-ENV:Body></SOAP-ENV:Envelope> This payload refects a hashtable: %h = ( chemistry => 'caffeine', a => 'aPiece', b => 'bPiece', smiles => 'c1ccccc1' ); Here are the major code lines (as you can see, I was trying to use the HashtableSerializer ): // build the call. Call call = new Call(); call.setSOAPTransport(st); call.setTargetObjectURI("http://localhost:8002/ChemDefServices"); call.setMethodName("getAllInfo"); SOAPMappingRegistry smrr = new SOAPMappingRegistry (); HashtableSerializer hsd = new HashtableSerializer (); smrr.mapTypes(Constants.NS_URI_SOAP_ENC, new QName("", "ChemDefServices"), Hashtable.class, null, hsd); // create the transport and set parameters call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); call.setSOAPMappingRegistry(smrr); Vector params = new Vector(); params.addElement(new Parameter("definition", String.class, "definition", null)); params.addElement(new Parameter("chemDefString", String.class, chemDefString, null)); call.setParams(params); // invoke it System.err.println("Invoking chemDef service at: "); System.err.println("\t" + serviceURL); Response resp; try { SOAPMappingRegistry smr = call.getSOAPMappingRegistry(); SOAPContext reqCtx = call.getSOAPContext(); DocumentBuilder xdb = XMLParserUtils.getXMLDocBuilder(); Envelope callEnv = call.buildEnvelope(); StringWriter payloadSW = new StringWriter(); callEnv.marshall(payloadSW, smr, reqCtx); reqCtx.setRootPart(payloadSW.toString(), Constants.HEADERVAL_CONTENT_TYPE); st.send(url, "", null, null, smr, reqCtx); SOAPContext respCtx = st.getResponseSOAPContext(); String payloadStr = Call.getEnvelopeString(st); Document respDoc = xdb.parse(new InputSource(new StringReader(payloadStr))); Element payload = null; if (respDoc != null) { payload = respDoc.getDocumentElement(); } else { throw new SOAPException (Constants.FAULT_CODE_CLIENT, "Parsing error, response was:\n" + payloadStr); } System.out.println("payloadStr = \n" + payloadStr); Envelope respEnv = Envelope.unmarshall(payload, respCtx); System.out.println("respEnv = \n" + respEnv.toString()); System.out.println("respCtx = \n" + respCtx.toString()); resp = Response.extractFromEnvelope(respEnv, smr, respCtx); // I got error right here Did I miss something to make it work? Do I need to write my own deseralizer for the hashtable? If yes, how to incorporate the deseralizer to the main funciton? Thanks in advance, Donald