6. XMLRPC Interoperability

Many published XMLRPC services have method names that cannot be directly mapped to Java methods. In order to inter-operate with these external services SwitchRMI must map from a Java method to a XMLRPC method name in order to construct the correct methodCall XML request. For example the O'Reilly Meerkat XMLRPC interface, documented at http://www.oreillynet.com/pub/a/rss/2000/11/14/meerkat_xmlrpc.html declares all of it's methods with a prefix of "meerkat." or "system." as in "meerkat.getChannels".

Calling a Third-Party XMLRPC Implementation

SwitchRMI uses a Java interface to interact with a remote XMLRPC service. Once the interface is defined a XML file, containing the mapping is deployed in the same directory as the class file for the interface. The file must have the same name as the class and the suffix .xmlrpcSignatures and MUST be deployed in the same directory as the class. The file contains a xmlrpc element wrapped around one, or more, method elements. Each method element must have an internal attribute with a string value representing the method signature of the method in the Java interface to the remote service and an external attribute with the value of the XMLRPC method name. The Java interface to the Meerkat service and the xmlrpcSignatures file used to convert Java method names to the Meerkat service method names are shown below.

Java interface:

		package com.mjh.switchrmi.protocol.xmlrpc;
		
		public interface IMeerkat {
	
			public List getChannels();
			public List getCategories();
			public List getCategoriesBySubstring(String substring);
			public List getChannelsByCategory(int categoryID);
			public List getChannelsBySubstring(String substring);
			public List getItems(Map params);
			public String getMethodHelpText(String methodName);
			public List getMethodSignature(String methodName);
			}
		

Signature mapping file:

		<?xml version="1.0"?>
		<xmlrpc>
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.IMeerkat:java.util.List:getChannels:"
				external="meerkat.getChannels" />
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.IMeerkat:java.util.List:getCategories:"
				external="meerkat.getCategories" />
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.IMeerkat:java.util.List:getCategoriesBySubstring:java.lang.String"
				external="meerkat.getCategoriesBySubstring" />
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.IMeerkat:java.util.List:getChannelsByCategory:int"
				external="meerkat.getChannelsByCategory" />
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.IMeerkat:java.lang.String:getMethodHelpText:java.lang.String"
				external="system.methodHelp" />
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.IMeerkat:java.util.List:getMethodSignature:java.lang.String"
				external="system.methodSignature" />
		</xmlrpc>
		

The internal method signature consists of a list of colon (:) separated fields representing the method return type, method name and method argument types (in order).

The client interaction is, once again, via a proxy and looks the same as interacting with a SwitchRMI published object:

		import com.mjh.switchrmi.*;
		import com.mjh.switchrmi.protocol.xmlrpc.*;
				
			private RmiClient rmi;
			private IMeerkat  meerkat;
					
			try {
				rmi     = new RmiClient();
				meerkat = rmi.connect("http://www.oreillynet.com/meerkat/xml-rpc/server.php", IMeerkat.class);
				
				List channels = meerkat.getChannels();
			}
			catch (Exception ex) {
			}
		

The .xmlrpcSignatures file is not required when the remote methods are hosted by SwitchRMI.

Exposing SwitchRMI Published Objects to Third-Party XMLRPC Implementations

In order to expose a SwitchRMI published service object to a third party implementation the Java interfaces supported by the service object must be mapped to XMLRPC method names. The mapping is achieved using the same type of mapping file used to allow a SwitchRMI client to communicate with a third-party XMLRPC service. The same rules for naming and location of file apply.

The JUnit test suites in the source code for SwitchRMI include an example of this type of interoperability. The validation tests described at http://validator.xmlrpc.com is implemented as a SwitchRMI service class conforming to the IValidator interface:

		package com.mjh.switchrmi.protocol.xmlrpc.validator;

		public interface IValidator {
	
			public int arrayOfStructsTest(List list);
			public Map countTheEntities(String string);
			public int easyStructTest(Map map);
			public Map echoStructTest(Map map);
			public List manyTypesTest(int number, boolean bool, String string, double dbl, Date date, byte[] base64);
			public String moderateSizeArrayCheck(List list);
			public int nestedStructTest(Map map);
			public Map simpleStructReturnTest(int number);
		}
		

With a mapping file:

		<?xml version="1.0"?>
		<xmlrpc>
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.validator.IValidator:int:arrayOfStructsTest:java.util.List"
				external="validator1.arrayOfStructsTest" />

			<method internal="com.mjh.switchrmi.protocol.xmlrpc.validator.IValidator:java.util.Map:countTheEntities:java.lang.String"
				external="validator1.countTheEntities" />
		
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.validator.IValidator:int:easyStructTest:java.util.Map"
				external="validator1.easyStructTest" />
		
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.validator.IValidator:java.util.Map:echoStructTest:java.util.Map"
				external="validator1.echoStructTest" />
		
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.validator.IValidator:String:moderateSizeArrayCheck:java.util.List"
				external="validator1.moderateSizeArrayCheck" />
		
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.validator.IValidator:int:nestedStructTest:java.util.Map"
				external="validator1.nestedStructTest" />
		
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.validator.IValidator:java.util.Map:simpleStructReturnTest:int"
				external="validator1.simpleStructReturnTest" />
		
			<method internal="com.mjh.switchrmi.protocol.xmlrpc.validator.IValidator:java.util.List:manyTypesTest:int:boolean:java.lang.String:double:java.util.Date:[B"
				external="validator1.manyTypesTest" />

		</xmlrpc>