Spring XmlRpcServiceExporter
Gary Blomquist asked me to share the Spring ServiceExporter mentioned in the previous post. Here is is:
package jteam.remoting.xmlrpc;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.xmlrpc.XmlRpcServer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.remoting.support.RemoteExporter;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.support.WebContentGenerator;
/**
* Web controller that exports the specified service bean as XML-RPC service
* endpoint, accessible via a XML-RPC proxy.
*
* XML-RPC is a simple, SOAP-like protocol. For more information, see the
* XML-RPC website.
*
* @author Arjen Poutsma
*/
public class XmlRpcServiceExporter
extends RemoteExporter
implements Controller, InitializingBean {
private XmlRpcServer server;
public void afterPropertiesSet()
throws Exception {
server = new XmlRpcServer();
server.addHandler(getServiceInterface().getName(), getProxyForService());
}
/**
* Process the incoming XML-RPC request and create a XML-RPC response.
*
* @param request current HTTP request
* @param response current HTTP response
* @return null
* @throws Exception in case of errors.
*/
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (!WebContentGenerator.METHOD_POST.equals(request.getMethod())) {
throw new ServletException(“XmlRpcServiceExporter only supports ” +
“POST requests”);
}
byte[] result = server.execute(request.getInputStream());
response.setContentType(“text/xml”);
response.setContentLength(result.length);
OutputStream output = response.getOutputStream();
output.write(result);
output.flush();
return null;
}
}
Nothing fancy. The full name of the service interface is used as a handler name. So if your interface is called jteam.businesslogic.TestManager, it gets exposed as jteam.businesslogic.TestManager.
This class depends on the Apache XML-RPC library to do the actual XML-RPC handling. This library does have it’s weaknesses: it uses the old, synchronized collections (Vector and Hashtable), and it does not handle XML-RPC structs very well, since it converts a struct into a Hashtable with the string names mapped to the value.
I would have preferred a more XStream-like approach, where the following struct:
<struct>
<member>
<name>lowerBound</name>
<value><i4>18</i4></value>
</member>
<member>
<name>upperBound</name>
<value><i4>139</i4></value>
</member>
</struct>
would have been converted into a bean with lowerBound and upperBound properties. If it bothers me too much, I will add this functionality myself.
Alef said,
February 13, 2005 @ 23:53
Well, like I said in my mail already, it’s gonna be hard to get full serializability for all your arguments. Normale beans and arrays work, but once you start to use collections, you can’t transform the structs into the necessary objects anymore (there’s not type information available). Then there’s properties that expose interfaces. You can go and guess a concrete type there. Finally there’s the objects that don’t adhere to the JavaBeans spec. You’ll need property editors for those, but that’s something I think you don’t want since you want to have completely transparent RPC.
Well, on the other side, it works for simple beans. I think we’ll have to add this to the Spring sandbox soon.
Steve Daly said,
July 27, 2005 @ 17:56
Can you post an example of how to configure this exporter with a service in the application context config file?
TIA,
Steve
Arjen said,
July 29, 2005 @ 14:26
You would configure it like any other
RemoteExporter. Refer to the Spring Reference documentation on remoting for more info.