Re: Kuddi: xmlrpc'ing vectors
"Thomas Koch" <[email protected]> Fri, 7 Mar 2003 09:15:31 +0100
| Newsgroups | gmane.comp.java.enhydra.kxmlrpc |
|---|---|
| Organization | OrbiTeam Software GmbH http://www.orbiteam.de |
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format. ------=_NextPart_000_0025_01C2E48A.1A52A9C0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Henrik, we've encoutered the same problem when starting our tests with the kXmlRpc lib and found some fixes for this. I posted an according message to the list in September last year.It's attached for your information. As there was no response on the list and also no updates of code or list archive I do now assume that the kxml-rpc project is 'on-hold'. Any 'official' comment from the kxml-rpc maintainers would be highly welcome. BTW, we're also doing work with kxml-rpc lib and J2ME midlets - I'd be interested in experience of other users with that technology combination. kind regards, Thomas Koch __________________________________________________________ Thomas Koch [email protected] OrbiTeam Software GmbH http://www.orbiteam.de Endenicher Allee 35 phone: +49 228 4101400 53121 Bonn fax: +49 228 4101401 Germany ----- Original Message ----- From: "Henrik Plate (GMX)" <[email protected]> To: <[email protected]> Sent: Thursday, March 06, 2003 5:43 PM Subject: Kuddi: xmlrpc'ing vectors > Hi everybody! > > Beside (k)XMLRPC is really lightweight, easy to use/learn and efficient I do > have some problems transfering vectors from a XMLRPC server to a MIDlet. > > I've got a servlet (source below, modified Apache class > org.apache.xmlrpc.XmlRpcProxyServlet) which acts as a XMLRPC server. The > servlet itself is registered as the default handler and got the method > getProviders, which simply returns a newly constructed Vector. Other methods > like getServerInfo, which returns a String, succeed. > > When I call the servlet with a J2SE client (slightly modified Apache > example) the resulting object is a Vector. Fine. > > When I call the method from a MIDlet, the Wireless Toolkit prints the > following exception: > > org.kxml.io.ParseException: unexpected: StartTag <data> line: -1 attr: null > @-1:-1 > at org.kxml.parser.AbstractXmlParser.read(+53) > at org.kxmlrpc.XmlRpcParser.parseValue(+15) > at org.kxmlrpc.XmlRpcParser.parseArray(+23) > at org.kxmlrpc.XmlRpcParser.parseValue(+241) > at org.kxmlrpc.XmlRpcParser.parseParams(+46) > at org.kxmlrpc.XmlRpcParser.parseResponse(+144) > at org.kxmlrpc.XmlRpcClient.execute(+200) > at midlet.ServerConnection.callMethod(+15) > at midlet.XmlRpcTestControl$1.run(+18) > > The via HTTP transfered xml response of the servlet is > > <?xml version="1.0" encoding="ISO-8859-1"?> > <methodResponse> > <params> > <param> > <value> > <array> > <data> > <value>String 1</value> > <value>String 2</value> > </data> > </array> > </value> > </param> > </params> > </methodResponse> > > Seems to be OK. > > Does kXMLRPC miss the implementation of Vector transfers? I can't imagine, > cause the parser fails at the data-, not the array-tag. Is it versioning > problem? > > Here's my enviroment: > > kXMLRPC 0.6 > XMLRPC 1.1 from Apache > J2SE 1.4.1 > Tomcat 4.0.1 > > Relevant part of the servlet source: > > import org.apache.xmlrpc.*; > > public class XmlRpcServlet extends HttpServlet { > > // The xml-rpc server. > final XmlRpcServer server = new XmlRpcServer(); > > public void init(ServletConfig config)throws ServletException{ > > // Config the xml-rpc server. > XmlRpc.setDebug(true); > server.addHandler("$default", this); > } > > public String getServerInfo() { return "XmlRpcServlet"; } > //"$Name$"; } > > public Vector getProviders() { > final Vector v = new Vector(); > v.add("String 1"); > v.add("String 2"); > return v; > } > > public void service(HttpServletRequest req, HttpServletResponse > res)throws ServletException, IOException{ > byte[] result = server.execute(req.getInputStream ()); > res.setContentType("text/xml"); > res.setContentLength(result.length); > OutputStream output = res.getOutputStream(); > output.write(result); > output.flush(); > } > } > > Another question: If a XMLRPC call fails, the XmlRpcClient class returns the > result of the previous call. Is that desireable? Not sure of this. > > Greetings und thanks in advance, > Henrik > > > > > > > > _______________________________________________ > Kuddi mailing list > [email protected] > http://support.enhydra.org/mailman/listinfo.cgi/kxmlrpc > ------=_NextPart_000_0025_01C2E48A.1A52A9C0 Content-Type: message/rfc822; name="Fixes to org.kxml.parser.XmlRpcParser .eml" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="Fixes to org.kxml.parser.XmlRpcParser .eml" From: "Thomas Koch" <[email protected]> To: <[email protected]> Subject: Fixes to org.kxml.parser.XmlRpcParser Date: Wed, 25 Sep 2002 12:15:21 +0200 Organization: OrbiTeam Software GmbH http://www.orbiteam.de MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0023_01C2648D.3832E0E0" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 5.50.4807.1700 X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4807.1700 This is a multi-part message in MIME format. ------=_NextPart_000_0023_01C2648D.3832E0E0 Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: 7bit Hi, I've downloaded kXML-RPC version 0.6 from http://kxmlrpc.enhydra.org and made some experiments with it. The package is very nice and runs out of the box but I found some minor problems when interacting with a python-based XML-RPC server: - it seems that the parser sometimes cannot handle whitespaces when parsing the Response - when parsing a response type "Array" the parser does not expect/consume the <data> tag, but the XML-RPC spec defines <array> as follows: "An <array> contains a single <data> element, which can contain any number of <value>s." e.g. <array><data> <value><string>Egypt</string></value> <value><boolean>0</boolean></value> </data></array> The fixes are as follows: in org.kxml.parser.XmlRpcParser: fixed: Object parseResponse() added: parser.skip(); before: Hashtable fault = (Hashtable) parseValue(); fixed: Object parseParams() added: parser.skip(); before: params.addElement( parseValue() ); fixed: Vector parseArray() added: parser.read( Xml.START_TAG, "", "data" ); parser.skip(); before: while( parser.peek().getType() != Xml.END_TAG ) { fixed: Vector parseArray() added: parser.read( Xml.END_TAG, "", "data" ); parser.skip(); before: return v; The new XmlRpcParser.java is attached. It has been tested with xmlrpc-lib of python2.2 - any comments are welcome. Please excuse if this has already been posted, but I couldn't browse the mailing list archive (it's empty on the website). I'm looking forward to further releases of kXML-RPC. kind regards Thomas Koch _______________________________________________________________ Thomas Koch [email protected] OrbiTeam Software GmbH http://www.orbiteam.de/ Rathausallee 10 phone: +49 2241 397996-0 53757 Sankt Augustin fax: +49 2241 397996-1 Germany ------=_NextPart_000_0023_01C2648D.3832E0E0 Content-Type: application/octet-stream; name="XmlRpcParser.java" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="XmlRpcParser.java" /* kxmlrpc=0A= *=0A= * The contents of this file are subject to the Enhydra Public License=0A= * Version 1.1 (the "License"); you may not use this file except in=0A= * compliance with the License. You may obtain a copy of the License=0A= * on the Enhydra web site ( http://www.enhydra.org/ ).=0A= *=0A= * Software distributed under the License is distributed on an "AS IS"=0A= * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See=0A= * the License for the specific terms governing rights and limitations=0A= * under the License.=0A= *=0A= * The Initial Developer of kxmlrpc is Kyle Gabhart. Copyright (C) 2001 =0A= * Kyle Gabhart -- [email protected] . All Rights Reserved.=0A= *=0A= * Contributor(s): Stefan Haustein=0A= */=0A= =0A= package org.kxmlrpc;=0A= =0A= import java.io.*;=0A= import java.util.*;=0A= =0A= import org.kxml.*;=0A= import org.kxml.parser.*;=0A= =0A= import org.kobjects.isodate.IsoDate;=0A= import org.kobjects.base64.Base64;=0A= =0A= /**=0A= * This abstract base class provides basic XML-RPC parsing capabilities. = The =0A= * kxml parser is required by this class.=0A= */=0A= public class XmlRpcParser {=0A= =0A= AbstractXmlParser parser;=0A= String methodName;=0A= Vector params =3D new Vector();=0A= =0A= /**=0A= * @param parser a kxml parser object reference=0A= */=0A= public XmlRpcParser( AbstractXmlParser parser ) {=0A= this.parser =3D parser;=0A= }//end XmlRpcParser( AbstractXmlParser )=0A= =0A= public String getMethodName() {=0A= return methodName;=0A= }//end getMethodName()=0A= =0A= public Vector getParams() {=0A= return params;=0A= }//end getParams()=0A= =0A= /*=0A= // This method is used to parse an incoming Client request=0A= // kxmlrpc does not currently support this feature=0A= public void parseCall() throws IOException {=0A= parser.skip(); =0A= parser.read( Xml.START_TAG, "", "methodCall" );=0A= =0A= parser.skip();=0A= parser.read( Xml.START_TAG, "", "methodName" );=0A= methodName =3D parser.readText();=0A= parser.read( Xml.END_TAG, "", "methodName" );=0A= =0A= parser.skip();=0A= =0A= if( parser.peek().getType() !=3D Xml.END_TAG ) =0A= parseParams();=0A= =0A= parser.read( Xml.END_TAG, "", "methodCall" );=0A= parser.skip();=0A= parser.read( Xml.END_DOCUMENT, null, null );=0A= }//end parseCall()=0A= */=0A= =0A= /** =0A= * Called by a client to parse an XML-RPC response returned by a = server.=0A= *=0A= * @return The return parameter sent back by the server.=0A= */=0A= public Object parseResponse() throws IOException {=0A= ParseEvent event;=0A= Object result;=0A= =0A= parser.skip();=0A= parser.read( Xml.START_TAG, "", "methodResponse" );=0A= parser.skip();=0A= =0A= event =3D parser.peek();=0A= result =3D null;=0A= =0A= if( event.getType() =3D=3D Xml.START_TAG ) {=0A= // If an error occurred, the server will return a Fault=0A= if( "fault".equals( event.getName() ) ) { =0A= parser.read();=0A= parser.skip(); // NEW: added 02-09-25, TKo =0A= // Fault's are returned as structs (which are mapped to = Hashtables)=0A= Hashtable fault =3D (Hashtable) parseValue();=0A= parser.skip();=0A= parser.read( Xml.END_TAG, "", "fault" );=0A= // Ultimately, a client-side exception object is = generated=0A= result =3D new XmlRpcException =0A= ( ( (Integer) fault.get( "faultCode" ) ).intValue(),=0A= (String) fault.get( "faultString" ) );=0A= }=0A= /* The current version of the XML-RPC spec -- = http://www.xmlrpc.org/spec=0A= does not permit multiple parameter values to be = returned, although=0A= a complex type (struct or array) containing multiple = values (and even=0A= other complext types) is permitted. This aspect of the = spec is currently=0A= being debated and may be changed in the future. */=0A= else if( "params".equals( event.getName() ) ) {=0A= parseParams();=0A= if( params.size() > 1 ) =0A= throw new IOException( "too many return parameters" );=0A= else if( params.size() =3D=3D 1 ) =0A= result =3D params.elementAt(0);=0A= }=0A= else throw new IOException =0A= ( "<fault> or <params> expected instead of " + event );=0A= }//end if( event.getType() =3D=3D Xml.START_TAG ) {=0A= =0A= parser.skip();=0A= parser.read( Xml.END_TAG, "", "methodResponse" );=0A= parser.skip();=0A= parser.read( Xml.END_DOCUMENT, null, null );=0A= =0A= return result;=0A= }//end parseResponse()=0A= =0A= /**=0A= * All data in an XML-RPC call is passed as a parameter. This method = parses =0A= * the parameter values out of each parameter by calling the = parseValue() =0A= * method. =0A= */=0A= void parseParams() throws IOException {=0A= parser.read( Xml.START_TAG, "", "params" );=0A= parser.skip();=0A= =0A= while( parser.peek().getType() !=3D Xml.END_TAG ) {=0A= parser.read( Xml.START_TAG, "", "param" );=0A= // Retrieve a Java representation of the XML-RPC parameter = value=0A= parser.skip(); // NEW: added 02-09-20, TKo=0A= params.addElement( parseValue() );=0A= parser.skip();=0A= parser.read( Xml.END_TAG, "", "param" );=0A= parser.skip();=0A= }//end while( parser.peek().getType() !=3D Xml.END_TAG )=0A= =0A= parser.read( Xml.END_TAG, "", "params" );=0A= parser.skip();=0A= }//end parseParams()=0A= =0A= /** =0A= * Core method for parsing XML-RPC values into Java data types. It = is called =0A= * recursively by the parseStruct() and parseArray() methods when = handling =0A= * complex data types =0A= * =0A= * @return A Java representation of the XML-RPC value=0A= */=0A= Object parseValue() throws IOException {=0A= Object result =3D null;=0A= =0A= parser.read( Xml.START_TAG, "", "value" );=0A= parser.skip();=0A= =0A= if( parser.peek().getType() !=3D Xml.START_TAG ) =0A= result =3D parser.readText();=0A= else {=0A= ParseEvent event =3D parser.read( Xml.START_TAG, "", null );=0A= String name =3D event.getName();=0A= =0A= if( name.equals("string") )=0A= result =3D parser.readText();=0A= else if( name.equals("i4") || name.equals("int") )=0A= result =3D new Integer =0A= ( Integer.parseInt( parser.readText().trim() ) );=0A= else if( name.equals("boolean") )=0A= result =3D new Boolean( parser.readText().trim().equals("1") );=0A= else if( name.equals("dateTime.iso8601") )=0A= result =3D IsoDate.stringToDate =0A= ( parser.readText(), IsoDate.DATE_TIME );=0A= else if( name.equals("base64") )=0A= result =3D Base64.decode( parser.readText() );=0A= else if( name.equals("struct") ) =0A= result =3D parseStruct(); =0A= else if( name.equals("array") )=0A= result =3D parseArray();=0A= // kxmlrpc does not currently support the XML-RPC double = data type=0A= // the temporary workaround is to process double values as = strings=0A= else if( name.equals("double") )=0A= result =3D parser.readText();=0A= =0A= parser.read( Xml.END_TAG, "", name );=0A= parser.skip();=0A= }//end if( parser.peek().getType() !=3D Xml.START_TAG )=0A= =0A= parser.read( Xml.END_TAG, "", "value" );=0A= return result;=0A= }//end parseValue()=0A= =0A= /**=0A= * @return kxmlrpc maps XML-RPC structs to java.util.Hashtables=0A= */=0A= Hashtable parseStruct() throws IOException {=0A= Hashtable h =3D new Hashtable();=0A= parser.skip();=0A= =0A= while( parser.peek().getType() !=3D Xml.END_TAG ) {=0A= parser.read( Xml.START_TAG, "", "member" );=0A= parser.skip();=0A= parser.read( Xml.START_TAG, "", "name" );=0A= String name =3D parser.readText();=0A= parser.read( Xml.END_TAG, "", "name" );=0A= parser.skip();=0A= h.put( name, parseValue() ); // parse this member value=0A= parser.skip();=0A= parser.read( Xml.END_TAG, "", "member" );=0A= parser.skip();=0A= }//end while( parser.peek().getType() !=3D Xml.END_TAG )=0A= return h;=0A= }//end parseStruct()=0A= =0A= /**=0A= * @return kxmlrpc maps XML-RPC arrays to java.util.Vectors=0A= */=0A= Vector parseArray() throws IOException {=0A= Vector v =3D new Vector();=0A= parser.skip();=0A= =0A= // NEW: need to consume <data> tag! (TKo)=0A= parser.read( Xml.START_TAG, "", "data" );=0A= parser.skip();=0A= // end new=0A= =0A= while( parser.peek().getType() !=3D Xml.END_TAG ) {=0A= v.addElement( parseValue() ); // parse this element value=0A= parser.skip();=0A= }//end while( parser.peek().getType() !=3D Xml.END_TAG )=0A= =0A= // NEW: need to consume </data> tag! (TKo)=0A= parser.read( Xml.END_TAG, "", "data" );=0A= parser.skip();=0A= // end new=0A= =0A= return v;=0A= }//end parseArray()=0A= }//end XmlRpcParser ------=_NextPart_000_0023_01C2648D.3832E0E0-- ------=_NextPart_000_0025_01C2E48A.1A52A9C0--