In the previous post I showed how you can make a Spring wrapper around the WebServer object and thus configure it easily in Spring-based applications. This solution is good for standalone applications that use Spring as a configuration mechanism.
But if you are using Spring MVC to develop web applications you probably don’t want to start another web server to handle XML-RPC calls. Instead, we have to find a way to configure XML-RPC to work with the web server that hosts our application and again to use our beans as XML-RPC handlers.
On the first look I thought that the easiest way to achieve this is to wrap the XmlRpcServlet (available from version 3.0 on) in the ServletWrappingController. But when I started looking at the code I found a solution that is much more simple and elegant.
The only thing we have to do is to make a Controller that will wrap the XmlRpcServer class and map this controller to handle desired requests.
package net.nighttale.spring.xmlrpc;
import java.util.HashMap;
import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.xmlrpc.XmlRpcServer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
/**
* @author Dejan Bosanac
*
*/
public class XmlRpcController extends AbstractController
implements InitializingBean {
XmlRpcServer server = new XmlRpcServer();
HashMap handlers = new HashMap();
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
byte[] resp = server.execute(request.getInputStream());
response.getOutputStream().write(resp);
return null;
}
public void setHandlers(HashMap handlers) {
this.handlers = handlers;
}
public void afterPropertiesSet() throws Exception {
for (Iterator it = handlers.keySet().iterator(); it.hasNext();) {
String key = (String)it.next();
Object value = handlers.get(key);
server.addHandler(key, value);
}
}
}
Now it’s time to configure this controller. First we have to add something like this in the web.xml deployment descriptor.
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/xmlrpc/</url-pattern>
</servlet-mapping>
This will instruct our DispatcherServlet to handle the appropriate URL, such as http://localhost/app/xmlrpc/, which we plan to use for our XML-RPC calls.
Next, we have to define our XmlRpcController and the handlers we are going to use (we will use the TestHandler from the previous post). For that, we have to add the following in the appropriate Spring MVC configuration file (/WEB-INF/spring-servlet.xml in our case).
<bean name="testHandler"
class="net.nighttale.spring.xmlrpc.TestHandler">
</bean>
<bean id="xmlrpcController"
class="net.nighttale.spring.xmlrpc.XmlRpcController">
<property name="handlers">
<map>
<entry>
<key><value>test</value></key>
<ref bean="testHandler"/>
</entry>
</map>
</property>
</bean>
Finally, we have to map a desired URL to this controller. In order to do that we have to put the following line in the appropriate URL mapping bean.
<prop key="/public/xmlrpc/">xmlrpcController</prop>
After all these steps, our web application is XML-RPC enabled. Of course, in this case the security issues must be addressed at the web server and spring application levels, just as it is with any other application resource.


I assume this is version 2.0, since XmlRpcServer#addHandler doesn't exist in 3.0.
Trejkaz is absolutely correct - the above example would not work with version 3.0. And this is not just because the addHandler() method doesn't exist, but because one is not supposed to use the XmlRpcServer class directly anymore. Instead, things have become more simple and complicated at the same time. The xml-rpc server now has its own IoC paradigm and configuring a server is as easy as creating a properties file containing the handlers and an entry in the web.xml. However, wrapping it into a Spring controller is also not too complicated - just much different.
I might create a blog about that on my page if I have the time to do this and add the URL to this blog as a comment later.