Initialization and Configuration

❗️

This is a legacy Apache Ignite documentation

The new documentation is hosted here: https://ignite.apache.org/docs/latest/

The below sections explain the basic steps to work with Apache Ignite using NodeJS client.

Before connecting to Ignite from Node.JS thin client, you must start at least one Ignite cluster node. For instance, you can use the ignite.sh script as follows:

./ignite.sh
./ignite.bat

Initializing IgniteClient

A usage of the client starts with the creation of an IgniteClient class instance that would connect a Node.JS application to the cluster. The constructor has one, optional, parameter - onStateChanged callback which will be called every time the client moves to a new connection state (see below).

It is possible to create as many IgniteClient instances as needed. All of them will work independently.

const IgniteClient = require('apache-ignite-client');

const igniteClient = new IgniteClient(onStateChanged);

function onStateChanged(state, reason) {
    if (state === IgniteClient.STATE.CONNECTED) {
        console.log('Client is started');
    }
    else if (state === IgniteClient.STATE.DISCONNECTED) {
        console.log('Client is stopped');
        if (reason) {
            console.log(reason);
        }
    }
}

Configuring IgniteClient

The next step is to define a configuration for the client's connection by populating IgniteClientConfiguration class instance.

A mandatory part of the configuration, which is specified in the constructor, is a list of endpoints of the Ignite nodes. At least one endpoint must be specified. A client connects to one node only - a random endpoint from the provided list. Other nodes, if provided, are used by the client for the "failover re-connection algorithm": the client tries to re-connect to the next random endpoint from the list if the current connection is lost.

Optional parts of the configuration can be specified using additional methods which include:

By default, the client establishes a non-secure connection with default connection options defined by NodeJS and does not use authentication.

The example below shows how to configure the client:

const IgniteClient = require('apache-ignite-client');
const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;

const igniteClientConfiguration = new IgniteClientConfiguration('127.0.0.1:10800');

The next example shows how to prepare Ignite Client Configuration with username/password authentication and additional connection options:

const IgniteClient = require('apache-ignite-client');
const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;

const igniteClientConfiguration = new IgniteClientConfiguration('127.0.0.1:10800').
    setUserName('ignite').
    setPassword('ignite').
    setConnectionOptions(false, { 'timeout' : 0 });

Connecting to the Cluster

The next step is to connect the client to an Ignite cluster. The configuration for the client's connection, which includes endpoint(s) to connect to, is specified in the connect method.

The client has three connection states - CONNECTING, CONNECTED, DISCONNECTED. A state is reported via onStateChanged callback, if it is provided in the client's constructor.

Any interactions with the Ignite cluster are possible in CONNECTED state only.

If the client looses the connection, it automatically moves to the CONNECTING state and tries to re-connect using the "failover re-connection algorithm". If it fails to reconnect to all the endpoints from the provided list, the client moves to DISCONNECTED state.

At any moment, an application can call the disconnect method and forcibly moves the client to the DISCONNECTED state.

When the client becomes disconnected, an application can call the connect method again - with the same or different configuration (eg. with a different list of endpoints).

const IgniteClient = require('apache-ignite-client');
const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;

async function connectClient() {
    const igniteClient = new IgniteClient(onStateChanged);
    try {
        const igniteClientConfiguration = new IgniteClientConfiguration(
          '127.0.0.1:10800', '127.0.0.1:10801', '127.0.0.1:10802');
        // connect to Ignite node
        await igniteClient.connect(igniteClientConfiguration);
    }
    catch (err) {
        console.log(err.message);
    }
}

function onStateChanged(state, reason) {
    if (state === IgniteClient.STATE.CONNECTED) {
        console.log('Client is started');
    }
    else if (state === IgniteClient.STATE.CONNECTING) {
        console.log('Client is connecting');
    }
    else if (state === IgniteClient.STATE.DISCONNECTED) {
        console.log('Client is stopped');
        if (reason) {
            console.log(reason);
        }
    }
}

connectClient();

Configuring Cache

The next step is to obtain a Cache instance - an instance of the CacheClient class to access data stored in Ignite.

The thin client provides several methods to work with Ignite caches and to create a Cache instance - get a cache by its name, create a cache with a specified name and optional cache configuration, get or create a cache, destroys a cache, etc.

It is possible to obtain as many Cache instances as needed - for the same or different Ignite caches - and work with all of them in parallel.

The following example shows how to get access to a cache by name and destroy its later:

const IgniteClient = require('apache-ignite-client');
const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;

async function getOrCreateCacheByName() {
    const igniteClient = new IgniteClient();
    try {
        await igniteClient.connect(new IgniteClientConfiguration('127.0.0.1:10800'));
        // get or create cache by name
        const cache = await igniteClient.getOrCreateCache('myCache');

        // perform cache key-value operations
        // ...

        // destroy cache
        await igniteClient.destroyCache('myCache');
    }
    catch (err) {
        console.log(err.message);
    }
    finally {
        igniteClient.disconnect();
    }
}

getOrCreateCacheByName();

The next example shows how to get access to a cache by name and with a configuration:

const IgniteClient = require('apache-ignite-client');
const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
const CacheConfiguration = IgniteClient.CacheConfiguration;

async function createCacheByConfiguration() {
    const igniteClient = new IgniteClient();
    try {
        await igniteClient.connect(new IgniteClientConfiguration('127.0.0.1:10800'));
        // create cache by name and configuration
        const cache = await igniteClient.createCache(
            'myCache',
            new CacheConfiguration().setSqlSchema('PUBLIC'));
    }
    catch (err) {
        console.log(err.message);
    }
    finally {
        igniteClient.disconnect();
    }
}

createCacheByConfiguration();

This example shows how to get an existing cache by name:

const IgniteClient = require('apache-ignite-client');
const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;

async function getExistingCache() {
    const igniteClient = new IgniteClient();
    try {
        await igniteClient.connect(new IgniteClientConfiguration('127.0.0.1:10800'));
        // get existing cache by name
        const cache = igniteClient.getCache('myCache');
    }
    catch (err) {
        console.log(err.message);
    }
    finally {
        igniteClient.disconnect();
    }
}

getExistingCache();

Types Mapping Configuration

It is possible to specify concrete Ignite types for the key and/or the value of the cache. If the key and/or value is a non-primitive type (eg. a map, a collection, a complex object, etc.) it is possible to specify concrete Ignite types for fields of that objects as well.

If Ignite type is not explicitly specified for some field, the client tries to make automatic default mapping between JavaScript types and Ignite object types.

More details about types and mappings are clarified in the Data Types section.

const IgniteClient = require('apache-ignite-client');
const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
const ObjectType = IgniteClient.ObjectType;
const MapObjectType = IgniteClient.MapObjectType;

async function setCacheKeyValueTypes() {
    const igniteClient = new IgniteClient();
    try {
        await igniteClient.connect(new IgniteClientConfiguration('127.0.0.1:10800'));
        const cache = await igniteClient.getOrCreateCache('myCache');
        // set cache key/value types
        cache.setKeyType(ObjectType.PRIMITIVE_TYPE.INTEGER).
            setValueType(new MapObjectType(
                MapObjectType.MAP_SUBTYPE.LINKED_HASH_MAP,
                ObjectType.PRIMITIVE_TYPE.SHORT,
                ObjectType.PRIMITIVE_TYPE.BYTE_ARRAY));
    }
    catch (err) {
        console.log(err.message);
    }
    finally {
        igniteClient.disconnect();
    }
}

setCacheKeyValueTypes();

At this point, we're ready to start working with the data stored or to be placed in Ignite.

Data Types

The client supports two cases of mapping between Ignite types defined by the Binary Client Protocol and JavaScript types:

  • Explicit mapping
  • Default mapping

Explicit Mapping

A mapping occurs every time an application writes or reads a field to/from an Ignite via the client's API. The field here is any data stored in Ignite - the whole key or value of an Ignite entry, an element of an array or set, a field of a complex object, etc.

Using the client's API methods, an application can explicitly specify an Ignite type for a particular field. The client uses this information to transform the field from JavaScript to Java type and vice verse during the read/write operations. The field is transformed to JavaScript type as a result of read operations. It validates the corresponding JavaScript type in inputs of write operations.

If an application does not explicitly specify an Ignite type for a field, the client uses default mapping during the field read/write operations.

Please refer to the Types Mapping Configuration section for more details and code examples.

Default Mapping

Default mapping between Ignite and JavaScript types is described here.

Complex Object Type Support

The client provides two ways to operate with Ignite Complex Object type - in the deserialized form and t​he binary form.

An application can specify an Ignite type of a field by an instance of the ComplexObjectType class which references an instance of a JavaScript Object. In this case, when the application reads a value of the field, the client deserializes the received Ignite Complex Object and returns it to the client as an instance of the corresponding JavaScript Object. When the application writes a value of the field, the client expects an instance of the corresponding JavaScript Object and serializes it to the Ignite Complex Object.

If an application does not specify an Ignite type of a field and reads a value of the field, the client returns the received Ignite Complex Object as an instance of the BinaryObject class - a binary form of the Ignite Complex Object. The BinaryObject allows working with its content avoiding deserialization (read and write values of the object's fields, add and remove the fields, etc.) Also, the application can create an instance of the BinaryObject class from a JavaScript Object. An application can write the BinaryObject as a value of a field into Ignite, if that field has no explicitly specified Ignite type.

The client takes care of obtaining or registering information about Ignite Complex Object type, including schema, from/at Ignite cluster. It is done automatically by the client, when required for reading or writing of the Ignite Complex Object from/to Ignite.

Supported APIs

The client API specification can be found here.

The client supports all operations and types from the Binary Client Protocol v.2.4 except the following not-applicable features:

  • OP_REGISTER_BINARY_TYPE_NAME and OP_GET_BINARY_TYPE_NAME operations are not supported.
  • Filter object for OP_QUERY_SCAN operation is not supported. OP_QUERY_SCAN operation itself is supported.
  • It is not possible to register a new Ignite Enum type. Reading and writing items of the existing Ignite Enum types are supported.​

The following additional features are supported:

Enabling Debug

To switch on/off the client's debug output (including errors logging), call setDebug() method of the IgniteClient instance. Debug output is disabled by default.

const IgniteClient = require('apache-ignite-client');

const igniteClient = new IgniteClient();
igniteClient.setDebug(true);
📘

Node.JS example files

Node.JS thin client contains fully workable examples to demonstrate the behavior of the client.