All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.configcat.ConfigCatHooks Maven / Gradle / Ivy

Go to download

Java SDK for ConfigCat, a feature flag, feature toggle, and configuration management service. That lets you launch new features and change your software configuration remotely without actually (re)deploying code. ConfigCat even helps you do controlled roll-outs like canary releases and blue-green deployments.

The newest version!
package com.configcat;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Consumer;

public class ConfigCatHooks {
    private final AtomicReference clientCacheState = new AtomicReference<>(null);
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
    private final List>> onConfigChanged = new ArrayList<>();
    private final List> onClientReadyWithState = new ArrayList<>();
    private final List onClientReady = new ArrayList<>();
    private final List>> onFlagEvaluated = new ArrayList<>();
    private final List> onError = new ArrayList<>();

    /**
     * Subscribes to the onReady event. This event is fired when the SDK reaches the ready state.
     * If the SDK is configured with lazy load or manual polling it's considered ready right after instantiation.
     * In case of auto polling, the ready state is reached when the SDK has a valid config.json loaded
     * into memory either from cache or from HTTP. If the config couldn't be loaded neither from cache nor from HTTP the
     * onReady event fires when the auto polling's maxInitWaitTimeInSeconds is reached.
     *
     * @param callback the method to call when the event fires.
     */
    public void addOnClientReady(Consumer callback) {
        lock.writeLock().lock();
        try {
            if(clientCacheState.get() != null) {
                callback.accept(clientCacheState.get());
            } else {
                this.onClientReadyWithState.add(callback);
            }
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * Subscribes to the onReady event. This event is fired when the SDK reaches the ready state.
     * If the SDK is configured with lazy load or manual polling it's considered ready right after instantiation.
     * In case of auto polling, the ready state is reached when the SDK has a valid config.json loaded
     * into memory either from cache or from HTTP. If the config couldn't be loaded neither from cache nor from HTTP the
     * onReady event fires when the auto polling's maxInitWaitTimeInSeconds is reached.
     *
     * @param callback the method to call when the event fires.
     */
    @Deprecated
    public void addOnClientReady(Runnable callback) {
        lock.writeLock().lock();
        try {
            this.onClientReady.add(callback);
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * Subscribes to the onConfigChanged event. This event is fired when the SDK loads a valid config.json
     * into memory from cache, and each subsequent time when the loaded config.json changes via HTTP.
     *
     * @param callback the method to call when the event fires.
     */
    public void addOnConfigChanged(Consumer> callback) {
        lock.writeLock().lock();
        try {
            this.onConfigChanged.add(callback);
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * Subscribes to the onError event. This event is fired when an error occurs within the ConfigCat SDK.
     *
     * @param callback the method to call when the event fires.
     */
    public void addOnError(Consumer callback) {
        lock.writeLock().lock();
        try {
            this.onError.add(callback);
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * Subscribes to the onFlagEvaluated event. This event is fired each time when the SDK evaluates a feature flag or setting.
     * The event sends the same evaluation details that you would get from getValueDetails().
     *
     * @param callback the method to call when the event fires.
     */
    public void addOnFlagEvaluated(Consumer> callback) {
        lock.writeLock().lock();
        try {
            this.onFlagEvaluated.add(callback);
        } finally {
            lock.writeLock().unlock();
        }
    }

    void invokeOnClientReady(ClientCacheState clientCacheState) {
        lock.readLock().lock();
        try {
            this.clientCacheState.set(clientCacheState);
            for (Consumer func : this.onClientReadyWithState) {
                func.accept(clientCacheState);
            }
            for (Runnable func : this.onClientReady) {
                func.run();
            }
        } finally {
            lock.readLock().unlock();
        }
    }

    void invokeOnError(Object error) {
        lock.readLock().lock();
        try {
            if(!this.onError.isEmpty()) {
                String errorMessage = error.toString();
                for (Consumer func : this.onError) {
                    func.accept(errorMessage);
                }
            }
        } finally {
            lock.readLock().unlock();
        }
    }

    void invokeOnConfigChanged(Map settingMap) {
        lock.readLock().lock();
        try {
            for (Consumer> func : this.onConfigChanged) {
                func.accept(settingMap);
            }
        } finally {
            lock.readLock().unlock();
        }
    }

    void invokeOnFlagEvaluated(EvaluationDetails evaluationDetails) {
        lock.readLock().lock();
        try {
            for (Consumer> func : this.onFlagEvaluated) {
                func.accept(evaluationDetails);
            }
        } finally {
            lock.readLock().unlock();
        }
    }

    void clear() {
        lock.writeLock().lock();
        try {
            this.onConfigChanged.clear();
            this.onError.clear();
            this.onFlagEvaluated.clear();
            this.onClientReady.clear();
        } finally {
            lock.writeLock().unlock();
        }
    }
}