使用TCL XMLRPC服务器的Java XmlRpc客户端POST问题

时间:2012-11-18 21:21:40

标签: apache tcl xml-rpc

我遇到一个简单的问题,我的Java XMLRPC客户端似乎无法正确使用用TCL编写的XMLRPC服务器

(使用TCL XMLRPC SERVER OPEN SOURCE implementation

总结:TCL / Python等XMLRPC客户端可以/可以向TCL XMLRPC服务器发送/接收消息,但我的Java XMLRPC客户端似乎可以工作。

Java客户端代码:

   /*
    * try's, catches, comments removed to show code-flow w/ out mess.
    * host/port/target all same as whats set in Python
    */
    //show imports / package used, this is using apache's xmlrpc v3.1.3
    import org.apache.xmlrpc.XmlRpcException;
    import org.apache.xmlrpc.client.XmlRpcClient;
    import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
    //... host and port are the same as whats used in working tcl/python clients. (remoteHostName / 5555)
    //... method is the same as well, 'fooBar123', and args is just 1 string passed to it.
    XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
    target = "RPC2";
    String targetUrl = "http://"+host+":"+port+"/" + target;
    TestNgUtil.ReportInfo("config.SetServerUrl("+targetUrl+")");
    config.setServerURL(new URL(targetUrl));
    XmlRpcClient client = new XmlRpcClient();
    client.setConfig(config);
    String result = null;
    /*
    * This Result Never Returns from TCL XMLRPC Server
    */
    result = (String) client.execute(command, params);

TCL服务器对Java的调试错误响应:

    //(notice unlike Python example below, no proper Header, Content-Type, etc)

    TCL Server Side of the Java Error
    in serveOnce: addr: 10.21.69.13
    in serveOnce: port: 64522
    Unknown type: fooBar123</value></param></params>
    bgerror failed to handle background error.
    Original error: 
    Error in bgerror: can't read "xmlcall": no such variable**

Python示例有效,但是,请注意我打印出XML-debug以查看成功的请求:

但是,如果我尝试使用TCL客户端,甚至是简单的Python XMLRPC客户端,它都可以使用。 我甚至使用Python打印出XMLRPC请求:

(来自Python客户端,nothing喜欢,)

    import xmlrpclib
    server_url = "http://remoteHostName:5555";
    server = xmlrpclib.Server(server_url, verbose=True);
    result = server.hello('hello world')
    ## DEBUG INFO PRINTED FROM REQUEST POST ##
    send: "POST /RPC2 HTTP/1.1\r\nHost: remoteHostName:5555\r\nAccept-Encoding: gzip\r\nUser-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)\r\nContent-Type: text/xml\r\nContent-Length: 160\r\n\r\n<?xml version='1.0'?>\n<methodCall>\n<methodName>hello</methodName>\n<params>\n<param>\n<value><string>hello world</string></value>\n</param>\n</params>\n</methodCall>\n"

    reply: 'HTTP/1.1 200 OK\n'
    header: Content-Type: text/xml
    header: Content-length: 162
    body: '<?xml version="1.0"?>\n<methodResponse>\n\t<params>\n\t\t<param>\n\t\t\t<value>     <string>hello(hello world) yaaaah?!</string></value>\n\t\t</param>\n\t</params>\n</methodResponse>\n'

TCL服务器对Python的调试/响应,然后再推回正确的响应:

    send: "POST /RPC2 HTTP/1.1
    Host: remoteHostName:5555
    Accept-Encoding: gzip
    User-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)
    Content-Type: text/xml
    Content-Length: 156

这是用于hello(arg)的TCL XMLRPC服务器代码,适用于tcl,python,而不适用于java。 (可能是java客户端配置问题)

    #using the TCL XMLRPC Server ( http://sourceforge.net/projects/xmlrpctcl/ ) 
    package require xmlrpc
    xmlrpc::serv 5555

    proc hello { world } {
  puts "IN HELLO WORLD!"
  set res "hello(${world}) yaaaah?!"
  return [list string $res]
    }

    vwait forever

我感谢任何指针,我已经尝试使用嵌入式TCL解释器的Java或Python来避免这种情况,但由于此应用程序必须使用,源和共享的大量TCL,我必须得到一个TCL XMLRPC服务器并正常工作。

我也尝试过使用带有XMLRPC的webservices httpd,但是即使让它与tcl / python客户端一起使用也没有多少成功。

已经在这个周末杀了一整个周末。

感谢阅读和任何指示/帮助。


解决方案(发布在此处)

  1. 问题归结为旧的tcl xmlrpc服务器的XML,不包括数据类型。它们是隐含的,所以为了让apache的XMLRPC客户端围绕字符串发送隐含的数据类型,只需实现“自定义数据类型”来放回标记。
  2. 代码在这里:

    import java.net.URL;
    
    import org.apache.xmlrpc.client.XmlRpcClient;
    import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
    import org.apache.xmlrpc.common.TypeFactoryImpl;
    import org.apache.xmlrpc.common.XmlRpcController;
    import org.apache.xmlrpc.common.XmlRpcStreamConfig;
    import org.apache.xmlrpc.serializer.StringSerializer;
    import org.apache.xmlrpc.serializer.TypeSerializer;
    import org.xml.sax.ContentHandler;
    import org.xml.sax.SAXException;
    
    public class XMLRPCClient {
        public static void main(String[] argv) throws Exception {
            XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
            config.setServerURL(new URL("http://127.0.0.1:6800/rpc"));
            XmlRpcClient client = new XmlRpcClient();
            client.setConfig(config);
            client.setTypeFactory(new MyTypeFactoryImpl(client));
            Object[] params = new Object[] {
                new String[] { "http://www.google.com" }
            };
            String result = (String)client.execute("aria2.addUri", params);
        }
    
        static private class MyStringSerializer extends StringSerializer {
            public void write(ContentHandler pHandler, Object pObject)
                throws SAXException {
                // Write <string> tag explicitly
                write(pHandler, STRING_TAG, pObject.toString());
            }
        }
    
        static private class MyTypeFactoryImpl extends TypeFactoryImpl {
            public MyTypeFactoryImpl(XmlRpcController pController) {
                super(pController);
            }
    
            public TypeSerializer getSerializer(XmlRpcStreamConfig pConfig, Object pObject) throws SAXException {
                if(pObject instanceof String) {
                    return new MyStringSerializer();
                } else {
                    return super.getSerializer(pConfig, pObject);
                }
            }
        }
    }
    

1 个答案:

答案 0 :(得分:0)

问题归结为旧的tcl XMLRPC服务器的XML,不包括数据类型。他们暗示,所以为了让Apache的XMLRPC客户端围绕字符串发送隐含的数据类型,只需实现自定义数据类型&#39;将标签放回去。

import java.net.URL;

import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.common.TypeFactoryImpl;
import org.apache.xmlrpc.common.XmlRpcController;
import org.apache.xmlrpc.common.XmlRpcStreamConfig;
import org.apache.xmlrpc.serializer.StringSerializer;
import org.apache.xmlrpc.serializer.TypeSerializer;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;

public class XMLRPCClient {
    public static void main(String[] argv) throws Exception {
        XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
        config.setServerURL(new URL("http://127.0.0.1:6800/rpc"));
        XmlRpcClient client = new XmlRpcClient();
        client.setConfig(config);
        client.setTypeFactory(new MyTypeFactoryImpl(client));
        Object[] params = new Object[] {
            new String[] { "http://www.google.com" }
        };
        String result = (String)client.execute("aria2.addUri", params);
    }

    static private class MyStringSerializer extends StringSerializer {
        public void write(ContentHandler pHandler, Object pObject)
            throws SAXException {
            // Write <string> tag explicitly
            write(pHandler, STRING_TAG, pObject.toString());
        }
    }

    static private class MyTypeFactoryImpl extends TypeFactoryImpl {
        public MyTypeFactoryImpl(XmlRpcController pController) {
            super(pController);
        }

        public TypeSerializer getSerializer(XmlRpcStreamConfig pConfig, Object pObject) throws SAXException {
            if(pObject instanceof String) {
                return new MyStringSerializer();
            } else {
                return super.getSerializer(pConfig, pObject);
            }
        }
    }
}