Ways to consume data in TimeBase.

Cursors and loaders have two ways of reading and writing messages: bound and raw.

Raw

When working with cursors and loaders, use options.raw = true to read/write raw messages. In this case getMessage() returns objects of a RawMessage class. This class stores data types, a message timestamp, and a buffer with the encoded message. TimeBase uses proprietary Unbound Codec to decode such messages field by field. This method is recommended for advanced TimeBase users.


// create decoder and temp buffer
CodecFactory factory = CodecFactory.newCompiledCachingFactory();
UnboundDecoder decoder = factory.createFixedUnboundDecoder(descriptor);
MemoryDataInput in = new MemoryDataInput();

SelectionOptions selectionOptions = new SelectionOptions();
selectionOptions.raw = true;
try (TickCursor cursor = stream.select(Long.MIN_VALUE, selectionOptions)) {
  while (cursor.next()) {
    RawMessage message = (RawMessage) cursor.getMessage();

    // init buffer and start reading
    in.setBytes(message.data, message.offset, message.length);
    decoder.beginRead(in);

    // read all fields
    decoder.nextField();
    double closePrice = decoder.getDouble();

    decoder.nextField();
    double highPrice = decoder.getDouble();

    // ...
  }
}

Bound

When working with cursors and loaders, use options.raw = false to read/write messages bound to any existing in TimeBase Java and/or C# classes. options.raw is set to false by default.

//sample MyBarMessage class
@SchemaElement(
    name = "org.messages.MyBarMessage",
    title = "Bar Message"
)
public class MyBarMessage extends InstrumentMessage {
  public double closePrice;
  public double openPrice;
  public double highPrice;
  public double lowPrice;
  public double volume;
  public String exchange;
}

//read data bound to the existing MyBarMessage class
options.raw = false;
// do select with options...
while (cursor.next()) { 
    InstrumentMessage message = cursor.getMessage();
    if (message instanceof MyBarMessage) {
        MyBarMessage barMessage = (MyBarMessage) message;
        // process bar message ...
    }
}

// example of writing to a native Java class MyBarPrices, which corresponds to org.messages.MyBarMessage message type in a TimeBase stream.
LoadingOptions options = new LoadingOptions();
options.raw = false;
options.typeLoader = new SimpleTypeLoader("org.messages.MyBarMessage", MyBarPrices.class);
try (TickLoader<InstrumentMessage> loader = changeStream.createLoader(options)) {
     MyBarPrices barPrices = new MyBarPrices();
     // populate MyBarPrices fields
     barPrices.close = 1.222f;
     // …
     // send to loader
     loader.send(barPrices);
}

To receive bound messages, TimeBase uses proprietary Bound Codec to populate class fields with data. Bound Codec is a high performance code that transforms TimeBase messages to native classes and vise versa using RecordClassDescriptor.

If your native class is listed in the classpath and its name fully matches the message type name in the TimeBase stream, TimeBase automatically reads/writes such messages and maps them to corresponding classes. In our example it is MyBarMessage class.

It is also possible to map TimeBase message types to native classes. Add your class information to TypeLoader to do that.

//For example, we have a class with the name and fields that differ from the ones in the TimeBase stream:

@SchemaElement(
    name = "org.messages.MyBarMessage"
)
public static class MyBarPrices extends InstrumentMessage {
  @SchemaElement(name = "closePrice")
  public double close;
  @SchemaElement(name = "openPrice")
  public double open;
  @SchemaElement(name = "highPrice")
  public double high;
  @SchemaElement(name = "lowPrice")
  public double low;
}

//native Java class MyBarPrices is mapped to MyBarMessage TimeBase message type

options.raw = false;
options.typeLoader = new SimpleTypeLoader("org.messages.MyBarMessage", MyBarPrices.class);
// do select with options...
while (cursor.next()) { 
    InstrumentMessage message = cursor.getMessage();
    if (message instanceof MyBarPrices) {
        MyBarPrices barMessage = (MyBarPrices) message;
        // process bar prices...
    }
}