Hazelcast IMDG tutorial – Implement Variable Replacer

Introduction

Hazelcast IMDG 3.10 comes with a new feature – support for Variable Replacers. The replacers allow to use placeholders (Variables) in configuration XML files. You can use Replacers to mask sensitive strings (such as passwords) or to provide values which depend on current environment.

There was already a partial support for placeholders before version 3.10, it allows to reference system properties:

<group>
  <name>${groupName}</name>
</group>

Hazelcast version 3.10 extends the feature and adds possibility to introduce your own replacer implementations. Variable replacers are classes which implement ConfigReplacer interface:

public interface ConfigReplacer {
    void init(Properties properties);
    String getPrefix();
    String getReplacement(String maskedValue);
}

A Variable to be replaced within the configuration file has following form:

"$" PREFIX "{" STRING-TO-BE-REPLACED "}"

where the PREFIX is the value returned by getPrefix() method and the STRING-TO-BE-REPLACED is a value provided to the getReplacement(String) method. The result of getReplacement(String) method call replaces the whole Variable String.

Hazelcast contains example implementation EncryptionReplacer in the codebase – it allows to mask sensitive strings in the configuration file. Another example implementation called ExecReplacer is placed in the Hazelcast code-samples – it allows to execute external command and use its output as the replacement.

Custom implementation

Now let’s show how simple is to implement and use your own custom replacer. The replacer will get a class name and create a new object from it. Then it will call toString() method on it to get the replacement value. Let’s use a “TOSTRING” prefix for our new replacer.

package com.hazelcast.tutorial;

import com.hazelcast.config.replacer.spi.ConfigReplacer;

public class ToStringReplacer implements ConfigReplacer {

    @Override
    public void init(java.util.Properties properties) {
        // we don't need init properties
    }

    @Override
    public String getPrefix() {
        return "TOSTRING";
    }

    @Override
    public String getReplacement(String value) {
        try {
            return Class.forName(value).newInstance().toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // Return null when we are not able to find proper replacement.
        return null;
    }
}

Once the new implementation is enabled within the configuration file’s element, we can use it to provide values for variables:

<hazelcast 
           xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi_schemaLocation="https://hazelcast.com/schema/config
           https://hazelcast.com/schema/config/hazelcast-config-3.10.xsd">

    <config-replacers>
        <replacer class-name="com.hazelcast.config.replacer.ToStringReplacer"/>
    </config-replacers>

    <group>
        <name>$TOSTRING{com.hazelcast.config.replacer.GroupNameProvider}</name>
    </group>

    <instance-name>Instance $TOSTRING{java.util.Date}</instance-name>
</hazelcast>

When you start such a server instance and the GroupNameProvider.toString() call returns “TestGroup” constant, then you will see it as the group name in the server console output:

...
INFO: [LOCAL] [TestGroup] [3.10] Prefer IPv4 stack is true.
Apr 30, 2018 11:00:05 AM com.hazelcast.instance.AddressPicker
INFO: [LOCAL] [TestGroup] [3.10] Picked [192.168.1.1]:5701, using socket ServerSocket[addr=/0:0:0:0:0:0:0:0,localport=5701], bind any local is true
Apr 30, 2018 11:00:05 AM com.hazelcast.system
...

Find the full source code of in a GitHub repository: kwart/hazelcast-tutorial-config-replacers

Summary

With Hazelcast you can use Variables within XML configuration files. Moreover you can provide own replacer implementations which will evaluate the Variables and provide replacements. We have implemented and used a custom variable replacer for Hazelcast XML configuration file.

Is there any replacer you would like to have implemented? Stop by at https://gitter.im/hazelcast/hazelcast and give us a shout!

Links: