What is the state of Apache XML-RPC, version 3?

It is alpha software. In other words, it is not yet sufficiently mature. Most possibly, lots of details will change in the near future. Give it a try, if you like, but do not expect to use it without modifications in the medium term.

[top]
How do I enable request compression?

That's simple: Set the properties "enabledForExtensions" and "gzipCompressing". That said, note the following hints:

  • Setting these properties will only work, if the XML-RPC server is aware of request compression. Compression is a violation of the XML-RPC specification, so typically the server will refuse the request, unless it is an Apache XML-RPC server with version 2 or later. (Apache XML-RPC 2 supports request compression, although it was officially designed to be strictly compliant to the XML-RPC specification. However, noone was aware, that compression violates the specification. :-)
  • Compressing the request doesn't mean that the response will also be compressed. You need to request response compression to achieve that.
  • Additionally, be aware of the following: Compression depends on HTTP/1.1 features. In particular, you must not use the LiteHttpTransport.
[top]

How do I enable response compression?

That's as simple as enabling request compression: Set the properties "enabledForExtensions" and "gzipRequesting". That said, note the following hints:

  • Requesting gzip compression is a standard HTTP feature. In other words, you may safely request compression from any XML-RPC server, even if it doesn't run Apache XML-RPC.
  • However, requesting compression doesn't necessarily mean, that the response *is* compressed. It depends on the server.
  • Additionally, be aware of the following: Compression depends on HTTP/1.1 features. In particular, you must not use the LiteHttpTransport.
[top]

Is it possible to specify a timeout, after which the client stops waiting for the servers response?

Yes, use the class TimingOutCallback.

<![CDATA[
    // Wait for 10 seconds.
    TimingOutCallback callback = new TimingOutCallback(10 * 1000);
    XmlRpcClient client = new XmlRpcClient(url);
    client.executeAsync(methodName, params, callback);
    try {
        return callback.waitForResponse();
    } catch (TimeoutException e) {
        System.out.println("No response from server.");
    } catch (Exception e) {
        System.out.println("Server returned an error message.");
    }
        ]]>
[top]
How do I enable streaming mode?

Set the property "enabledForExtensions". Note, that enabling the streaming mode doesn't mean, that all responses are served in streaming mode. It depends on the clients:

  • If a client sends a content-length header, then the server assumes, that the client is a traditional XML-RPC application and doesn't support the vendor extensions from Apache XML-RPC. Consequently, the server assumes, that it needs to set the content-length header itself and disables the streaming mode for that particular request.
  • However, if the client doesn't send a content-length header, then the server assumes that it will be able to accept any standard HTTP/1.1 request and enable the streaming mode. Streaming mode means, in particular, that the response will not contain a content-length header.
[top]

How do I enable streaming mode?

Set the property "enabledForExtensions". Note, that enabling the streaming mode doesn't mean, that all responses are served in streaming mode. It depends on the clients:

  • If a client sends a content-length header, then the server assumes, that the client is a traditional XML-RPC application and doesn't support the vendor extensions from Apache XML-RPC. Consequently, the server assumes, that it needs to set the content-length header itself and disables the streaming mode for that particular request.
  • However, if the client doesn't send a content-length header, then the server assumes that it will be able to accept any standard HTTP/1.1 request and enable the streaming mode. Streaming mode means, in particular, that the response will not contain a content-length header.
[top]

How do I initalize the handler objects?

The PropertyHandlerMapping assumes, that handlers are POJO's (plain old java objects). However, this is not always desirable. For example, sometimes it is assumed that handlers need to be initialized by the servlet, which is configured through parameters.

The recommended solution is to create a subclass of the XmlRpcServlet, which in turn uses a subclass of the PropertyHandlerMapping:

<![CDATA[
public interface InitializableHandler {
    void init(HttpServlet pServlet) throws XmlRpcException;
}

public class MyXmlRpcServlet extends XmlRpcServlet {
    protected PropertyHandlerMapping newPropertyHandlerMapping(URL url) throws IOException, XmlRpcException {
		return new PropertyHandlerMapping(getClass().getClassLoader(), url){
		    protected Object newHandlerObject(ClassLoader pClassLoader, String pClassName)
		            throws XmlRpcException {
		        Object o = super.newHandlerObject(pClassLoader, pClassName);
		        ((InitializableHandler) o).init(MyXmlRpcServlet.this);
		        return o;
		    }
		};
	}
    
}
        ]]>
[top]

How to I get the clients IP address in a handler?

That's a similar question than the question on initializing handlers. The main difference is, that in this case you want to initialize the handler with any request. So, here's how to do it: First of all, we assume that all handlers will implement an interface RequestInitializableHandler. This interface has an init method, which is being called to receive an object with the clients IP address:

<![CDATA[
public class MyConfig extends XmlRpcHttpRequestConfigImpl {
	private String clientIpAddress;
	public String getClientIpAddress() {
	    return clientIpAddress;
	}
	public void setClientIpAddress(String pClientIpAddress) {
	    clientIpAddress = pClientIpAddress;
	}
}

public interface RequestInitializableHandler {
    public void init(MyConfig pConfig);
}

public class MyXmlRpcServlet extends XmlRpcServlet {
	protected XmlRpcServletServer newXmlRpcServer(ServletConfig pConfig)
			throws XmlRpcException {
		return new XmlRpcServletServer(){
	        protected XmlRpcHttpRequestConfigImpl newConfig(HttpServletRequest pRequest) {
	            MyConfig config = new MyConfig();
	            config.setClientIpAddress(pRequest.getRemoteAddr());
	            return config;
	        }
		};
	}
	protected PropertyHandlerMapping newPropertyHandlerMapping(URL url) throws IOException, XmlRpcException {
		PropertyHandlerMapping result = super.newPropertyHandlerMapping(url);
		result.setInitializableHandler(new InitializableHandler(){
            public void init(XmlRpcRequest pRequest, Object pObject)
                    throws XmlRpcException {
                ((RequestInitializableHandler) pObject).init((MyConfig) pRequest.getConfig());
            }
		});
		return result;
	}
}
        ]]>
[top]