11. Message Types¶
Unlike other AMPS client libraries, the JavaScript library parses message data contents before delivering the message to a handler. This happens for all the supported message types.
By default, the client supports the following message types:
- JSON;
- FIX / NVFIX - via
FixTypeHelper
class; - Binary.
Messages of these types are automatically parsed into native JavaScript data structures and are ready for consumption.
The client library utilizes the concept of a type helper for message data processing. It’s an inteface with a set of methods for parsing and serializing message data of a paricular type.
The provided static TypeHelper
class is used for fine grained control
over message types. It is used to register new composite and custom
message types, or replace type helpers for existing types.
Composite Message Types¶
The TypeHelper.compositeHelper
static method handles creating
and parsing composite message types:
// Register the json-xml-json-binary composite message type
TypeHelper.helper(
// The name of the new composite message type
'compositejxjb',
// create the composite type helper
TypeHelper.compositeHelper(
'json', // Part 1: JSON
'xml', // Part 2: XML
'json', // Part 3: JSON
'binary' // Part 4: Binary
)
);
Example 11.1: Register a composite type helper
The composite type helper created with TypeHelper.compositeHelper
will automatically build data to send from the array of the message
parts and parse multi-part messages from the received raw data.
All types used in the new composite type helper should be registered
before creating it.
Building Composite Messages¶
Once the composite type helper was registered, it becomes very easy
to build composite messages of that type. In the following example,
we register a new composite message type, compositejjjb
that
consists of three JSON parts and one binary part. Then, we create
the composite message and publish it. The type helper will take care
of converting message parts into the raw message data that will be
sent:
// Before creating a client, register the composite message type
TypeHelper.helper(
'compositejjjb',
TypeHelper.compositeHelper('json', 'json', 'json', 'binary')
);
const client = new Client('composite-sender');
await client.connect('ws://localhost:9000/amps/compositejjjb');
// create the array with message parts
const parts = [
{id: 5, value: 'part1'}, // JSON part 1
{value: 'part2', data: 22.22}, // JSON part 2
{value: 'part3', data: 33.33}, // JSON part 3
'XXXXXXXXXXXXXXXXXXXXXXXXXXX' // Binary data
];
// Publish the composite message
client.publish('composite-topic', parts);
Example 11.2: Publish a composite message
Parsing Composite Messages¶
Once the composite type helper is registered, the composite messages
of that type will be parsed automatically. The Message.data
field
will contain the array of message parts, parsed according to their
types:
await client.subscribe(
message => {
const parts = message.data;
console.log('Received message with', parts.length, 'parts');
parts.forEach(part => console.log(part));
},
'composite-topic'
);
Example 11.3: Consume a composite message
Notice that the receiving application is written with explicit knowledge of the structure and content of the composite message type.
Custom Message Types¶
If a message type used in your application is not supported by default, it is possible to create a new type helper for it. Another situation in which you might need a custom type helper is when the default implementation does not fit your needs. For example, the default implementation of FIX / NVFIX message types assumes that the keys in each message are unique, thus overriding values if the same key occurs twice in the same message. If your messages contain duplicated keys and that is expected behavior, you need to override the default type helper with a custom implementation.
Each type helper is an object that must contain the following methods:
serialize(data: any): string[]
- this method is used to serialize data in order send it to the server. All data chunks should be converted into an array of strings.deserialize(data: any): any
- this method deserializes data from the Server into a format that will be consumed by the message handler. It can be any format as long as the consumer of the data is aware of it.
Below we provide some examples on how to utilize TypeHelper
functionality.
Create New Type Helpers¶
Create and register a custom type helper for XML
messages:
class XMLTypeHelper {
serialize(data) {
return [new XMLSerializer().serializeToString(data)];
}
deserialize(data) {
if (data.constructor === String) {
return new DOMParser().parseFromString(data);
}
// Binary buffer, need to decode utf8
return new DOMParser().parseFromString(
decodeURIComponent(escape(Uint8ToString(data)))
);
}
}
// Register the XML helper for parsing XML messages
TypeHelper.helper('xml', new XMLTypeHelper());
Example 11.4: New Type Helper for XML Messages
Override Default Type Helpers¶
In case the custom parsing behavior is expected, it is possible to override the default type helper:
/**
* create a JSON type helper that does not parse JSON data into native
* JS objects keeping it in form of a string
*/
const jsonHelper = {
serialize: data => [data],
deserialize: data => JSON.stringify(data)
};
// override the default type helper
TypeHelper.helper('json', jsonHelper);
Example 11.5: Overriding the default type helper
More examples are provided in the JavaScript client library API Documentation.
FIX / NVFIX delimiters¶
In some cases the delimiter value used in FIX / NVFIX messages differs
from the default (\x01
). In this situation you don’t have to
implement a custom type helper; instead, the custom delimiter can
be set:
TypeHelper.helper('nvfix').delimiter('%01');
Example 11.6: Custom Delimiter for NVFIX