At FinScope we built a general purpose library alongside our automated trading product. We used Open Source components for their obvious virtues as well as to save time. It's now time to repay the favour. After some revisions and improvements I am now releasing the library to the community.
The primary purpose of this library is to make scalable, flexible and message-based applications quicker and easier to write. Since writing any application places demands on the memory, I have tried to add as little as possible to what is already publicly available.
The packages in this library mirror the Java or third party packages they are intended to work with. Where possible
I use the same package names. There are some other conventions I have adopted. First, the root package
contains only the core classes and resources needed to make something work;
utilities and other, non-essential, embellishments are in
a subpackage named .etc
. Second, each package is internationalised with a resource bundle:
see the section on configuration for more details on this.
The packages in the library are:
Package name | Role | |
---|---|---|
configuration | Defining how classes can be configured and internationalised. | |
dataset | A generic data container. | |
http | Embedding the Simple HTTP engine in applications. | |
javascript | Embedding JavaScript in applications. | |
jms | Java Messaging made even simpler. | |
logging | An implementation of Java logging. | |
maths | Further maths. | |
multicast | An framework for multicasting. | |
pattern | Design pattern implementations. | |
util | Utilities |
These packages are described in the remainder of this page. Names in code font
refer to classes and resources in the library.
Java Properties objects are the foundation for configuration throughout the
library. The Configurable
interface marks its implementers as being able to be configured
using a properties object. As Properties only supports string values,
a JavaProperties
class provides a facade onto a properties object with
Java type specific access methods.
ClassPathConfiguration
is a singleton which can load properties files (note, with the
suffix .conf
rather than .properties
) from the class path, either for a name or specific class.
Each package in the library is internationalised through using a resource bundle for text specific to
that package.
The LanguageResources
class is a singleton that loads a number of resource bundles and
uses these as text resources or message formats. LanguageResources
has a subclass in each
package which offers a shortcut singleton to the specific resource bundle for that package. All text output,
for logging or exceptions, is translated from the bundle. The resource bundle is even used for XML
formatting in the http package.
Many applications end up implementing a generic container for name-value pairs and this library
is no exception. The DataSet
class provides Java type accessor methods to a TreeMap: the package
also defines an adapter interface to allow datasets to be quickly transformed. See, for example, the
JMS package for a JMS map message DataSet adapter.
Applications can be made more usable through making them HTTP aware. This does not always mean
writing them as a web application; an alternative is to embed an HTTP engine into the application.
The Simple HTTP engine is a particularly straightforward
and efficient way of going this. The principal class in this library package, HttpServer
makes
embedding Simple a little easier through wrapping the server oriented
Simple objects in a singleton.HttpServer
allows servlets to be loaded and
the HTTP service to be started and stopped. The LoggingServlet
in the package extension
illustrates both how Java logging can be controlled through HTTP and how the package language resource
bundle can be used for XML formatting.
The Simple classes are a prerequisite for this package.
Using the HttpServer
requires minimal coding. First, get the singleton and configure
it with a properties file.
public void begin() { HttpServer http = HttpServer.getInstance(); http.configure(this.properties); ...
The properties file, which of course may include other application properties, must contain the HTTP port number for the service, for example;
http.port = 30000
Next load implementations of the Simple BasicService class and assign them to their uri's. Then start the service and, when needed, stop it.
... http.load(LoggingServlet.class, "/admin/logging"); http.load(StopServlet.class, "/admin/stop", this); http.start(); } public void end() { HttpServer.getInstance().stop(); }
The javascript
package provides convenience classes for embedding the mozilla
Rhino JavaScript interpreter. The two classes in this
package implement the tiered scopes suggested by mozilla for improved performance: the JavaScript
singleton initialises a root scope with the standard JavaScript objects; while the Scope
class
fills the gap with Rhino in that there is no supplied object to represent a scope. Scope
offers
convenience methods for evaluating strings and files, and for instantiating JavaScript objects, arrays and Dates
within the scope.
The .etc
package contains a class for implementing various Java and library methods through
a host object in JavScript.
The Rhino classes are a prerequisite for this package.
This package provides two closely cooperating classes for using JMS topics. The JMSSession
singleton handles all the connectivity with the JMS provider, and is also a factory for
making and keeping JMSTopic
objects. Each JMSTopic
provides a single point
for subscribing, publishing and requesting messages over a topic.
The package uses a JMS correlation id scheme which allows both requests and responses over the same JMS topic.
An example implementation with these classes. Get the session singleton and configure it with properties. Then open the session.
public void begin() { JMSSession jms = JMSSession.getInstance(); jms.configure(this.properties); jms.open(); }
The properties need to contain slightly more than with the http
package.
Here is an example for Fiorano;
# # JMS provider configuration. # java.naming.security.principal = anonymous java.naming.security.credentials = anonymous java.naming.provider.url = http://localhost:1856 java.naming.factory.initial = fiorano.jms.runtime.naming.FioranoInitialContextFactory # # Session configuration. # connection.factory = PrimaryTCF
Once the session is open, add any subscribers (implementors of the JMS MessageListener
interface) for topics using the JMSTopic
class, then start receiving messages.
public void subscribe() { JMSSession jms = JMSSession.getInstance(); JMSTopic ticker = jms.getTopic("ticker"); ticker.subscribe(new TickerListener(this)); jms.startReceiving(); }
Each JMS topic should have the message time to live and priority configured in the same JMS properties as above. For example, with the 'ticker' topic;
# # TICKER topic configuration. # ticker.time.to.live = 60000 ticker.priority = 4
The JMSTopic
instances provide publishing and requesting methods as well;
public void publish() { JMSTopic ticker = JMSSession.getInstance().getTopic("ticker"); MapMessage msg = ticker.makeMapMessage(); ... ticker.publish(msg); } public void request() { JMSTopic ticker = JMSSession.getInstance().getTopic("ticker"); MapMessage request = ticker.makeMapMessage(); ... MapMessage reply = ticker.request(request); }
The decision on logging was difficult not because it is controversial - the library uses logging to advise on all status and exceptions - but because of preferences in the underlying logging package. I have used log4j and will doubtless extend the library logging package to use it; but for now this package is a simple implementation of Java logging.
The maths
package principally contains classes oriented towards finance, including
a Black-Scholes options model. Subpackages also define a range of average price calculators
(simple and exponential moving averages, plus VWAP and TWAP); and stock price models.
The multicast
package implements a framework for multicasting which is similar
to JMS. A MulticastSession
class defines the IP address and character conversion
for the session, plus methods for sending multicast packets using a given protocol.
The .etc
package defines two such protocols: an elementary protocol and another,
MulticastSessionProtocol
which prevents published packets from being received
by an observer with the same session id.
Of course, the prime reference for this is the Design Patterns book (ISBN 0-201-63361-2). I have followed the naming conventions of the authors wherever possible. Some of the patterns are simply marker interfaces, for example those for Singleton and Visitor. The memento pattern is more elaborate, as there are interfaces for both the Memento and the MementoOriginator. The Memento interface also allows for an (optional) persistence mechanism using byte arrays.
One pattern that is not in Design Patterns is closure. I was introduced to this by Mark Chaplin and have persisted with it because of its benefits. The principle of closures is that a class owning a collection of objects does not expose an iterator on that collection but instead implements methods which allow a visitor-like class to see each member in the collection. The advantages are that the owner keeps control over synchronisation, casting and the sequence and selection for the iteration: the exposed methods are much like a query language on the collection. The downside (for some) is that the implementation of the visitor usually requires inner classes.
For example; a closure on some class ...
public interface ThingClosure extends Closure { public void visit(Thing thing); }
... with some things owned by another class ...
public class ThingOwner { private Thing[] things; public void forEachOddThing(ThingClosure closure) { for (int i = 0; i < this.things.length; i += 2) { closure.visit(things[i]); } } }
... and an application which needs to see these things.
public class Application { private ThingOwner owner; public void execute() { this.owner.forEachOddThing(new ThingClosure() { public void visit(Thing thing) { //do something } }); } }
This package contains some classes with useful methods for dealing with byte arrays,
Bytes
, and strings, Strings
. There is also a text formatting
class and a Java Date equivalent for universal time, UTC
.