Michael Balber
Michael Balber

Reputation: 119

import file to zookeeper in java

I am using zookeeper for configuration management for my java microservices. For that I use apache curator and java zookeeper client.

How can I import a configuration file(properties or json) to zookeeper when the microservice initializes?

Upvotes: 2

Views: 1996

Answers (2)

asolanki
asolanki

Reputation: 1373

I had a similar problem, where we were using zookeeper as the config server and the configuration was stored in yml format in file. Instead of writing code for creating the znode hierarchy dynamically as per yml file, I found a groovy based tool which basically does the same.

You need to have groovy installed and run as below

zookeeperdump.groovy -s localhost:2181 -c /config/application < dump.yml

Upvotes: 0

Alykoff Gali
Alykoff Gali

Reputation: 1221

You should use curator framework if you wanted to load your config in zookeeper. See the post about how you may use curator framework.

There is a some base code example for yml files (for spring config):

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.BoundedExponentialBackoffRetry;
import org.springframework.core.io.ClassPathResource;
import org.yaml.snakeyaml.Yaml;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

@Slf4j
public class LoadConfigsInZoo {
    // base path of your config
    // /CONFIG_PATH/APP_NAME,CONTEXT_NAME
    private static final String BASE_PATH = "/configuration/myApp";
    private static final String ZOO_URL = "localhost:2181";
    private static final String CONFIG_FILE = "bootstrap.yml";
    private final ObjectMapper objectMapper = new ObjectMapper();

    public static void main(String[] args) throws IOException {
        new LoadConfigsInZoo().loadConfig();
    }

    private void loadConfig() throws IOException {
        BoundedExponentialBackoffRetry retryPolicy =
                new BoundedExponentialBackoffRetry(100, 300, 10);
        Map<String, String> config = flattenInnerProperties("", getContentOfYaml(CONFIG_FILE));

        try (CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString(ZOO_URL)
                .retryPolicy(retryPolicy)
                .build()) {
            client.start();
            for (Map.Entry<String, String> entry : config.entrySet()) {
                String path = createPath(BASE_PATH, entry.getKey());
                try {
                    log.info("Try add node with name '{}'", path);
                    client.create()
                            .creatingParentsIfNeeded()
                            .forPath(path, entry.getValue().getBytes());
                    log.info("Node with name '{}' was created", path);
                } catch (Exception e) {
                    log.warn("Unable to create node by path: {}, exception: {}", path, e.getMessage());
                }
            }
        }
    }

    // need your own implementation for properties/json files
    @SuppressWarnings("unchecked")
    private Map<String, Object> getContentOfYaml(String path) throws IOException {
        Yaml yaml = new Yaml();
        try (InputStream in = new ClassPathResource(path).getInputStream()) {
            return yaml.loadAs(in, Map.class);
        }
    }

    @SuppressWarnings("unchecked")
    private Map<String, String> getContentOfProperties(String path) throws IOException {
        try (InputStream in = new ClassPathResource(path).getInputStream()) {
            Properties properties = new Properties();
            properties.load(in);
            return (Map) (properties);
        }
    }

    @SuppressWarnings("unchecked")
    private Map<String, String> getContentOfJson(String path) throws IOException {
        try (InputStream in = new ClassPathResource(path).getInputStream()) {
            return new ObjectMapper().readValue(in, HashMap.class);
        }
    }

    @SuppressWarnings("unchecked")
    private Map<String, String> flattenInnerProperties(String prefix, Map<String, Object> rootMap) {
        Map<String, String> result = new HashMap<>();
        for (Map.Entry<String, Object> entry : rootMap.entrySet()) {
            String newPrefix = prefix.isEmpty() ? entry.getKey() : prefix + "." + entry.getKey();
            Object value = entry.getValue();
            if (value instanceof Map) {
                result.putAll(flattenInnerProperties(newPrefix, (Map<String, Object>) value));
            } else if (value instanceof List) {
                result.putAll(flattenInnerListInProperties(newPrefix, (List) value));
            } else {
                result.put(newPrefix, String.valueOf(value));
            }
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    private Map<String, String> flattenInnerListInProperties(String prefix, List value) {
        int i = 0;
        Map<String, String> result = new HashMap<>();
        for (Object v : value) {
            String listKey = prefix + "[" + i + "]";
            if (v instanceof Map) {
                result.putAll(flattenInnerProperties(listKey, (Map) v));
            } else if (v instanceof List) {
                result.putAll(flattenInnerListInProperties(listKey, (List) v));
            } else {
                result.put(listKey, String.valueOf(v));
            }
            i++;
        }
        return result;
    }

    private String createPath(String basePath, String configName) {
        return basePath + "/" + configName.replaceAll("\\.", "/");
    }
}

Upvotes: 2

Related Questions