Anyone using this library probably has rox in their headers ...

Getting Started

If you're really looking to get started quickly take a look over the examples.

Still here? Excellent.

The best place to start is with an idea of what Rox tries to achieve. Although the initial driver for Rox was scaling to large numbers of concurrent connections most of my energy subsequent to that has been focused on making using Rox as natural as possible. As a result, at the moment this documentation focuses largely on that, rather than delving into the intricacies of NIO or SSL. When I get a chance I'll add some documentation covering these other topics.

This documentation will look at using Rox from the point of view of writing minimal code and of making as much of the code you do write as "natural" as possible. Natural in this context means the code should not look out of place in the context of the rest of your (non XML-RPC) Java code. In those cases where there are alternatives that I consider less natural (but are sometimes more efficient or more flexible) I'll mention them in passing. In truth though, there's a fair bit to Rox if you dig deep enough and my aim with this documentation is to get you started quickly and assist you when you have questions without getting bogged down in unnecessary special cases or detail that won't help the majority of programmers.

I've split this documentation into client and server oriented discussions. There's a lot of overlap, mostly related to how objects are marshalled, since that has to happen for both requests and responses. Often you're faced with the task of writing either a client or a server with someone else handling the other side of the picture. Even if you aren't writing both the client and the server I recommend a glance through both sets of documentation, if only so you have an idea of what the other side is likely to be doing with whatever it is you're sending them.

So without further ado, let's take a look at the client side of the picture.

Some terminology

Like any new technology, XML-RPC comes complete with it's own set of jargon. Some of this is general to both the client and server side of the picture (although the signifance may vary) so it's worth covering them before diving into anything.

Mount Point

The term mount point seems to have been introduced by the Apache XML-RPC developers. In the XML-RPC specification it's (correctly) referred to as the URI. I'll use the term interchangeably. This is the URI value sent as part of the HTTP request line to indicate which "page" the client wants. In an XML-RPC method call request everything required to look up the "page" on the server is present as part of the XML-RPC request. So the URI isn't really necessary. The XML-RPC specification suggests that servers might use the URI in a way that essentially amounts to a namespace specifier. Think of it as one way of dividing up the possible XML-RPC requests when choosing which piece of code should handle what. Rox supports using URIs in this way, but it also supports a slightly more "natural" mechanism which is discussed later as part of a look at the server side of the picture.

Persistent HTTP Connections

This isn't really specific to XML-RPC but it's relevant in the context of Rox. Rox implements HTTP 1.1 (the subset that applies to XML-RPC at any rate). This means Rox supports persistent connections. On the server side connections are not closed when a response is sent (except in cases required by the HTTP 1.1 specification). On the client side Rox will transparently reuse connections. More on the latter later.

The client side of things

In a nutshell, invoking an XML-RPC method call requires three things:

  1. A URL which really consists of two things, a host to send the request to, and a URI, sometimes referred to as the mount-point for an XML-RPC service.
  2. A method name.
  3. A list of method parameters.

Of these only the host and the method name are actually mandatory. The host, port and mount point are specified in the form of a URL. Actually, the host, port and the mount point are specified in the form of a URL when constructing a new XML-RPC client instance. The method name and parameters are specified when you invoke a method using one of the execute() methods.

Whether or not you need to provide a URI at all depends on the server. XML-RPC leaves it entirely up to implementations as to whether or not the URI is signifant. On the client side of things there's not much to the URI. If the server you're talking to requires something specific then include it in the URL you pass to the client. If not, well then it's irrelevant.

As mentioned earlier, Rox implements HTTP version 1.1. If the server also implements HTTP 1.1 then Rox will reuse connections whenever possible. A pool of recently used connections is maintained under the covers. Whenever a connection is returned to this pool Rox takes a quick look at the other connections in the pool. If they haven't been used for 5 seconds (currently this can't be configured) then they are closed. Closing these unused connections avoids unnecessarily hanging onto large numbers of idle connections. Pooling connections avoids the cost of establishing a new connection for each method call (particularly important if you're using SSL because of the cost of the handshake).

The only caveat around connection pooling is this. The number of connections in the pool is not capped by Rox (currently anyway, this may change in the future). When you're using the synchronous client side API this probably won't matter to you because the number of connections will be inherently limited by the number of threads you can create. However, if you're using the asynchronous client side API then you need to be aware of this or you might easily consume all of your local connections because you're issuing requests faster than the remote server can process them.

Which brings us neatly around to the asynchronous client side API. I'm not going to spend too much time delving into this, since it isn't really the most natural way to invoke methods. Most of the time method invocations are synchronous. If you want to do something asynchronously then you have to build it yourself (and even so the method calls themselves are still synchronous). But, normally you aren't facing method call latencies of the order of hundreds of milliseconds. When that happens often the only realistic approach is to make the call asynchronously and get on with other processing (usually making other asynchronous calls) while you wait for a response. Rox supports asynchronous calls on the client side by providing overloaded execute() methods that take a ResponseHandler implementation. The ResponseHandler is the callback via which you're notified when a method response is available.

All of this is great until you actually want to start calling methods. This is where (in my humble opinion) Rox starts to shine. Rox sports a slew of execute() methods but they could hardly be called "natural". There's a much easier way to use Rox to invoke remote methods. The first step is to create an interface that defines all of the methods you want to invoke on the remote server. Feel free to use whatever types you need for parameters (see the types table below to see what Rox supports), as long as they're compatible with the remote server. If the remote server is expecting a list of integer values then go right ahead and declare a parameter of type int[].

Once you have your server interface pass it to the proxyObject() method. The returned object implements the interface you passed in, so feel free to cast it back to that interface to use it. This is where the magic happens. Whenever you invoke one of the methods on the returned object Rox will translate it into an XML-RPC method call under the hood, transparently. It can't get much easier than that.

The server side of things

On the server side of things there's marginally more work to do. But only marginally. Handling XML-RPC method calls requires (oddly enough) a RequestHandler. When you register a request handler you need to give Rox two pieces of information it needs to decide which handler to pass incoming method calls to. The first of these is a URI (mount point). This can be null, in which case Rox will ignore the URI in the HTTP request. The second piece of information you need to provide Rox with is a regular expression describing the method names your handler is responsible for. Rox uses a regular expression because it's not uncommon to have a single handler be responsible for a collection of methods (grouped together using a common prefix for example).

Rox supports both synchronous and asynchronous handlers. The former are simpler to use, Rox will invoke a method defined on the handler instance and the return value is sent back to the client as the XML-RPC method response. The calling thread is one of Rox's worker threads, so tying it up for too long may impact the server's throughput. One way to address this is to increase the number of worker threads using the addWorker() method. However, this doesn't scale tremendously well. If processing a request is expensive, or if you need to scale to large numbers of simultaneous requests then you probably want to take a look at writing an asynchronous handler. When Rox invokes an asynchronous handler it passed in a ResponseChannel. Your handler can pass the request and response channel off to another thread and process it at your leisure. When you're done the response channel can be used to send the response back to the client. This frees up the worker thread to unpack other responses.

Writing a handler is pretty simple. You're passed an object encapsulating the XML-RPC method and it's parameters and you construct and return an appropriate XML-RPC method response. But I promised you a more natural way of doing things and this doesn't exactly fit the bill. If you take a closer look you'll see a registerProxyingHandler() method. As with the other methods for registering handlers you pass this one a URI and regular expression. You also pass it an object and once again, this is where the magic starts. Rox will inspect this object and register a handler for it that maps incoming methods and their parameters onto methods on the object. Parameters can be of any type Rox supports, so that int[] parameter we mentioned on the client side is perfectly acceptable here. The only additional piece Rox needs from you is a group within the regular expression. Rox will use the first group from the regular expression to look up the Java method. So you can register a handler for methods that share a common prefix and with an appropriate regular expression indicate to Rox that only the portion after the prefix should be used to look up Java methods. Only the method name is used to locate methods and which method Rox will try to invoke is undefined if you overload methods on a class (this may change in future). The parameters defined on the chosen method will be used when unmarshalling XML-RPC structs.

Sometimes you want control over whether or not Rox should even bother accepting a new client request. This is possible by implementing an AcceptPolicy and passing it to the appropriate XmlRpcServer() constructor. If an accept policy is installed Rox will check with it after accepting a new client connection. If the accept policy indicates that the connection should not be retained then it is closed immediately.

Threading in Rox

Rox uses the same underlying threading model for both clients and servers. One thread is responsible for monitoring I/O on the sockets "in play". This thread is responsible for accepting new connections on the server side, requesting and completing new connections on the client side, and reading and writing data when socket's become available. As data is read off socket's this thread collects packets from the same socket together until a complete HTTP message has been received. At this point the message is handed off to a pool of worker threads.

Worker threads can be added or removed dynamically using the addWorker() and removeWorker() methods. There's also a convenience method for adding more than one worker thread in a single call. If no worker threads have been added by the time you start the client or server Rox will add one for you. If you do add any worker threads then Rox will not add any. So calling addWorker() once before starting the instance will result in a single worker thread (not two).

How Rox marshals (and unmarshals) Java objects

Rox is pretty capable when it comes to marshalling an XML-RPC method call or response. Parameters and return values can be of pretty much any type you want. Primitive types (and their Object equivalents) will be marshalled using the appropriate XML-RPC equivalent. java.util.List instances and arrays will be marshalled as XML-RPC arrays. java.util.Map instances and any other Object will be marshalled as structs. When marshalling an Object Rox uses a combination of Bean introspection and looking at public fields to decide what should be marshalled. Bean properties and public field names are used as struct member names during marshalling. If there's an overlap and a Bean getter or setter exists for a public method Rox will prefer the method.

When Rox unmarshals an XML-RPC method call or response it handles simple types pretty much as you'd expect. However Rox has to decide what to do with complex values, specifically arrays and structs. Without any additional information Rox will produce instances of java.util.List and java.util.Map. However, if you provide Rox with a starting point it can do much, much better than that. On the request side this means providing Rox with a java.lang.Class instance for each positional parameter that is a complex value. A null value can be used if you want a java.util.List or java.util.Map instance, or if the parameter isn't a complex type. If this mapping has to be dynamic (for example, if you're writing a handler that is responsible for multiple methods then the parameter types will probably depend on the method being invoked) then you can use an UnmarshallerAid. But more on that shortly.

Out of the box, when Rox marshals your own Objects it uses the field name as the XML-RPC struct member name. Rox's default behaviour is to translate the Java field name by splitting it on capital letter, convering all the resulting strings to lowercase and rejoining them using hyphens. When unmarshalling it inverts this process. This is largely an artifact of the environment in which I developed Rox. You may want Rox to do something different here or your field names may use a different naming convention. Whatever the reason, the thing you're looking for is the FieldNameCodec interface. This let's you plug in different logic for encoding and decoding field names during marshalling and unmarshalling respectively. Take a look at the JavaDoc Use page for the interface to get an idea of where to plug it in. Yes, I'm lazy and this should be far more detailed. I'll get there.

The table below illustrates a few examples of the mapping provided by the default field codec implementation.

XML-RPC member name Java field name
field field
field-name fieldName
a-field-name aFieldName

I mentioned the UnmarshallerAid interface briefly earlier. This is a hook into the unmarshalling process that gives you a chance to plug in different logic at various stages. There's not much more to be said about it, but I thought it was worth pointing out since it's the entry point if you're looking to do anything fancy during unmarshalling (especially with mapping XML-RPC method parameters to an appropriate Java type).

XML-RPC type Java type Notes
int/i4 byte or java.lang.Byte
int/i4 short or java.lang.Short
int/i4 int or java.lang.Integer XML-RPC integer values are limited to 32 bits (signed). Java's integer (and long) support a larger range than this. Rox will refuse to marshal integer values that can't be handled by other implementations because they exceed the 32 bit range. However, RoX will accept integer values that exceed this range, provided they fit into the target member's range.
int/i4 long or java.lang.Long See the note above about integer ranges.
double float or java.lang.Float
double double or java.lang.Double
boolean boolean or java.lang.Boolean
string char or java.lang.Character
string java.lang.String
string char[] or java.lang.Character[] An array of characters is treated as a string. All other array types are treated as arrays.
dateTime.iso8601 java.util.Date All date values are in UTC.
base64 byte[] Note that java.lang.Byte[] values are marshalled as arrays of integers.
array Any Java array or an instance of java.util.List During unmarshalling, if the target field (or the relevant parameter Class provided) is an array type then it will be initialized with values of the correct type, if the XML-RPC array members are amenable.
struct Any Java object or an instance of java.util.Map Objects are marshalled as maps, using the name of accessible fields as "keys" after transforming them using the configured FieldNameCodec (the default codec is HyphenatedFieldNameCodec). During unmarshalling an instance of java.util.Map is created unless a parameter Class is provided.