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.
No related posts.
Related posts brought to you by Yet Another Related Posts Plugin.
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.
Magento…
Also sollte mal jemand in die Verlegenheit kommen Magento benutzen zu müssen, tut er mir leid. Vom Funktionsumfang her ist hat es so ziemlich alles, was man sich wünschen könnte. Geht es jedoch darum Erweiterungen zu schreiben hört der Spaß auf. D…
Just for clarification: according to the XMLRPC spec, NIL does not exist at all, namespace or not (http://www.xmlrpc.com/spec).
The ex:nil is an extension first added by the Apache lib whereas the ‘nil’ extension was added by another implementation (http://ontosys.com/xml-rpc/extensions.php), long time before that iirc.
So to say that the fault lies on the magento side is a bit arbitrary…
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
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
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.
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);
}
}
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
Thanks a lot – this saved me a couple of hours of debugging.
Thank you very much for the solution, saved a tone of time… I was just about to start debugging myself. Thanks again…
Thanks man, this saved my day(literally)
Thanks man! Damn. Merci mille fois!
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
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!