Release 1.2 ===================== - Fixed a bug in the SaxUnmarshaller that prevented internal state from correctly being reset when unmarshalling failed while handling a nested struct or array. - Improved error detection when a complex type is being unmarshalled and the target type is incompatible (e.g. unmarshalling a struct into a String member). - Introduced support for pipelining HTTP 1.1 requests (including POST requests, which violates the HTTP RFC but pipelining support for GET requests only is a little useless for XML-RPC). - Improved structural validation for XML-RPC messages. Release 1.1 ===================== - Stashing the SAXParserFactory instance for a (slight) performance increase. - Fixed a bug in the check for a reset() method on the SAXParser in use. - Pooled connections are now closed when a zero byte read occurs. - Giving up on supporting 1.4 only since it's starting to feel a bit antiquated and no longer worth the trouble. - Introduced rewritten SaxUnmarshaller. This implementation should function correctly with any off the shelf SAX parser. It's marginally slower than the previous implementation (but that's the price of correctness). - SSL support has been rewritten to use Java 1.5's SSLEngine instead of the black magic used prior to this release to combine NIO and SSL support on Java 1.4. SSL configuration is considerably more flexible. - As part of the SSL rewrite SSLSessionPolicy has been introduced, providing the ability to configure flexible session acceptance policy rules. - Much in the way of refactoring, some of which will break compatibility (but generally only for sub-classes, users of this library should be largely unaffected). Release 1.0 ===================== - Support for Java 1.5 improved. Rox will now load different marshalling implementations based on the Java runtime version. Under version 1.5 and higher support for generics and enumerated types is transparent. - Rox now supports optional automatic mapping of HTTP GET requests onto your XML-RPC method handlers. See the com.flat502.rox.server.CgiRequestUnmarshaller class for more details. - Connections from HTTP/1.0 clients are correctly terminated after a response has been returned (unless they're using HTTP/1.1-style keepalives). - Responses will now mirror the HTTP version of the request and HTTP 1.1 headers will not be included in these responses. - HttpRpcServer now supports an idle client timer. This is disabled by default. If set clients that are idle for a period exceeding the timeout specified are forcibly disconnected. Release 0.9 ===================== - The connection pool was only being scanned for aged connections when connections were returned. The pool is now also scanned when pooled connections are checked out. This ensures that aged connections are never used. - IOExceptions during a write operation resulted in a busy loop sending CPU usage to 100%. This exception is now handled and the offending channel is cancelled. - A logic error that caused connection pooling to stop expiring aged connections has been fixed. Release 0.8 ===================== - A new method has been added to the UnmarshallerAid base class that controls whether or not missing fields should be ignored when unmarshalling an XML-RPC struct into a Java type. Both the DOM and SAX unmarshaller honour this flag. - The UnmarshallerAid interface has been replaced with an abstract base class. Although slightly less convenient than an interface, this allows Rox to provide default implementations for some methods and supports evolving the class without breaking compatibility. As part of this change the functionality has been split into three classes, one base class and two that are specialized for call and response unmarshalling. - A number of other calls to methods only available on 1.5 have been replaced with equivalent calls that exist on 1.4. - The SAX marshaller pools parser instances to improve performance. This logic depends on the SAXParser.reset() method which was introduced in 1.5. We now check for the availability of this method and only call it if it exists (this check is done once). For efficiency's sake, if the method is not available but we're using our own parser imeplementation then we typecast and call the method directly. Thanks to Sandeep Raja Rao for reporting this problem. - The ChannelSelector was erroneously trying to read off unowned channels that were not yet connected. This resulted in a NotYetConnectedException that ultimately resulted in that channel being forcibly closed. - RemoteSocketClosedException is now logged at the TRACE level, since it happens frequently and isn't really an error condition. - The shared connection pool's logic for checking out a connection has been rewritten as part of work to address a problem that allowed more connections than the defined limit to be checked out and to address a NullPointerException that resulted because clients seen for the first time that could be satisfied with an existing pooled connection were not recorded. - The ThreadQueue class has been greatly simplified as part of work to address a rare race condition. The guarantees it makes are slightly weaker but still sufficient for the original (performance related) reasons it was written. - Corrected a NullPointerException that resulted from erroneously removing a pooled connection stack when a connection was closed remotely. - An unhandled exception within a TimerTask implementation cancelled the global request timer causing havoc and general dismay. - Corrected a NullPointerException that resulted from erroneously removing an active set when a connection was cleaned up when a timeout occurred just after a client had detached from the connection pool. Release 0.7 ===================== - NoSuchMethodException and NoSuchMethodError are reported by server instances using a 404 (Not Found) HTTP response code. - Shutting a server down did not correctly close established connections. - Remote closure of a connection that was pooled on the client side resulted in a deadlock because the wrong client was notified of the closure. - Timeout exceptions were closing the connection the timeout occurred on without notifying the connection pool, resulting in a logical resource leak. - Timeout exceptions are now raised within the context of the caller rather than the timer thread. - A common base class has been introduced for both timeout exceptions so uniform handling can easily be applied to both cases. - A default request timeout can now be configured on a ClientResourcePool. Any client instances sharing this pool will have their request timeout initialized based on this value. - When using a resource pool connection pooling is keyed on the protocol, host and port rather than on individual client instances. This allows client instances that shared a remote destination to share connections. - All instances of SimpleDateFormat are now retrieved from thread local storage. This ensures that these instances are never accessed by multiple threads simultaneously while avoiding creating unnecessary instances. - The synchronous client API will now raise a more specific IOException (RPCCallFailedException) if a non-timeout related error occurs invoking an XML-RPC method. - The resource pool mentioned previously is now responsible for connection pooling. This makes it possible restrict the number of open connections across a set of client instances. - It's now possible to associated an explicit pool of worker threads with a collection of client or server instances. This makes it possible to reuse I/O, worker and timer threads across a selected set of instances, which assists when trying to scale to large numbers of client or server instances by keeping the thread count under control. - Introduced a LogFactory class. The model for logging has changed in this release. Log instances are no longer associated with a particular client or server instance. Rather, they're "looked up" in much the same fashion as with Log4J. This is a slightly less flexible approach to logging since it effectively forces a single global logging strategy, but I don't feel this limitation is too serious (for now), and this simplifies logging and removes one coupling point between worker threads and client/server instances in anticipation of some upcoming changes. Release 0.6 ===================== - Various fixes to the SAX based unmarshaller when dealing with nested structs that must be mapped onto user-defined classes. - Corrected a logic error in the SAX unmarshaller that broke XML-RPC fault handling. - Some improvements to the SAX unmarshaller when handling messages that span buffers. - Corrected an error when handling an empty value within the SAX unmarshaller. - Fixed a buffer refill error in our internal XML parser. - Added logic to avoid reporting a ClosedSelectorException unnecessarily. - NullLog no longer logs errors to standard error by default. I'm still thinking about how best to handle this. Release 0.5 ===================== - The timeout for an SSL handshake is now configurable, and defaults to 10 seconds. - The underlying socket channel (connection) pool now supports a an optional limit. If set threads will be blocked when this limit is reached and held until capacity is once again available. A timeout may be configured for this blocking period. If exceeded an exception will be raised (releasing the blocked thread). The limit and timeout default to 0 (no limit, infinite timeout). - Support has been introduced for customizing the encoding used on the wire. An implementation supporting gzipping the RPC method content has been included. This API is still unstable and is subject to change (or possibly removal). Customizing the encoding is currently pretty expensive in space and only really makes sense if you're behind a really thin pipe or your requests are large. Oh, and this is a proprietary extension to XML-RPC but it should be compatible with other such "proprietary" extensions if they followed the intention of the HTTP specification with respect to content encodings. - As part of the work to support custom encodings the HTTP codebase now supports the Accept-Content header in all it's glory. - Fixed a DomUnmarshaller bug that meant directly compatible types were not correctly handled as part of the generic type coercion logic. A concrete side-effect was that Class members that were typed as a java.util.Map or java.util.List would not be correctly assigned during unmarshalling. - Fixed a bug which meant connections were being flushed from the connection pool irrespective of how recently they were used. - Removed a spurious ByteBuffer.put(). A send data buffer was being copied once more than was necessary for every write. - Fixed a bug in the XmlRpcSaxParser that corrupted ampersand entities. - Fixed a bug in the Base64 implementation. Decoding array subsets was broken. - The DomUnmarshaller now correctly handles members with a concrete List or Map type. - The SaxUnmarshaller now correctly handles members with a concrete List or Map type and type coercion has been brought into line with the DomUnmarshaller. - Numerous performance enhancements, including * a rewrite of the HTTP header parsing logic * a rewrite of the HTTP header marshalling logic * corrected logic that would reparse HTTP headers unnecessarily if an HTTP message was fragemented over multiple packets * tweaks in the NIO code to directly manipulate the Selector where permissable. * Removal of an unnecessary additional ByteBuffer write per send. * XML marshalling now avoids PrintStream and handles character encoding directly. * General cleanup of the SaxUnmarshaller and XmlRpcSaxParser so we can make these the default unmarshalling implementations for Rox (they're quite a bit faster than the DOM based solution). In all these changes have resulted in an order of magnitude increase in throughput with a single client performing synchronous calls in a tight loop (other tests pending). - A bunch of internal methods that are shared by both unmarshaller implementations have been exposed as utility routines. - If an RpcFault was received by an asynchronous client-side handler both handleException() handleResponse() were invoked. This has been corrected and only the former is invoked. - Some minor error handling improvements, including avoiding calling ResponseHandler.handleException() again if it raises an exception and trapping Throwable instead of Exception. - NullLog will now log errors to standard error by default. Release 0.4 ===================== - registerProxyingHandler() has been pushed down into XmlRpcServer, since it registers an XML-RPC specific handler. This should not affect existing code unless the server instance was being stored in a member of type HttpRpcServer. - HttpRpcServer and XmlRpcServer now use InetAddress instances instead of Strings for host addresses. I think this is more consistent with other, similar APIs, especially within the JDK. - HttpRpcProcessor now implements Runnable instead of extending Thread. - HttpRpcProcessor now sports a stop() method for shutting down a client or server. - String URIs (or mount points) are now used instead of URI instances. URI's normalization was sufficiently lacking so that it doesn't make sense to depend so heavily on this class. URI normalization has also been moved into Utils.normalizeURIPath() so we can cater explicitly for some edge cases. - Fixed a bug which resulted in a malformed Content-Type header being returned to the client if an exception occurred within a server-side handler. - When proxying objects on the server side Rox will now raise an exception if more than one method with a given name is declared on the target object (currently there is no support for method overloading and there are no immediate plans to support this). Methods declared on java.lang.Object are not included when proxying an Object. - Rox was erroneously expecting the HTTP Host header to be present in HTTP responses. They're only mandatory in requests. This has been fixed. - An XmlRpcFaultException has been introduced and RpcFaultException moved and modified to extend RuntimeException. This exception can be raised if explicit control over the XML RPC fault returned to the client is required from within a method on a proxied server side Object and you don't want to (or can't) modify the throws clause on that method. - Final fields are now skipped during marshalling and unmarshalling. - Client-side timeouts are now supported. Timeouts are set per client instance, but can be changed on an existing instance. By default there is no timeout. If a request times out the connection on which the request is pending is closed. Release 0.3 ===================== - Fixed a bug which produced malformed XML for XML-RPC faults. - Byte, Short and their respective primitive types are now marshalled as ints. - Character (and char) are marshalled as a single character string. - The ParameterTypeMapper interface has been replaced by a more general UnmarshallerAid which supports pluggable FieldNameCodec implementations as well as parameter type mapping. - The logic governing Class member introspection has been extracted into a new class (ClassDescriptor). In addition to centralizing this logic this new class caches class member information upfront which should result in a performance improvement when repeatedly marshalling or unmarshalling objects of the same type. - A new utility method has been added to HttpRpcServer to simplify using a synchronous proxying request handler. - Method lookup on the server side when proxying an object is more general (and hopefully more useful as a result). Names are matched case-insensitively after dropping '-' and '_'. - Static fields were being included when marshalling or unmarshalling objects. They're now skipped (along with transient fields). - Encoded field names are cached as they're computed to reduce the cost of repeatedly marshalling instances of the same class. - In the spirit of being "strict in what you produce and tolerant in what you accept" RoX will now raise an exception if an integer value exceeds the range defined by the XML-RPC specification (32 bits, signed). RoX will accept integer values that exceed this range, provided they fit into the target member's range. - Convenience methods have been added for configuring and querying the number of worker threads on an HttpRpcProcessor instance. Release 0.2 ===================== - The AcceptPolicy interface has changed slightly. In addition to the new SocketChannel an (approximate) indication of the number of existing connections is passed to the policy implementation. - Fixed a race condition during connection establishment which resulted in requests occasionally failing to be sent to the server. - Fixed a bug that meant if the remote entity shuts a connection down cleanly during a read the caller wasn't notified. A specific IOException exception (RemoteSocketClosedException) is passed to the caller to indicate this case. - All the boolean test methods on the Log interface now take a Class context parameter so implementations can make the most informed decision about whether or not a given logging action should be allowed. - Log4J has been added to the RoX project, along with a Log4J adapter implementation of the Log interface. This adapter class is built into a separate (optional) extension JAR (rox-log4j.jar). - Introspected Fields are cached. Class.getField() is pretty expensive in the general case. - Support has been added for selecting between compact XML for efficiency, or more readable but less efficient XML for debugging. - The ResponseChannel interface now has a close() method on it allowing asynchronous server-side method call handlers to close the channel on which a response would normally be sent. - When unmarshalling a struct member where the Java Object member is an array type with a component type other than Object RoX will marshal an array of instances of the component type. So if you have a field (public or accessible via a setter) of type Foo[] then it will be populated with instances of Foo (assuming the data within the XML-RPC array is amenable). - Fixed a bug that would result in a NullPointerException instead of a more informative exception if no field or setter could be located for a struct member. - Support has been added for marshalling and unmarshalling arrays of primitive types (int, long, double, float and boolean). - Support has been added for marshalling and unmarshalling multi-dimensional (well, they're really jagged) arrays, of both primitive types and POJOs. - XmlRpcMethod and kin have been refactored to split out unmarshalling. Marshalling is still the province of this class but unmarshalling is now handled by implementations of a new pair of interfaces, one for method calls and one for method responses. The (DOM based) unmarshalling logic in XmlRpcMethod has been moved out into concrete implementations of these interfaces. This required a number of incompatible interface changes. - An interface encapsulating common XML-RPC constants has been introduced. - An experimental SAX based unmarshaller is included with this release. It's by no means finished yet and the interface exposed is still under review. Thanks to Roland Patterson-Jones for this contribution (and some testing and debugging). - Fixed a bug that broke server side proxying when parameter types were user-defined structs. - Field name encoding/decoding is now pluggable. RoX still defaults to assuming hyphenated fields for XML-RPC struct member names and camelCase for Java member names. - As of this release RoX passes the validation suite published at http://validator.xmlrpc.com/ The source code for the server can be found in the class com.flat502.rox.demo.validation.ValidationSuiteServer. There's also a client implementation for testing locally. - Presence of the Host header was being enforced irrespective of the HTTP version in the message. This is now only enforced for HTTP 1.1 messages. Release 0.1 ===================== - First public release - This is really an alpha release