Caplin DataSource for Java SDK 4.4.7

The Caplin DataSource for Java SDK (Software Development Kit) is a library of classes that enables developers to create applications that can send and receive financial market data in the form of structured records and fields, pages, news headlines and news stories to and from other DataSource-enabled applications, using Caplin's DataSource protocol.

See:
          Description

Packages
com.caplin.config.util Provides utility classes to aid configuration of Caplin products.
com.caplin.config.xml Provides XML configuration with optional type safety and Java class instantiation.
com.caplin.datasrc The main package for the Java DataSource Developers Kit classes.
com.caplin.datasrc.cache Provides a caching mechanism which allows a DataSource to turn a broadcast source into an active one.
com.caplin.datasrc.delay Provides the ability to create one or more delay channels for sending data to peers after a specified delay period.
com.caplin.datasrc.fields Provides field management interfaces and classes that represent all the configured fields that are available.
com.caplin.datasrc.interfaces Defines the main data interfaces used by DataSource for Java SDK and related products.
com.caplin.datasrc.latencychain  
com.caplin.datasrc.logging.application Contains XML Configuration classes to allow configuration of a standard Logger instance for DataSource application logging.
com.caplin.datasrc.logging.packet Provides packet-level logging of DataSource communications with peers.
com.caplin.datasrc.mapping.object Provides object name mapping utility classes.
com.caplin.datasrc.udp Provides the DataSource specific implementation of UDP message send and receive functionality.
com.caplin.event Provides event related functionality such as: an event loop and associated classes for use by timed events or NIO events, and a generic event multicaster.
com.caplin.net.udp Provides access to the UDP command interface for receiving and sending UDP messages.
com.caplin.util.base64 Provides Base64 encoding for sending typed objects using DataSource.
com.caplin.util.logging  
examples.container ActiveContainerSource is an example that can provide a Container object to the Liberator.
examples.liberator  
examples.liberator.data  
examples.liberator.data.filters  
examples.liberator.data.impl  
examples.liberator.data.translate  
examples.liberator.dispatch  
examples.multipledatasources MultipleDataSourcesInOneJVM is an application that shows how to run more than one data source in one JVM.
examples.news NewsSource is an active source that services requests and discards from a peer.
examples.simple SimpleBroadcast is a very basic broadcast source.
examples.sink Sink is a simple DataSource that listens for a peer connection, then requests and discards, on a timer, a random selection of objects from its connected peer.
examples.source Source is an active source that services requests and discards from a peer.
examples.udp UDPControlled is a UDP Controlled broadcast source that provides record data controlled with various rate parameters.

 

The Caplin DataSource for Java SDK (Software Development Kit) is a library of classes that enables developers to create applications that can send and receive financial market data in the form of structured records and fields, pages, news headlines and news stories to and from other DataSource-enabled applications, using Caplin's DataSource protocol.

The kit contains the following components:

Using DataSource SDK for Java

Follow the links on the table below for information on the following topics:

Topic
About Java DataSource
New in version 4.4
Getting started with the Java DataSource
Upgrading from DataSource for Java 4.2.x
Scenarios for using DataSource
Configuring your Java DataSource application
Initialising your Java DataSource application
Peers
Contributing, requesting/discarding and receiving data
Logging
Using SSL
Running Multiple DataSources in one JVM
Using the helper classes and features
The example applications
Latency Chaining
The DataSource XML configuration schema
The Field XML configuration schema

About DataSource

A DataSource application can perform the following tasks:

  1. It can convert incoming data from data providers into a format suitable for distribution to other DataSource applications and transmit the data using the DataSource protocol to any DataSource applications (in either a "broadcast" or "active" manner);
  2. It can receive data using the DataSource protocol from another DataSource application that is providing it.

The Java DataSource includes many helper classes and mechanisms for performing these tasks efficiently, including:

TOP


What is new in version 4.4

To be able to use the new datasource it is necessary to take the following upgrade steps

TOP


Getting Started

Installing DataSource SDK

To install DataSource SDK:

Coding with DataSource SDK

To use the DataSource SDK for Java classes:

Sample files

A number of example DataSource applications created using DataSource SDK for Java are available in the examples subdirectory. Information about these applications is available here.

Java requirements

Caplin DataSource for Java requires a 1.4 or newer JVM as it uses features only found in these versions. It is tested and approved for use with the Sun 1.4.2 JVM on Windows, Solaris and Linux but should work on any operating system with a suitable JVM installed.

TOP


Upgrading from DataSource for Java 4.2.x

In order to take advantage of configuring the application from an XML stream some changes to the code need to be made.

  1. Change the way DataSource is constructed

    The old DataSource() constructor that retrieved configuration via System Property has been deprecated.

    To upgrade, use the DataSource.DataSource(InputStream) constructor to take advantage of configuring from any InputStream source. Also remove all System Property configuration from the code, this is no longer needed. Note that the new constructor throws IOException and SAXException to indicate issues with retrieving configuration.

  2. Remove any configuration for the location of XML schemas, this is no longer needed as they are included in the JAR.

TOP


Scenarios for using Java DataSource

Example: Converting incoming data and providing it to other DataSource applications

Scenario:

Your application receives incoming data from a data provider (e.g. proprietary data feed, database trigger). This data contains values that need to be contributed to another DataSource application. To be able to do this, Java DataSource SDK runtime libraries need to be included as a component within your application. In order to contribute these values, you need to use the Java classes and interfaces (such as DSData , DSRecord and DSFactory) provided by the DataSource library to create data objects and add the values (fields) to these objects. The object can then be forwarded to where it is needed, be that a Caplin Liberator for onward distribution over the Internet, or another DataSource application for aggregation or further processing of data.

Source functionality

The application will act as a source of data for any other applications to which it is connected which also use the DataSource protocol. These other applications are known as DataSource peers.

Choosing an active or broadcast DataSource

Broadcast: A broadcast DataSource is the simplest type of DataSource. It sends all object and updates to all connected peers. If a broadcast DataSource is chosen then when an update is received from the data provider a simple process can be followed to send this data on to connected peers:

  1. Create a DSData (or subclass) object (e.g. DSRecord) using the DSFactory
  2. Add data to it using one of the add methods (e.g. DSRecord.addRecordData)
  3. Send the data to all connected peers using the DSData.send() method, or to a specific peer using the DSData.sendToPeer(int peer) method.

For an example of a simple broadcast DataSource see the SimpleBroadcast class in the provided examples.

Active: An active DataSource accepts requests for objects, keeps track of which objects have been requested and only sends updates for those objects. Objects may be discarded as well as requested. Discarding is when a connected peer tells DataSource that it no longer wishes to receive updates for this object. Request and discard messages are tracked using the DSRequestListener and DSDiscardListener respectively.

The following steps should be followed to provide data using an active DataSource:

  1. Add a DSRequestListener and a DSDiscardListener to the DataSource object using DataSource.setDSRequestListener(com.caplin.datasrc.DSRequestListener) and DataSource.setDSDiscardListener(com.caplin.datasrc.DSDiscardListener).
  2. Wait for a request to be received as a call to DSRequestListener.receiveRequest(int, java.lang.String[]).
  3. Start providing data for the requested object using the mechanism described in the broadcast section above.
  4. Stop providing data when a discard is received by the DSDiscardListener.receiveDiscard(int, java.lang.String[]) method.

For an example of an active DataSource see the Source class in the provided examples.

It is also possible to convert a broadcast DataSource to behave as an active DataSource by using the CacheManager. This provides caching of broadcast data by utilising the DSSendManager interface to intercept data sent using DSData.send(). See the section on caching for more information on this feature. It has the advantage of automatically only sending data to peers that have requested it by maintaining a subscription database.

Example: Receiving data from another DataSource application

Scenario:

Your application needs to receive data from another DataSource peer to allow monitoring of certain market data elements. This data will be requested from another active peer and if certain conditions are met then some action should be taken.

Sink functionality

The application will act as a sink (i.e. consume data, not publish). It will receive data from other peers for processing.

The following steps should be followed to allow data to be received from peers:

  1. Add a DSUpdateListener to the DataSource object using DataSource.setDSUpdateListener(com.caplin.datasrc.DSUpdateListener).
  2. If you wish to be notified of "No Data" messages (e.g. when the providing peer deletes an object) then also add a DSNoDataListener to the DataSource object.
  3. Additional listeners, such as DSMessageListener and DSStatusListener can be added as required.
  4. Data updates will be received by the listener on the DSUpdateListener.receiveUpdate(int, com.caplin.datasrc.interfaces.DSData) method. The first parameter will indicate the peer number that sent the packet, the second parameter will be the DSData packet that has been received.

For an example of a DataSource that receives data from another peer see the Sink class in the provided examples.

TOP


Configuring your DataSource application

DataSource applications are configured using XML which can be passed to the DataSource constructor as an InputStream or File. The specification for this is found here: 'DataSource.xml'

The FieldManager can optionally be configured via XML which can also be passed to the DataSource constructor as an InputStream or File. The specification for this can be found here: 'Fields.xml'

TOP


Initialising your DataSource application

There are three main steps required to initialise a DataSource application:

  1. Obtain any XML configured objects that are required
  2. Register interest in particular callbacks through various listeners. The following listeners can be set using the appropriate setDSxxxListener method on DataSource:
  3. Start the application using the DataSource.start() method. This will start the main DataSource thread which will begin to listen for connections and connect to other peers as configured.

Sample Initialisation Code

import java.util.logging.Logger;

import com.caplin.datasrc.DataSource;
import com.caplin.datasrc.DSMessageListener;
import com.caplin.datasrc.DSUpdateListener;
import com.caplin.datasrc.DSStatusListener;
import com.caplin.datasrc.DSNoDataListener;

public class ExampleDataSource implements DSMessageListener, DSUpdateListener,
DSStatusListener, DSNoDataListener
{
    // The main DataSource object
    private DataSource dataSource;

    // A local FieldManager reference
    private FieldManager fieldManager;

    // Constructor
    public ExampleDataSource(DataSource dataSource)
    {
        this.dataSource = dataSource;
    }

    public void receiveMessage(int num, int type, int val, String message)
    {
        // Add code for receiving messages here ...
    }
    public void receiveUpdate(int num, DSData dsData)
    {
        // Add code for receiving updates here ...
    }
    public void receiveNoData(int num, String subject, int flags)
    {
        // Add code for receiving nodata messages here ...
    }
    public void receiveStatus(int num, String name, int flags, int code, String message)
    {
        // Add code for receiving status messages here ...
    }
    public static void main(String[]args)
    {
        // Configuration can be passed in via InputStream or File - here we just pass in a file
        DataSource dataSource = new DataSource(new File("conf/DataSource.xml"));

        // Initialise the ExampleDataSource object
        ExampleDataSource eds = new ExampleDataSource(dataSource);
        dataSource.setDSMessageListener(eds);
        dataSource.setDSNoDataListener(eds);
        dataSource.setDSStatusListener(eds);
        dataSource.setDSUpdateListener(eds);
        dataSource.start();
    }
}

TOP


Using DataSource Peers

A DataSource application is bi-directional - a DataSource can send and receive data from another DataSource. In addition, a DataSource can either connect to, or listen for connections from, another DataSource. These other DataSources are referred to as Peers.

The Caplin Liberator and Caplin Transformer are examples of DataSource peers.

peers

Objects can be requested from individual DataSource peers or groups of peers.

Active DataSources

An active DataSource is one that will service requests for objects (the opposite of this is a broadcast DataSource, which simply sends all objects and updates to its peers regardless). It is an active DataSource's responsibility to keep track of which objects have been requested and send updates for those objects only.

When a user requests an object, and Caplin Liberator does not already have it, it will request it from one or more of its active sources. If another user requests that object Caplin Liberator will already have all the information it needs, and will respond to the user immediately.

Objects may be discarded as well as requested. This tells the source that we no longer wish to receive updates for this object. When a user logs out or discards an object, Caplin Liberator will send a discard message to the active DataSource (as long as no other user is viewing that object). This discard will actually take place one minute after the user discarded the object; this prevents objects being requested and discarded from the source unnecessarily.

TOP


Contributing, requesting/discarding and receiving data

Contributing

The DSData interface is the base interface used for sending data updates to DataSource peers. Data is passed using the format of an object name (subject) to identify the object and one or more field number/value pairs. Typically a field number will map to field name such as "Bid" and "Ask". DSData provides numerous methods such as DSData.addData and DSData.addBinaryData to add field pairs to objects, and other methods to access and change data values.

The DSFactory

Example code:

DSRecord record = DSFactory.createDSRecord(dataSource, "/I/VOD.L");
record.addRecordData("Bid", 12.385);
record.addRecordData("Ask", 12.398);
// Send data to all connected peers.
record.send();

DSRecord, DSPage, DSNews and DSStory extend DSData and offer more methods for adding data that are specific to certain object types.

Iterating over fields in a DSData, Example code:

Iterator i = data.iterator();

while(i.hasNext())
{
    DSField field = (DSField)i.next();
    System.out.println("FieldNum="+ field.getFieldNumber()+" Value="+field.getValue());
}

 

Requesting/Discarding

A DataSource can request or discard objects from a peer by using the RequestDiscardOperations class. Use the DataSource.getRequestDiscardOperations() method to get an instance of this class for a DataSource. A DataSource peer can listen for requests and discards by adding implementations of the DSRequestListener and DSDiscardListener respectively.

Example code

DataSource dataSource = new DataSource(new File("conf/DataSource.xml"));

String[] recordSubjects = { "/INTL.O", "/SUNW.O", "/MSFT.O", "/CSCO.O", "/DELL.O" };

//Get an instance of RequestDiscardOperations
RequestDiscardOperations ops = dataSource.getRequestDiscardOperations();

//Make a request to all connected peers
ops.requestObjects(recordSubjects);

// ... some time later...

// Make a discard to all connected peers
ops.discardObjects(recordSubjects);

 

Receiving Data

A DataSource can listen for data updates from connected peers by registering a DSUpdateListener interface using the DataSource.setDSUpdateListener(com.caplin.datasrc.DSUpdateListener) method. The DSUpdateListener.receiveUpdate(int, com.caplin.datasrc.interfaces.DSData) method will be invoked on the listener each time data is received from a peer.

A DataSource application can also receive contributions made by RTTP clients connected to a Liberator. This behaviour is often desired if these user contributions need to be passed back to an upstream component, for example in the case of a trade message. To achieve this the DataSource must be configured to send the CONTRIB flag, see the local tag in the DataSource XML Configuration Schema for more details.

The Liberator will send any client contributions to objects that are owned by a particular DataSource back to that DataSource. An object is owned by a DataSource if that DataSource has provided data for the object in the current Liberator session. If more than one DataSource provides data then both will receive the client contribution.

Object Status Information

The DSStatus interface represents a message indicating the current status of an object. These can be sent to peers or received from peers.

To create a DSStatus object use the DSFactory.createDSStatus(com.caplin.datasrc.DataSource, java.lang.String, int, int, java.lang.String) factory method.

Example code

DSStatus status = DSFactory.createDSStatus(dataSource, "/DEMO/TEST", S_STALE, 15, "Stale due to feed down");
status.send();

A DataSource will receive these messages through the DSStatusListener interface registered on the DataSource object using DataSource.setDSStatusListener(com.caplin.datasrc.DSStatusListener) method.

System Status Information

System status messages may be sent using the StatusOperations class.

The DataSource peers can listen for these messages by adding a DSMessageListener to the DataSource. The StatusOperations class also provides methods that allow a DataSource to disconnect and stop listening for messages (StatusOperations.setStatusDown()) and subsequently reconnect and start listening again (StatusOperations.setStatusUp()). With the StatusOperations.setStatusMessage(int messageId, String message) function it is possible to send a status message to all peers.

Example code:

StatusOperations statusOperations;
statusOperations = dataSource.getStatusOperations();
statusOperations.setStatusMessage(1, "Going down in 1 minute...");

// Code to wait a minute ...

statusOperations.setStatusDown();

// Do some other operations until ready to set status up again

statusOperations.setStatusUp();
statusOperations.setStatusMessage(2, "Back up again");

Systen status messages can be sent to a particular peer. All three setStatus functions have equivalent ones that take additional parameter: peer number which is an index in the peers array in DataSource object. See: StatusOperations.setStatusDownToPeer(int peer), StatusOperations.setStatusUpToPeer(int peer), StatusOperations.setStatusMessageToPeer(int peernum, int messageId, String message).

Example code:

// all operations on peer 0 only

StatusOperations statusOperations = dataSource.getStatusOperations();
statusOperations.setStatusMessage( 0, 1, "Going down in 1 minute...");

// Code to wait a minute ...

statusOperations.setStatusDown(0);

// Do some other operations until ready to set status up again

statusOperations.setStatusUp(0);
statusOperations.setStatusMessage(0, 2, "Back up again");

The Container Object

The Container object DSContainer represents a collection of objects that are related in some way.
What is a container?
When sent to a Liberator, the Container allows a single subscription by a client to subscribe to a container and therefore its contents. Any updates for the linked objects will be automatically sent to the subscribers of any containers the object belongs to.

New (linked) objects can be easily added to the Container using the DSContainer.addObject(String) method. Objects can also be removed from the Container using the DSContainer.removeObject(String) method.

If a container is sent with the DSData.F_IMAGE flag, the cached container is cleared and replaced with any objects added in this container update. Otherwise, adding or removing merely adjusts the existing cached container.

Note that 'adding' a DataSource object to a container actually adds a link to that object. So for example a Container object called /BOOK1 could contain /OBJ1 and /OBJ2, where /OBJ1 is a record data type and /OBJ2 is a news data type.

Example code:

// Create a container with two constituents

...
DSContainer container = DSFactory.createDSContainer(info.getDataSource(), info.getName(), getFlags());
container.addObject("/RECORD/MSFT");
container.addObject("/NEWS");
container.send();

Example code:

// Change the contents of an existing container

...
DSContainer container = DSFactory.createDSContainer(info.getDataSource(), info.getName(), getFlags());
container.removeObject("/RECORD/MSFT");
container.addObject("/RECORD/ORCL");
container.send();

TOP

Logging using DataSource

DataSource's packet log file keeps a record of all data and to which destinations (peers) the data was sent. The packet log is stored in a proprietary compressed binary format and requires the use of JLogCat to view it as text. The packet log is configured using the packetLog tag in the DataSource XML Configuration file. See here for more details on the XML configuration.

File log wrapping functionality allowing to configure how the packet log files are being cycled, more details in packetLog tag description.

The Datasource text log is for application logging, and writes to an instance of a java.util.logger.Logger class. DataSource includes a default java.util.logger.Handler that writes to a file and formats all messages with a date-stamp, log level and performs parameter substitution using java.text.MessageFormat. To access the logger at runtime, either use the static java.util.logger.Logger.getLogger(String name) method to access using the subsytem attribute specified in the logging tag or alternatively use Configurables.getLogger() method.

The text log is configured using the logging tag in the DataSource XML Configuration file. See here for more details on the XML configuration.

Rotating Logs

ConfigurableRotateLogHandler is a configurable Handler. The class will log to a file and after a user specified number of hours, the current log will be archived as current_log_name.sequence_number and a new log will be created with the name current_log_name. All logging messages will then be written to this file. The sequence number starts at 1 and is then incremented after each archive file is created. By default, the class will rotate after 48 hours.

Although this class is configured by hours, it may take longer than the specified time to rotate the logs as the check to rotate the logs is only performed when a log message is passed to the class for writing out to a file.

This functionality is enabled through the DataSource XML configuration file.

Example code:

 
<dataSource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" port="2500" id="1" >
  <logging default="true" defaultFileName="logs/sample.log" level="FINE" 
        logRotateHours="24" useParentHandlers="false" />
  ...
</dataSource>
        

The class can be used by defining an instance of it and then using the Logger.addHandler(Handler handler) method. The code below shows how this can be done.

 
//define a logger and initialise it
Logger logger;
...     

//create an instance of the class. By default it will rotate every 48 hours
ConfigurableRotateLogHandler handler = new ConfigurableRotateLogHandler(filename);
logger.addHandler(handler);
        
logger.log(Level.INFO,"Logger created successfully");

TOP

Using SSL

DataSource uses the standard Java security packages to provide message transportation under SSL.

The standard java.net.ssl.<property> is used to point to truststores/keystores and to fine-tune settings. See http://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html for further details.

TOP


Running multiple datasources in one JVM

Scenarios for usage

It is possible to run more than one datasource in one JVM. Possible use cases for this are for the client application to manage the datasource by controlling startup and shutdown and testing that two datasources are communicating correctly

Usage

Simply costruct two datasources with the required configuration

 
...
DataSource dataSourceOne = new DataSource(new File(datasourceOneConfiguration), new File(fieldsConfigOneLocation)); 
DataSource dataSourceTwo = new DataSource(new File(datasourceTwoconfiguration), new File(fieldsConfigTwoLocation));
...
                

An example application that runs two datasources is provided in the examples.multipledatasources package.

Tips and Limitations

When running with multiple datasources there are a few things to note:

TOP


Helper classes and features

DataSource provides a number of helper classes and features for commonly used functionality.

Configurable sending

The DSPacket.send() method can be intercepted by a custom handler and any desired behaviour can be added. This mechanism forms the basis for the caching and delaying features described below.

To add a custom send handler, an implementation of the DSSendManager interface should be created. This DSSendManager is put in place by calling DataSource.setDSSendManager(com.caplin.datasrc.DSSendManager). Once in place, all DSData.send() calls are intercepted by the DSSendManager's DSSendManager.send(com.caplin.datasrc.interfaces.DSPacket) method. Any custom behaviour can then be added, for example delaying the sending of data or storing the packet, etc.

Example:

public class SendAndStore extends SendDirect
{
    public SendAndStore(DataSource dataSource)
    {
        super(dataSource);
    }

    public void send(DSPacket packet)
    {
        super.send(packet);

        // store the packet contents somewhere for later use
    }
}

Setting the DSSendManager:

// ... during initialisation code - have an instance of DataSource called dataSource

DSSendManager sendAndStore = new SendAndStore(dataSource);
dataSource.setDSSendManager(sendAndStore);

Caching data

The com.caplin.datasrc.cache package provides a pre-built cache that enables a broadcast DataSource (or a DataSource receiving upstream data in a broadcast manner) to act as an active source to its peers without the need to implement caching and subscription management.

The CacheManager registers itself with the DataSource as the DSSendManager, DSRequestListener and DSDiscardListener. It will then cache any DSData sent and provide subscription management, only sending data to peers that have it currently requested.

The CacheManager can be configured using the <activeCache> tag in the DataSource XML configuration file. See here for more details on the XML configuration.

Field name and number conversion

The FieldManager provides field name, number and index mapping and configuration. It allows interchangeable use (and conversion of) string field names, integer DataSource field numbers and a direct index into the underlying data structure. Each field is represented as a FieldInfo instance, which provides access to the name, field number and index for the field. The FieldManager is particularly useful when dealing with DSRecord objects.

The FieldManager is configured at DataSource initialisation time using an XML configuration file (see here for details.

Fields can be added dynamically at runtime using the FieldManager.addField(java.lang.String, int) methods

Delaying data

The com.caplin.datasrc.delay package provides data-delay functionality. This allows for easy configuration of any number of delay channels that will provide data with a configurable delay period. Each delay channel will delay, by a configurable period, all data that is sent using DSPacket.send() and also prefix all object names with a configurable prefix. For example, a prefix of "/D/" would mean that every delayed object would be prefixed "/D/", differentiating it from the real-time feed and any other delay channels. Delayed data can also be sent in configurable batches to make it more efficent.

The DelayManager intercepts all sent data and can be configured to either block or send the live data and then add any number of delay channels with data prefixes (as detailed above). The DelayManager and delay channels are configured using the delayManager and delayChannel tags in the DataSource XML Configuration file. See here for more details on the XML configuration.

Object name mapping

DataSource provides an object name mapping feature that allows any number of pattern-based mappings to be configured.

For example, the pattern *.FX -> /FX/* will map any incoming data that matches *.FX to /FX/* (e.g. the incoming data object name USDGBP.FX will be sent out to peers as /FX/USDGBP).

Object name mapping using pattern matching is enabled by using the patternManager tag in the DataSource XML Configuration file. Individual patterns are added with instances of pattern tags. See here for more details on the XML configuration.

XML Java object creation and configuration

DataSource provides a generic XML configuration mechanism that allows Java Objects to be created and configured from schema-defined XML files. This mechanism is used to configure the DataSource object itself, all of its utility classes such as UDPSignal and also theFieldManager class via the Fields XML.

The class used to create and configure Java objects is XMLConfigurationContext. It uses SAX-based callback parsing of the XML, and can be extended to provide custom functionality. It will create a named class using a default constructor, then use Java-Bean standard setters to configure it (e.g. set[AttributeName] or set[ElementName] or add[ElementName]. The available standard Schema types are defined in XMLSimpleTypes and their associated Java Object types or primitive types are available from the XMLSimpleTypeMapper.

The example applications use this type of XML configuration provide a good starting point for using XML configuration in your own application

Replaying received data

This functionality allows the DataSource to read a log file containing previously received data from other peers and process it in a similar way. To configure and use the replay manager add the <replayManager> tag to the DataSource XML configuration file. The available replay manager modes (depending on the replayType parameter value) are:

replayType value Optional parameters Description
"all" [default value]
fileName
To replay all updates from the latest log file on start-up.
"date"
dateString
dateFormatClass
fileName
To replay updates received after specified date only. There are two optional parameters: dateString to specify the date to replay updates from and dateFormatClass the name of the class to format the given date. The provided class should be a subclass of a the java.text.DateFormat class with a method format(...) overridden. Otherwise or if there is no dateFormatClass parameter a standard ´dd/MM/yy HH:mm´ pattern and the standard java.util.SimpleDateFormat class are used.
"fieldValue"
fieldNum
fieldVal
fileName
To replay all updates received after the first occurrence of the specified field/value pair.
"selective"
symbol
fieldNum
fieldVal
fileName
To replay only selected updates filtered on: a symbol name, a field and its value. Omitting one or more parameters will result in increasing the range of the replayed data - for example <replayManager replayType="selective" symbol="/DELL"/> would replay all updates for symbol "/DELL".

Examples:

<replayManager replayType="all" />
<replayManager replayType="date" dateString="2004-Dec-08 21:01" dateFormatClass="com.company.DateFormatImpl"/>
<replayManager replayType="selective" symbol="/DELL" fieldNum="25" fieldVal="ABC"/>
<replayManager replayType="fieldValue" fieldNum="25" fieldVal="133"/>
<replayManager replayType="all" fileName="packet-7.log"/>

All the replayed updates will be received by the default update listener. To replay a log file while the DataSource is running (rather than to start-up replay from XML configuration) and/or provide an update listener different than the default one there is a group of methods in the ReplayManager class:

replayManager.replay( DSUpdateListener updateListener, String fileName );
replayManager.replayByDate( DSUpdateListener updateListener, String fileName, Date date );
replayManager.replayByFieldValue( DSUpdateListener updateListener, String fileName, int fieldNum, String value );
replayManager.replaySelected( DSUpdateListener updateListener, String fileName, String symbol, int fieldNum, String value );

where:
TOP

Sending and receiving UDP messages

A DataSource can be configured to send and receive UDP messages. This allows for basic management of a DataSource by an administrator, or control of another application by the DataSource. A typical function performed with a UDP message would be resetting the DataSource's peer connection to its primary peer after a failover event.

The UDPSignal class provides this functionality. It is enabled and configured to listen on a particular interface/port with the udpSignal tag in the DataSource XML Configuration file.

For each UDP Command that the DataSource wishes to process, a UDPCommandListener should be added to the UDPSignal using the MulticastingUDPAccessor.addUDPCommandListener(java.lang.String, com.caplin.net.udp.UDPCommandListener) method. The UDPCommandListener will be notified if a UDP message is received that has a first word that matches the String that it was registered with.

To send a UDP message (either to the DataSource itself or to another host / port), one of the MulticastingUDPAccessor.send(java.lang.String) methods should be used. Note: When using this method the message will be sent 3 times due to the inherent unreliability of the UDP protocol. The DataSource will filter out these duplicates when it receives the UDP message, but other applications may not.

TOP

About the example applications

This DataSource for Java SDK comes with a number of example applications. They show how to use the main features of the SDK. They also show how to extend the XML configuration mechanism to provide type safe construction and configuration of Java classes.

Each of the examples can be run from within its own directory (in the default installation) by specifying the examples.jar, datasrc.jar and xercesImpl.jar in the classpath.

E.g. To run the SimpleBroadcast example, make sure you are in the examples/simple directory and issue the following command (note - the ; separator in the classpath may vary depending on operating system.):

java -classpath ../examples.jar;../../lib/datasrc.jar;../../lib/xercesImpl.jar examples.simple.SimpleBroadcast

Click on the appropriate package link for more details on the chosen example.

TOP

Latency Chaining

Datasource for Java supports latency chaining both as a Latency chain source and as a Latency Chain link.

What are Latency Chains?

A latency chain is a way of measuring the latency of any given message as it passes through connected systems. When the message is originated at the first datasource, the message is timestamped.
As the packet is transmitted from datasource to datasource (and on through the liberator), each datasource can record an entry and exit timestamp difference.
This allows the end user to see the latency at each point in the system

How do I start a latency chain?

If your datasource should be the start of the chain, at the point at which it uses the DSFactory method to create a DSData, it should call LatencyChain.initLatency, passing in the new DSData.

How do I implement a latency chain link?

In order to maintain good records for a latency chain, you should record both an Entry and an Exit time.
Luckily, the implementation of DataSource for Java will do this for you. Just before you receive an Update, DS4J will stamp the packet with an Entry time, and just before it is sent to any peers, the packet will be stamped with an exit timestamp.
These actions will only happen if the packet already has a Latency Init field present and if the configuration has enabled latency chaining.

TOP

The DataSource XML configuration schema

Since version 3.4, a DataSource is configured using an XML file. This replaces the previous configuration mechanism of passing a Properties object in to the DataSource constructor. Note: For backwards compatibility the Properties mechanism is still available, though not recommended. There is no guarantee that it will be supported in future versions of the DataSource SDK.

To use the XML configuration, pass it in via a File or InputStream to the DataSource constructor.

DataSource for Java SDK uses XML files validated against XML schemas. This enforces order, so elements within other elements must appear in the correct order as declared in the schema. The hierarchy and order of tags is shown below.

N.B. Tags without children must be self-closing (end with />) or the parser will throw an error.

<dataSource>
    <logging />
    <udpSignal />
    <packetLog>
        <pattern />
    </packetLog>
    <replayManager />
    <latencyChainManager />
    <patternManager>
        <pattern />
        </pattern>
    </patternManager>
    <activeCache />
    <delayManager>
        <delayChannel>
        </delayChannel>
    </delayManager>
    <peer>
        <heartbeat />
        <local />
        <remote />
        <destination />
    </peer>
    <jmxManager />
    <sendDirect />
</dataSource>

A description of each tag and its attributes follows.

<dataSource> tag

The root tag for configuring a DataSource.

Configures how peers will identify and connect to this DataSource application. This application will identify its peers using the information set in the <peer> tags.

Attributes:

Name Type Default Required Description
appName string [class name] No The name of this DataSource, and how DataSource peers will identify it. This name can be overridden by putting a value in the name attribute of a <peer> element.
id int 0 No ID number of this DataSource. This ID can be overridden by putting a value in the id attribute of a <peer> element. It must match the id attribute given in the <remote> element of the remote DataSource's configuration
address string localhost1 No Network interface to listen for connections from DataSource peers
port int 0 No Network port to listen for connections from DataSource peers. The default of 0 means that no connections can be made to this DataSource
SSLAddress string localhost No Network interface to listen for SSL connections from DataSource peers
SSLPort int 0 No Network port to listen for SSL connections from DataSource peers. The default of 0 means that no SSL connections can be made to this DataSource
peerConnectionTimeout int 10 No The amount of time to wait for a valid peer info packet (protocol negotiation) when making or receiving a peer connection.

<dataSource> tags can contain the following elements:

   <logging>

(either 0 or 1 occurrence)

   <udpSignal>

(either 0 or 1 occurrence)

   <packetLog>

(either 0 or 1 occurrence)

   <replayManager>

(either 0 or 1 occurrence)

   <latencyChainManager>

(either 0 or 1 occurrence)

   <patternManager>

(either 0 or 1 occurrence)

   <activeCache>

(either 0 or 1 occurrence)

   <delayManager>

(either 0 or 1 occurrence)

   <peer>

(either 0 or up to 63 occurrences)

   <jmxManager>

(either 0 or 1 occurrence)

Example:

<dataSource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" port="25099" appName="TEST">
   <logging default="true" level="ALL" useParentHandlers="false" />
   <udpSignal port="2459" />
   <peer>
      <local id="112" type="ACTIVE CONTRIB"/>
      <destination address="merlin" port="25007" />
   </peer>
</dataSource>

Back to DataSource XML schema

< logging> tag

Configures how your DataSource application logs internal status messages and error messages.

This tag will result in a Logger instance being created with the specified configuration. This logger instance is available from Configurables.getLogger().

Attributes:

Name Type Default Required Description
subsystem string "com.caplin.datasrc.DataSource" No The name for the Logger (see java.util.logging.Logger)
default boolean true No Specifies whether the default DataSource implementation of java.util.logging.Handler is used publishing log messages. The default handler writes to a text file. Each line writes out the date in ISO8601 format, the level of the message and the message itself.
defaultFileName string datasource.log No If using the default Handler (i.e. default attribute set to true), sets the name of the output file.
level string "INFO" No Sets the java.util.logging.Level for DataSource logging. This will pick up any custom levels that have been added as well as the standard levels. The standard Java levels for logging messages are:
  • OFF
  • SEVERE
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST
  • ALL

The logger will inherit the system default of any logging properties.

useParentHandlers boolean false No Specifies whether or not this logger should send its output to its parent Logger.
logRotateHours integer 48 No Specifies the period of time in hours before the log is wrapped (i.e. the current log is closed and renamed and a new log is created). If this attribute is left out, then the logs will not wrap.
count integer 10 No Specifies how many wrapped logs to keep, including the currently used log. If this attribute is left out then 10 logs files will be maintained provided the logRotateHours attribute is specified. Otherwise there will only ever be one log file.

Example:

<logging default="true" level="ALL" useParentHandlers="false" />

Back to DataSource XML schema

<udpSignal> tag

Configures how your DataSource application sends and receives UDP commands. The kit includes a UDP command interface that enables you to receive and send UDP messages in order to perform management operations such as resetting peer connections after failover.

See the section on UDP Messages for more detail on how to use this functionality.

This tag will result in a UDPSignal instance being created with the specified configuration. This UDPSignal instance is available from DataSource.getUDPSignal().

Attributes:

Name Type Default Required Description
address string 127.0.0.1 No The interface to bind to.
port integer 0 Yes The port to listen to for a UDP signal.

Example:

<udpSignal port="2459" />

Back to DataSource XML schema

<packetLog> tag

Configures how your DataSource records binary messages sent between this DataSource and its peers.

This tag will result in a packet-level log file being created with the specified configuration, unless the noPacketLog attribute is set.

Attributes:

Name Type Default Required Description
append boolean false No If true, append to the end of the existing packet log file. If false, start a new file.
cyclePeriod integer 1440 No The frequency (in minutes) of log files rotation tries. The try fails only if the size of the actual log file is less than minSize parameter. Setting cyclePeriod to 0 will prevent any log rotation tries apart from the ones based on exceeding maxSize parameter by the actual log file size (see maxSize parameter description below). The default value is one day.
cycleTime integer 240 No

If cycleTime is < 1440 (one day) it will result in the cycling of the packet log beginning at the time of day specified (in minutes), and occurring every cyclePeriod minutes (subject to the minimum size specified by the minSize parameter being met).

The default value is 240 which, with the default cyclePeriod of 1440, means the logs are cycled at 4:00am every day.

If cycleTime is > 1440 (one day) it will result in the cycling of the packet log beginning at the time since the start of the week specified (in minutes), and occurring every cyclePeriod minutes (subject to the minimum size specified by the minSize parameter being met).

For example: if cycleTime=2880 (two days) and cyclePeriod=10080 (a week) the logs cycle (subject to minSize parameter ) every Wednesday at 0:00.

maxSize integer 0 No The maximum size in bytes of the packet log before rotating, or 0 for no limit. If the size of the log file is greater than this parameter it will force the rotation, regardless of the all other parameters values. This parameter can be used to put absolute maximum limits on log size.
minSize integer 0 No The minimum size in bytes of the packet log that will allow a periodical rotation to occur (see cyclePeriod parameter), or 0 for no minimum.
count integer 10 No The maximum number of old log files (with the same name prefixes) to keep when rotating the logs.
pattern String [no default] No Deprecated The pattern to name the log file. If the <pattern> tag is used then this attribute is ignored.
noPacketLog boolean false No If true, suppresses writing out a packet log.

Example:

<packetLog append="true" maxSize="100000" minSize="10000" cyclePeriod="3600" count="10"/>

<pattern> tag attributes:

Pattern tag is optional and there can be only one in a <packetLog> tag. It allows to specify the name of the log files to be created by the DataSource. The pattern may be constructed with an expression for java.text.SimpleDateFormat class to parse, so the file names would contain the actual date and/or time. There are several special character allowed:

Name Type Default Required Description
patternType string "text" No Possible values: "text" - patternString parameter contains a string to name the log file with, "date" - patternString parameter contains date pattern for the java.text.SimpleDateFormat class.
patternString string "packet.log" No Contains the pattern to name the log file. With patternType="date" it should be in java.text.SimpleDateFormat acceptable format.

Example:

<packetLog append="true" maxSize="100000" minSize="10000"cyclePeriod="3600" count="10">
   <pattern patternType="date" patternString="'%u/packet-%n-'yyyy-MM-dd'.log'" />
</packetLog>

Back to DataSource XML schema

<replayManager> tag

Tag for replaying data on DataSource startup.

Attributes:

Name Type Default Required Description
replayType string "all" No The type of replay, possible values: "all", "date", "fieldValue", "selective".
dateString string [no default] No Date/time pattern for the dateFormatClass class.
(Applies to replayType="date" only, ignored otherwise.)
dateFormatClass string "java.text.SimpleDateFormat" No The name of a class to format dateString parameter. Should be a subclass of the java.text.DateFormat class. If not, or if this parameter is not specified the standard java.text.SimpleDateFormat is used.
(Applies to replayType="date" only, ignored otherwise.)
symbol string [no default] No The name of the symbol to replay.
(Applies to replayType="selective" only, ignored otherwise.)
fieldNum integer
0
No The number of the field to replay.
(Applies to replayType="fieldValue" or replayType="selective"only, ignored otherwise.)
fieldVal string [no default] No The value of the field.
(Applies to replayType="fieldValue" or replayType="selective"only, ignored otherwise.)/td>
fileName string [no default] No The name of the packet log file to replay (e.g. "logs/packet.log"). If this attribute is not specified then the most recent packet log file that was written is replayed.
(Applies to every replayType.)

Example:

<replayManager replayType="date" dateString="2004-Dec-08 21:01" dateFormatClass="com.company.DateFormatImpl" fileName="packet.log"/>

Back to DataSource XML schema

<latencyChainManager> tag

Tag for enabling latency chaining.

Attributes:

Name Type Default Required Description
InitialTimeStampField string 1 No Sets the rttp field number for the InitialTimeStamp
TimeStampListField string 2 No Sets the rttp field number for the TimeStampList
EventListField string 3 No Sets the rttp field number for the EventList
Base64 string ignore No Sets the configuration for Base64 encoding of the fields.
  • ignore - no Base64 encoding
  • detect - inspect received fields to see if they are using Base64 encoding and decode if it is encoded
  • decode - decode all received latency chain fields
  • encode - encode all transmitted fields with Base64

Example:

<latencyChainManager InitialTimeStampField="2" TimeStampListField="3" EventListField="4"/>

Back to DataSource XML schema

<patternManager> tag

Parent tag for replaying data on DataSource startup. A DataSource application can be configured to map its internal namespace to a different external namespace. This can either be used to simply make it a valid object name for an external source, or to create a complex directory structure of objects.

A valid pattern contains either 0 or 1 * characters, where a * represents 0 or more characters to match, much like a filename pattern match.

If present, patterns will be applied in the following ways to different actions:

Forward Mapping (e.g. if object name matches "from", will be mapped to the "to" form.) Reverse Mapping (e.g. if object name matches "to", will be mapped to the "from" form.)

This tag takes no attributes.

This tag will result in a PatternManager instance being created with Pattern objects for each <pattern> child tag.

The PatternManager instance is available from DataSource.getPatternManager().

<patternManager> tags can contain the following elements:

   <pattern>

(unlimited occurrences)

Example:

<patternManager>
   <pattern from="*.FX" to="/FX/*" />
   <pattern from="MSFT*" to="/Microsoft/*" />
<\patternManager>

Back to DataSource XML schema

<pattern> tag

Configures how DataSource maps object names that match the pattern specified.

A Pattern object is created and added to the PatternManager for each instance of this tag.

Attributes:

Name Type Default Required Description
from string [no default] Yes The name to search for
to string [no default] Yes The name to change to.

Example:

<pattern from="*.FX" to="/FX/*" />

Back to DataSource XML schema

<activeCache> tag

Configures the application's Active Cache. Active Caching enables a broadcast-style data feed to be turned into an active request-based one, by caching all data in DataSource and handling requests for that data internally (see here for a description of this feature). The Active Cache makes it unnecessary to write a database or caching mechanism yourself, which is useful when one DataSource is feeding multiple DataSource peers, each of which is only interested in a small subset of the overall data.

This tag will result in a CacheManager instance being created with the specified configuration. The CacheManager instance will automatically add itself to the DataSource and act as the Active Cache.

Note: Use of both the Active Cache and DelayManager simultaneously is not supported, nor is a custom DSSendManager supported if using one of these features.

Name Type Default Required Description
enable boolean true No If true, turns on the active cache
hashSize integer 1024 No Number of entries in the internal hashtable used for storing the active objects.
symbol XML tag [no default] No The symbol to pre-request from the application on DataSource startup

Example:

<activeCache enable="true" hashSize="2048">
        <symbol symbolName="/DELL"/>
        <symbol symbolName="/MSFT"/>
</activeCache>

Back to DataSource XML schema

<symbol> tag

Configures a symbol (object name) to be pre-requested on DataSource start up from the application by the CacheManager and added to the cache.

Attributes:

Name Type Default Required Description
symbolName string [no default] Yes The name of the object to pre-request.

Example:

<symbol symbolName="/DELL"/>

Back to DataSource XML schema

<delayManager> tag

Configures the DataSource application to send (or resend) its data after a specified time as a "Delay Channel". Any number of delay channels can be created with a defined prefix for the object name and a defined delay time. The live channel can remain or can be blocked so that all data is delayed. In addition, the delayed updates can be batched for efficiency.

This tag will result in a DelayManager instance being created with DelayChannel objects for each <delayChannel> child tag.

The DelayManager instance will automatically add itself to the DataSource and provide the Delay Channels.

Note: Use of both the Active Cache and DelayManager simultaneously is not supported, nor is a custom DSSendManager supported if using one of these features.

Attributes:

Name Type Default Required Description
blockRealTime boolean false No Determines whether to block the "live" undelayed channel. If false, both the real-time and delayed information is sent.
batchTime long 500 No Default time in milliseconds to send batches of delayed data. Each <delayChannel> element can override this value.
batchSize int 10 No Number of updates to be included in each batch for delay channels. It is recommended that this value is set to the number of updates expected in the batchTime attribute. This may be overridden on a channel-by-channel basis.

<delayManager> tags can contain the following element:

   <delayChannel>

(unlimited occurrences)

Example:

<delayManager>
   <delayChannel prefix="" delayTime="1000" batchTime="500" batchSize="50" />
   <delayChannel prefix="/TEST1" delayTime="5000" batchTime="1000" batchSize="100" />
   <delayChannel prefix="/TEST2" delayTime="10000" batchTime="1500" batchSize="150" />
</delayManager>

Back to DataSource XML schema

<delayChannel> tag

Configures an individual stream of delayed data.

Batching enables you to collect a number of updates and send them to peers with one command. When sending batches, your DataSource will keep all updates received in delayTime milliseconds, and then wait batchTime milliseconds before sending them.

A DelayChannel object is created and added to the DelayManager for each instance of this tag.

Attributes:

Name Type Default Required Description
prefix string "" No Object name prefix, to differentiate this channel's data from the real-time stream and other delayed data.
delayTime long 1000 No Milliseconds to delay data by.
batchTime long 500 No Milliseconds to delay batch of updates by.
batchSize int 10 No Starting point of number of updates in that batch.

Example:

<delayChannel prefix="/TEST1" delayTime="5000" batchTime="1000" batchSize="100" />

Back to DataSource XML schema

<peer> tag

Parent tag containing the elements which configure how this application communicates with its peers. Multiple destinations should be used to enable failover. If multiple destinations are present then connections to the destinations will be attempted in the order the tags appear in the XML.

Attributes:

Name Type Default Required Description
ssl boolean false No If true, uses the Secure Sockets Layer (SSL) protocol when connecting to another peer.
msgQueueSize int 200 No Sets the size of the message queue that will buffer outgoing messages in the event of the peer disconnect and then send them when the peer connection is re-established.
ejectExistingConnection boolean true No Whether this peer (if listening for inbound connections) should eject any existing connection when a new peer connection is received.
enableTCPNoDelay boolean false No Set whether the peer socket should use TCP_NODELAY. This setting should be true if the lowest possible message latency is required. When set to true, there is a trade-off of maximum throughput (messages / second) that will be possible.


<peer> tags can contain the following elements:

   <heartbeat>

(either 0 or 1 occurrence)

   <local>

(either 0 or 1 occurrence)

   <remote>

(either 0 or 1 occurrence)

   <destination>

(unlimited occurrences)

Example:

<peer>
    <local id="112" name="CaplinTest" type="ACTIVE CONTRIB"/>
    <destination address="merlin" port="25007" />
    <destination address="merlin2" port="25005" />
</peer>

Back to DataSource XML schema

<heartbeat> tag

Configures the rate of heartbeats sent between peers which indicate the health of connections. This heartbeat rate is just a suggestion: on connection to a peer, the DataSources will negotiate a suitable heartbeat rate. If the peer doesn't support heartbeats then they will not be sent.

Attributes:

Name Type Default Required Description
time long -1 No The time, in milliseconds, between heartbeats. The default (-1) means
heartbeats are turned off. A suggested time is 15000 as this will send a heartbeat every 15 seconds if no other traffic is being sent, which is suitable for most firewall configurations.
slackTime long 5000 No The delay, in milliseconds, after the time attribute before the peer connection is terminated and your application attempts to reconnect due to no heartbeat being received.

Example:

<heartbeat time="5000" slackTime="2000" />

Back to DataSource XML schema

<local> tag

Configures the type information that the DataSource sends to this peer to identify its capabilities.

Attributes

Name Type Default Required Description
name string appName (<dataSource> attribute) No Name of this DataSource. Overrides the appName attribute of the <dataSource> tag's attribute.
id int id (<dataSource> attribute) No ID number of this DataSource. Overrides the id attribute of the <dataSource> tag's attribute.
type string "" No

Type of this DataSource.

Possible values are shown below and can be either one or both, space separated. This type information is used by the peer so that it knows what operations this DataSource provides. Without either values the peer assumes this DataSource to be a Broadcast source that doesn't support Contributions.

  • "ACTIVE"
    This application only sends updates to those peers which requested them)
  • "CONTRIB"
    This application will receive contributions made by clients to objects which it supplies updates for).

Example:

<local id="112" name="CaplinTest" type="ACTIVE CONTRIB"/>

Back to DataSource XML schema

<remote> tag

Configures the expected capabilites of this peer. N.B: once connected, this peer may send different capabilities, which will override those set here.

Attributes:

Name Type Default Required Description
name string src_[index of peer] No Name of DataSource peer. Will be overridden by the peer once the connection is established.
id int 0 No ID number of the DataSource peer that will connect.
type string "" No

Type of this DataSource.

Possible values are shown below and can be either one or both, space separated. This type information is used by the DataSource so that it knows what operations this peer is expected to provide. This may differ from the actual operations that the peer provides, these will be set at connection time. Without either values this DataSource assumes the peer to be a Broadcast source that doesn't support Contributions.

  • "ACTIVE"
    This peer operates in active mode. Can be overridden by the peer once the connection is established.
  • "CONTRIB"
    This peer can receive contributions made by clients to objects which it supplies updates for.