I have imported the Apache XML-RPC jar files, and got them working (has taken me all day to figure out how to get it working - so I'm kind of frustrated at the moment ;D) ... but that used the execute(..) method which requires two parameters ... there was no one-parameter version which is what I *think* I need.

NOTE: My code is at the bottom of the post.


I want to access an API by sending it requests and collecting whatever it returns back to me.

The XML-RPC server in question is the one that Wikidot.com makes available to it's users to access their wikis.

The main page introducing the API is here: http://www.wikidot.com/doc:api (despite what it says on that page, the API *is* operational and working - I've confirmed that with Wikidot)

For now, I'd just like to get the system.listMethods() method working, as that takes no parameters and returns a list of the methods that I can use. The reason for me wanting to do this one is because I'm guessing it'll be the easiest to do - it doesn't need any parameters.

That method is mentioned on the page I linked to, along with instructions for how to access and use the API using a Python interactive console. I have successfully accessed the API and used it with Python - but I want to do the same thing with a Java application.

This is what I have so far. I have no idea how to call the system.listMethods() method. So the question I'm asking in this thread is - how do I do that?

RunProgram.java

import java.net.MalformedURLException;
import java.util.Vector;
import java.util.Hashtable;
import org.apache.xmlrpc.*;
import org.xml.*;


public class RunProgram
{
	private String user = "****"; //Private info, removed
	private String key = "****"; //Private info, removed
	
	private final String server_url = "https://"+user+":"+key+"@www.wikidot.com/xml-rpc-api.php";
	
	public static void main(String[] args)
	{
		new RunProgram().exe();
	}
	
	public void exe()
	{
		System.out.println("*********************************************");
		System.out.println("***** Wikidot API - Java Program ************");
		System.out.println("*********************************************");
		
		try
		{
			// Create an object to represent the server
			XmlRpcClient myServer = new XmlRpcClient(server_url);
			
			// TODO: I want to call the method "system.listMethods()"
			
			
			// *** Here, I'd like to call system.listMethods() ***
			// myServer.system.listMethods() doesn't work ;-)
		}
        catch (Exception e)
        {
            System.err.println("JavaClient: " + e.toString());
        }
		
		System.out.println("REACHED END OF PROGRAM");
	}
}

I have removed the username and API key for security reasons, but I can assure you that the username/key combination I am using is correct as it worked with Python.

Note: Keep in mind that I am new to everything to do with XML-RPC, which probably explains the difficulty I had in getting this far. Something that seems obvious to you may not be so obvious to me.

Recommended Answers

All 9 Replies

Have you tried to understand the client examples posted on the official XML-RPC site? IMO, something like client.execute("System.listMethods", new ArrayList()) or client.execute("system.listMethods", new ArrayList()) should do the trick.

I definitely looked at the official website, but I don't remember seeing that particular page.

I think those instructions might be out of date though. For one thing it suggests:

import org.apache.xmlrpc.client.XmlRpcClient;

That couldn't be found on my machine. I checked the Jar file and found that it wasn't in a subfolder called client at all, so removing the 'client' worked:

import org.apache.xmlrpc.XmlRpcClient;

However XmlRpcClientConfigImpl seems to be missing - I can't find it anywhere in the xmlrpc Jar file.

You've given me somewhere else to look for answers, thanks. Will see if I can figure out where XmlRpcClientConfigImpl is meant to be and hopefully, I'll be able to get things working once that's done.

To find out which JAR a given class belongs to, use a service like GrepCode. It tells you all the possible JAR files which has that particular class along with providing download for the same. For e.g. here's the grepcode result for the JAR file which uses the class XmlRpcClient.

I was able to get system.listMethods working eventually. Turned out that the latest version of Apache XML-RPC only had some of the JARs I needed... for some strange reason. Had to search through Google for the rest.

Now I'm having more problems - any method that requires a parameter doesn't work :S (I can't seem to figure out what data type to pass in!)
Any help or suggestions are appreciated (posted to Python forums): http://www.daniweb.com/forums/post1266826.html#post1266826

What do you mean by "doesn't work"? Exception? No result? Anyways, have you tried passing in an Object array as shown in the official documentation? Paste the code you are using.

As I mentioned, "I can't seem to figure out what data type to pass in!". What I mean by that is that I am getting an XmlRpcException with the message "Calling parameters do not match signature".

CLASS: class org.apache.xmlrpc.XmlRpcException
MESSAGE: Calling parameters do not match signature

Passing in an empty Object[] array works fine for methods that do not require any parameters, however this doesn't work:

Object[] params = new Object[] { "user", "username" };

The corresponding Python code for the same method is this (and these parameters are accepted):

>>> s.user.sites({'user': 'username'})

From what I can tell through reading about that kind of statement, it seems to be a hashtable with 'user' as the key and 'username' as the data stored using that key.

The equivalent in Java is a Map, correct? However the Apache XML-RPC libraries only allow me to pass in either a List or an Object[] as parameters. I've attempted to use both of those, but continue to get the exception stating that the parameters do not match.

Solved the problem. The Apache XML-RPC libraries only accepted a List and Object[] ... so I was trying to explicitly cast to Object[] instead, and was getting problems with that.

This worked (passing in a Hashtable, inserted into an Object[]), as it is passing in an Object[] array as the parameter... and the method accepted it:

// Create the Object[] params
Object[] params = new Object[] { null };
Hashtable ht = new Hashtable();
ht.put("user", "username");
params[0] = ht;
// Pass 'params' to the method
// ...

I blame my own inexperience for this. At least I won't make the same mistake again.

Thanks for the help ~s.o.s~

> Solved the problem

Good thing that you could come up with a solution on your own. A couple of points though in case you are starting with Java:

  • Declare/define variables closest to their usage point. In your code, you create an object array on the first line and use it on the 4th line. The lesser the scope of your variables created, the more easier it would be for you to reason out with your code. A thousand declarations at the start of a method add to the confusion. In your case, you could have done something like:
    Map<String, String> map = new HashMap<String, String>();
    map.put("user", "username");
    Object[] params = new Object[] { map };

    Mind you, this is more of a "good coding practice" thing than a requirement.

  • Don't use HashTable; use an HashMap instead. In almost all cases, you really don't need the additional method level synchronization offered by HashTable. HashTable, Vector and a few other classes have got pretty good replacements in the standard library so unless you are planning on dealing with some legacy code, you are better off without them. The only reasons these classes have been around is to maintain binary/backward compatibility.
  • If you are using Java 5 or greater (btw, you really should), utilize the "generics" feature offered by the language. For example, your map could have been created like Map<String, String> map = new HashMap<String, String>(); . The advantage here is the additional compile time check placed by the compiler when you work with your map. Your current code will allow things like map.put("user", new Date()); whereas the generified code won't.

I've taken your suggestions on board and have modified my code as you suggested.

> A thousand declarations at the start of a method add to the confusion.

Usually, I would compact my code as much as possible when I'm writing it (with the exception that I dislike using the shortened form of an if statement).

As anything networking-related is new to me, including interacting with a website's API as I am doing here, I've mostly copied code and mixed up several examples to get what I want... therefore this isn't really my best work :) So thanks for helping me to clean it up a bit!

I'm breaking down barriers and trying to learn how to do more with Java, and that undoubtedly means I'm making a lot of mistakes along the way :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.