Magento api with Java Client — problem with XML-RPC interface

One of the features touted by Magento is the api exposed via both XML-RPC and SOAP. I quickly (and successfully) tested the SOAP interface using the amazingly complete (and free) soapUI. I wanted to use XML-RPC, and decided to build a test client in Java. While trying to build a client, using the apache ws-xmlrpc library, I ran into a roadblock. The initial login and some other calls would work just fine, but some calls such as product.info would always cause an exception, similar to:

Exception in thread "main" org.apache.xmlrpc.client.XmlRpcClientException:
Failed to parse servers response: Unknown type: nil

I posted on the magento forum to no success (except to find a few others with the same problem). So I was on my own..

After some research, I determined that the problem (IMHO) is that the Magento api is incorrectly using the nil type in responses. According to the XML-RPC spec, nil is an extended type, and can only be used with a namespace (e.g. ex:nil) — see the data types section on the apache site. But, luckily, the ws-xmlrpc library can be easily extended to provide a work around, and the following solution worked for me.


All you need to do is extend the builtin TypeFactoryImpl class and the assign the client TypeFactory to your custom class. Most of the work by this custom TypeFactory can be done using the super class, so just check for the incorrect nil usage when getting a parser. e.g the TypeFactory I used :

public class MyTypeFactory extends TypeFactoryImpl {

    public MyTypeFactory(XmlRpcController pController) {
        super(pController);
    }

    @Override
    public TypeParser getParser(XmlRpcStreamConfig pConfig,
      NamespaceContextImpl pContext, String pURI, String pLocalName) {

        if ("".equals(pURI) && NullSerializer.NIL_TAG.equals(pLocalName)) {
            return new NullParser();
        } else {
            return super.getParser(pConfig, pContext, pURI, pLocalName);
        }
    }
}

and then created my XmlRpcClient as follows:

XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL(new URL("http://mymagentoserver.com/api/xmlrpc/"));
XmlRpcClient client = new XmlRpcClient();
client.setConfig(config);
client.setTypeFactory(new MyTypeFactory(client));

Notes:

  • There is a enabledForExtensions property used by the client (and server) classes, which can be set by XmlRpcConfig:: setEnabledForExtensions(), but that has no effect here since the Magento server is doing it wrong.
  • You would use a very similar method if you needed to implement a custom type (if your XML-RPC server defined one), but would need to provide a custom TypeSerializer as well, by overriding the getSerializer() method in MyTypeFactory. There is an example of this on the ws-xmlrpc site in the advanced techniques section.

As usual, your milage may vary.

15 thoughts on “Magento api with Java Client — problem with XML-RPC interface

  1. Jonathan Rogers

    Thanks for the workaround. I was surprised to discover that the bug was in Magento or whatever XML-RPC implementation it’s using, since Python’s xmlrpclib communicates with it just fine. I guess a number of implementations must allow the non-standard nil. Ideally, this should be addressed in Magento.

  2. Pingback: Stephan Wiencznys Blog

  3. panticz.de

    Hello everybody!

    I am currently writing a Magento Connector for Java. The goal is to create a free wrapper / library to manage Magento from a Java application. A few parts such as management of products, categories and pictures are already partially finished and can be used.

    The latest version (source code and JAR package) can be downloaded from this homepage:
    http://www.panticz.de/MagentoConnector

    If someone is interested in co-development, please contact my here http://www.panticz.de/contact/.

    Greeting

    Pawel

  4. hoook

    Hey,
    Thanks for this post, it saved me hours of making my own walkarround :)

    I’m not sure, that this is only magento problem. I’m connectiong from Java (apache .jar) to Python’s XMLRPC WebService and got the same exception.

    Anyway, thanks :)

  5. leeman

    Thanks for this post, saved me lots of time! And I wasn’t even doing anything with Magento, it was some other web service using XML-RPC with nil instead of ex:nil.

  6. lee

    This solved an issue I had making requests to a web service from Java using the Apache XML-RPC library (unrelated to Magento). But, I still had issues because I needed to send nil to the web service, but it didn’t recognize nil encoded as . To fix it, in the MyTypeFactory class from the code above I included the following method:

    @Override
    public TypeSerializer getSerializer(XmlRpcStreamConfig pConfig, Object pObject) throws SAXException {
    if (pObject == null) {
    return new TypeSerializerImpl() {
    public void write(ContentHandler pHandler, Object o) throws SAXException {
    pHandler.startElement(“”, VALUE_TAG, VALUE_TAG, ZERO_ATTRIBUTES);
    pHandler.startElement(“”, NullSerializer.NIL_TAG, NullSerializer.NIL_TAG, ZERO_ATTRIBUTES);
    pHandler.endElement(“”, NullSerializer.NIL_TAG, NullSerializer.NIL_TAG);
    pHandler.endElement(“”, VALUE_TAG, VALUE_TAG);
    }
    };
    } else {
    return super.getSerializer(pConfig, pObject);
    }
    }

  7. arimus

    Thank you very much. I had extensions enabled for perl RPC::XML and needed to get the apache client working and the enabledForExtensions also did not work for me…was scratching my head. You saved me a few hours, which after a long string of tracking things down myself was a welcome change.

    Cheers

  8. Gary

    Thank you very much for the solution, saved a tone of time… I was just about to start debugging myself. Thanks again…

  9. Ravi

    Thanks panticz.de, has been struggling since long. my client gave me these APIs as there own. I was not aware they come from some commerce website. so had not searched on net. this saved my day

  10. Michael Andreas

    Hey, just wanted to say thanks a lot for sharing this. I’m not using Magento but the solution works like a charm with my nil-spitting Python server. Thanks again!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>