/*
 * Copyright DataStax, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.datastax.oss.driver.api.core.config;

import com.datastax.oss.driver.api.core.context.DriverContext;
import com.datastax.oss.driver.api.core.session.SessionBuilder;
import com.datastax.oss.driver.internal.core.config.composite.CompositeDriverConfigLoader;
import com.datastax.oss.driver.internal.core.config.map.MapBasedDriverConfigLoader;
import com.datastax.oss.driver.internal.core.config.typesafe.DefaultDriverConfigLoader;
import com.datastax.oss.driver.internal.core.config.typesafe.DefaultProgrammaticDriverConfigLoaderBuilder;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.io.File;
import java.net.URL;
import java.nio.file.Path;
import java.util.concurrent.CompletionStage;

Manages the initialization, and optionally the periodic reloading, of the driver configuration.
See Also:
  • withConfigLoader.withConfigLoader(DriverConfigLoader)
/** * Manages the initialization, and optionally the periodic reloading, of the driver configuration. * * @see SessionBuilder#withConfigLoader(DriverConfigLoader) */
public interface DriverConfigLoader extends AutoCloseable {
Builds an instance using the driver's default implementation (based on Typesafe config) except that application-specific classpath resources will be located using the provided ClassLoader instead of the current thread's context class loader.

The returned loader will honor the reload interval defined by the option basic.config-reload-interval.

/** * Builds an instance using the driver's default implementation (based on Typesafe config) except * that application-specific classpath resources will be located using the provided {@link * ClassLoader} instead of {@linkplain Thread#getContextClassLoader() the current thread's context * class loader}. * * <p>The returned loader will honor the reload interval defined by the option {@code * basic.config-reload-interval}. */
@NonNull static DriverConfigLoader fromDefaults(@NonNull ClassLoader appClassLoader) { return new DefaultDriverConfigLoader(appClassLoader); }
Builds an instance using the driver's default implementation (based on Typesafe config), except that application-specific options are loaded from a classpath resource with a custom name.

The class loader used to locate application-specific classpath resources is the current thread's context class loader. This might not be suitable for OSGi deployments, which should use fromClasspath(String, ClassLoader) instead.

More precisely, configuration properties are loaded and merged from the following (first-listed are higher priority):

  • system properties
  • <resourceBaseName>.conf (all resources on classpath with this name)
  • <resourceBaseName>.json (all resources on classpath with this name)
  • <resourceBaseName>.properties (all resources on classpath with this name)
  • reference.conf (all resources on classpath with this name). In particular, this will load the reference.conf included in the core driver JAR, that defines default options for all mandatory options.
The resulting configuration is expected to contain a datastax-java-driver section.

The returned loader will honor the reload interval defined by the option basic.config-reload-interval.

/** * Builds an instance using the driver's default implementation (based on Typesafe config), except * that application-specific options are loaded from a classpath resource with a custom name. * * <p>The class loader used to locate application-specific classpath resources is {@linkplain * Thread#getContextClassLoader() the current thread's context class loader}. This might not be * suitable for OSGi deployments, which should use {@link #fromClasspath(String, ClassLoader)} * instead. * * <p>More precisely, configuration properties are loaded and merged from the following * (first-listed are higher priority): * * <ul> * <li>system properties * <li>{@code <resourceBaseName>.conf} (all resources on classpath with this name) * <li>{@code <resourceBaseName>.json} (all resources on classpath with this name) * <li>{@code <resourceBaseName>.properties} (all resources on classpath with this name) * <li>{@code reference.conf} (all resources on classpath with this name). In particular, this * will load the {@code reference.conf} included in the core driver JAR, that defines * default options for all mandatory options. * </ul> * * The resulting configuration is expected to contain a {@code datastax-java-driver} section. * * <p>The returned loader will honor the reload interval defined by the option {@code * basic.config-reload-interval}. */
@NonNull static DriverConfigLoader fromClasspath(@NonNull String resourceBaseName) { return fromClasspath(resourceBaseName, Thread.currentThread().getContextClassLoader()); }
Just like fromClasspath(String) except that application-specific classpath resources will be located using the provided ClassLoader instead of the current thread's context class loader.
/** * Just like {@link #fromClasspath(java.lang.String)} except that application-specific classpath * resources will be located using the provided {@link ClassLoader} instead of {@linkplain * Thread#getContextClassLoader() the current thread's context class loader}. */
@NonNull static DriverConfigLoader fromClasspath( @NonNull String resourceBaseName, @NonNull ClassLoader appClassLoader) { return DefaultDriverConfigLoader.fromClasspath(resourceBaseName, appClassLoader); }
Builds an instance using the driver's default implementation (based on Typesafe config), except that application-specific options are loaded from the given path.

More precisely, configuration properties are loaded and merged from the following (first-listed are higher priority):

  • system properties
  • the contents of file
  • reference.conf (all resources on classpath with this name). In particular, this will load the reference.conf included in the core driver JAR, that defines default options for all mandatory options.
The resulting configuration is expected to contain a datastax-java-driver section.

The returned loader will honor the reload interval defined by the option basic.config-reload-interval.

/** * Builds an instance using the driver's default implementation (based on Typesafe config), except * that application-specific options are loaded from the given path. * * <p>More precisely, configuration properties are loaded and merged from the following * (first-listed are higher priority): * * <ul> * <li>system properties * <li>the contents of {@code file} * <li>{@code reference.conf} (all resources on classpath with this name). In particular, this * will load the {@code reference.conf} included in the core driver JAR, that defines * default options for all mandatory options. * </ul> * * The resulting configuration is expected to contain a {@code datastax-java-driver} section. * * <p>The returned loader will honor the reload interval defined by the option {@code * basic.config-reload-interval}. */
@NonNull static DriverConfigLoader fromPath(@NonNull Path file) { return fromFile(file.toFile()); }
Builds an instance using the driver's default implementation (based on Typesafe config), except that application-specific options are loaded from the given file.

More precisely, configuration properties are loaded and merged from the following (first-listed are higher priority):

  • system properties
  • the contents of file
  • reference.conf (all resources on classpath with this name). In particular, this will load the reference.conf included in the core driver JAR, that defines default options for all mandatory options.
The resulting configuration is expected to contain a datastax-java-driver section.

The returned loader will honor the reload interval defined by the option basic.config-reload-interval.

/** * Builds an instance using the driver's default implementation (based on Typesafe config), except * that application-specific options are loaded from the given file. * * <p>More precisely, configuration properties are loaded and merged from the following * (first-listed are higher priority): * * <ul> * <li>system properties * <li>the contents of {@code file} * <li>{@code reference.conf} (all resources on classpath with this name). In particular, this * will load the {@code reference.conf} included in the core driver JAR, that defines * default options for all mandatory options. * </ul> * * The resulting configuration is expected to contain a {@code datastax-java-driver} section. * * <p>The returned loader will honor the reload interval defined by the option {@code * basic.config-reload-interval}. */
@NonNull static DriverConfigLoader fromFile(@NonNull File file) { return DefaultDriverConfigLoader.fromFile(file); }
Builds an instance using the driver's default implementation (based on Typesafe config), except that application-specific options are loaded from the given URL.

More precisely, configuration properties are loaded and merged from the following (first-listed are higher priority):

  • system properties
  • the contents of url
  • reference.conf (all resources on classpath with this name). In particular, this will load the reference.conf included in the core driver JAR, that defines default options for all mandatory options.
The resulting configuration is expected to contain a datastax-java-driver section.

The returned loader will honor the reload interval defined by the option basic.config-reload-interval.

/** * Builds an instance using the driver's default implementation (based on Typesafe config), except * that application-specific options are loaded from the given URL. * * <p>More precisely, configuration properties are loaded and merged from the following * (first-listed are higher priority): * * <ul> * <li>system properties * <li>the contents of {@code url} * <li>{@code reference.conf} (all resources on classpath with this name). In particular, this * will load the {@code reference.conf} included in the core driver JAR, that defines * default options for all mandatory options. * </ul> * * The resulting configuration is expected to contain a {@code datastax-java-driver} section. * * <p>The returned loader will honor the reload interval defined by the option {@code * basic.config-reload-interval}. */
@NonNull static DriverConfigLoader fromUrl(@NonNull URL url) { return DefaultDriverConfigLoader.fromUrl(url); }
Builds an instance using the driver's default implementation (based on Typesafe config), except that application-specific options are parsed from the given string.

The string must be in HOCON format and contain a datastax-java-driver section. Options must be separated by line breaks:

DriverConfigLoader.fromString(
        "datastax-java-driver.basic { session-name = my-app\nrequest.timeout = 1 millisecond }")

More precisely, configuration properties are loaded and merged from the following (first-listed are higher priority):

  • system properties
  • the config in contents
  • reference.conf (all resources on classpath with this name). In particular, this will load the reference.conf included in the core driver JAR, that defines default options for all mandatory options.

This loader does not support runtime reloading.

/** * Builds an instance using the driver's default implementation (based on Typesafe config), except * that application-specific options are parsed from the given string. * * <p>The string must be in HOCON format and contain a {@code datastax-java-driver} section. * Options must be separated by line breaks: * * <pre> * DriverConfigLoader.fromString( * "datastax-java-driver.basic { session-name = my-app\nrequest.timeout = 1 millisecond }") * </pre> * * <p>More precisely, configuration properties are loaded and merged from the following * (first-listed are higher priority): * * <ul> * <li>system properties * <li>the config in {@code contents} * <li>{@code reference.conf} (all resources on classpath with this name). In particular, this * will load the {@code reference.conf} included in the core driver JAR, that defines * default options for all mandatory options. * </ul> * * <p>This loader does not support runtime reloading. */
@NonNull static DriverConfigLoader fromString(@NonNull String contents) { return DefaultDriverConfigLoader.fromString(contents); }
Starts a builder that allows configuration options to be overridden programmatically.

Note that fromMap(OptionsMap) provides an alternative approach for programmatic configuration, that might be more convenient if you wish to completely bypass Typesafe config.

For example:


DriverConfigLoader loader =
    DriverConfigLoader.programmaticBuilder()
        .withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(5))
        .startProfile("slow")
        .withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(30))
        .endProfile()
        .build();
produces the same overrides as:
datastax-java-driver {
  basic.request.timeout = 5 seconds
  profiles {
    slow {
      basic.request.timeout = 30 seconds
    }
  }
}
The resulting loader still uses the driver's default implementation (based on Typesafe config), except that the programmatic configuration takes precedence. More precisely, configuration properties are loaded and merged from the following (first-listed are higher priority):
  • system properties
  • properties that were provided programmatically
  • application.conf (all resources on classpath with this name)
  • application.json (all resources on classpath with this name)
  • application.properties (all resources on classpath with this name)
  • reference.conf (all resources on classpath with this name). In particular, this will load the reference.conf included in the core driver JAR, that defines default options for all mandatory options.
Note that application.* is entirely optional, you may choose to only rely on the driver's built-in reference.conf and programmatic overrides.

The class loader used to locate application-specific classpath resources is the current thread's context class loader. This might not be suitable for OSGi deployments, which should use programmaticBuilder(ClassLoader) instead.

The resulting configuration is expected to contain a datastax-java-driver section.

The loader will honor the reload interval defined by the option basic.config-reload-interval.

Note that the returned builder is not thread-safe.

See Also:
/** * Starts a builder that allows configuration options to be overridden programmatically. * * <p>Note that {@link #fromMap(OptionsMap)} provides an alternative approach for programmatic * configuration, that might be more convenient if you wish to completely bypass Typesafe config. * * <p>For example: * * <pre>{@code * DriverConfigLoader loader = * DriverConfigLoader.programmaticBuilder() * .withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(5)) * .startProfile("slow") * .withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(30)) * .endProfile() * .build(); * }</pre> * * produces the same overrides as: * * <pre> * datastax-java-driver { * basic.request.timeout = 5 seconds * profiles { * slow { * basic.request.timeout = 30 seconds * } * } * } * </pre> * * The resulting loader still uses the driver's default implementation (based on Typesafe config), * except that the programmatic configuration takes precedence. More precisely, configuration * properties are loaded and merged from the following (first-listed are higher priority): * * <ul> * <li>system properties * <li>properties that were provided programmatically * <li>{@code application.conf} (all resources on classpath with this name) * <li>{@code application.json} (all resources on classpath with this name) * <li>{@code application.properties} (all resources on classpath with this name) * <li>{@code reference.conf} (all resources on classpath with this name). In particular, this * will load the {@code reference.conf} included in the core driver JAR, that defines * default options for all mandatory options. * </ul> * * Note that {@code application.*} is entirely optional, you may choose to only rely on the * driver's built-in {@code reference.conf} and programmatic overrides. * * <p>The class loader used to locate application-specific classpath resources is {@linkplain * Thread#getContextClassLoader() the current thread's context class loader}. This might not be * suitable for OSGi deployments, which should use {@link #programmaticBuilder(ClassLoader)} * instead. * * <p>The resulting configuration is expected to contain a {@code datastax-java-driver} section. * * <p>The loader will honor the reload interval defined by the option {@code * basic.config-reload-interval}. * * <p>Note that the returned builder is <b>not thread-safe</b>. * * @see #fromMap(OptionsMap) */
@NonNull static ProgrammaticDriverConfigLoaderBuilder programmaticBuilder() { return new DefaultProgrammaticDriverConfigLoaderBuilder(); }
Just like programmaticBuilder() except that application-specific classpath resources will be located using the provided ClassLoader instead of the current thread's context class loader.
/** * Just like {@link #programmaticBuilder()} except that application-specific classpath resources * will be located using the provided {@link ClassLoader} instead of {@linkplain * Thread#getContextClassLoader() the current thread's context class loader}. */
@NonNull static ProgrammaticDriverConfigLoaderBuilder programmaticBuilder( @NonNull ClassLoader appClassLoader) { return new DefaultProgrammaticDriverConfigLoaderBuilder(appClassLoader); }
Builds an instance backed by an OptionsMap, which holds all options in memory.

This is the simplest implementation. It is intended for clients who wish to completely bypass Typesafe config, and instead manage the configuration programmatically. A typical example is a third-party tool that already has its own configuration file, and doesn't want to introduce a separate mechanism for driver options.

With this loader, the driver's built-in reference.conf file is ignored, the provided OptionsMap must explicitly provide all mandatory options. Note however that OptionsMap.driverDefaults() allows you to initialize an instance with the same default values as reference.conf.

// This creates a configuration equivalent to the built-in reference.conf:
OptionsMap map = OptionsMap.driverDefaults();
// Customize an option:
map.put(TypedDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(5));
DriverConfigLoader loader = DriverConfigLoader.fromMap(map);
CqlSession session = CqlSession.builder()
    .withConfigLoader(loader)
    .build();

If the OptionsMap is modified at runtime, this will be reflected immediately in the configuration, you don't need to call reload(). Note however that, depending on the option, the driver might not react to a configuration change immediately, or ever (this is documented in reference.conf).

Since:4.6.0
/** * Builds an instance backed by an {@link OptionsMap}, which holds all options in memory. * * <p>This is the simplest implementation. It is intended for clients who wish to completely * bypass Typesafe config, and instead manage the configuration programmatically. A typical * example is a third-party tool that already has its own configuration file, and doesn't want to * introduce a separate mechanism for driver options. * * <p>With this loader, the driver's built-in {@code reference.conf} file is ignored, the provided * {@link OptionsMap} must explicitly provide all mandatory options. Note however that {@link * OptionsMap#driverDefaults()} allows you to initialize an instance with the same default values * as {@code reference.conf}. * * <pre> * // This creates a configuration equivalent to the built-in reference.conf: * OptionsMap map = OptionsMap.driverDefaults(); * * // Customize an option: * map.put(TypedDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(5)); * * DriverConfigLoader loader = DriverConfigLoader.fromMap(map); * CqlSession session = CqlSession.builder() * .withConfigLoader(loader) * .build(); * </pre> * * <p>If the {@link OptionsMap} is modified at runtime, this will be reflected immediately in the * configuration, you don't need to call {@link #reload()}. Note however that, depending on the * option, the driver might not react to a configuration change immediately, or ever (this is * documented in {@code reference.conf}). * * @since 4.6.0 */
@NonNull static DriverConfigLoader fromMap(@NonNull OptionsMap source) { return new MapBasedDriverConfigLoader(source, source.asRawMap()); }
Composes two existing config loaders to form a new one.

When the driver reads an option, the "primary" config will be queried first. If the option is missing, then it will be looked up in the "fallback" config.

All execution profiles will be surfaced in the new config. If a profile is defined both in the primary and the fallback config, its options will be merged using the same precedence rules as described above.

The new config is reloadable if at least one of the input configs is. If you invoke reload() on the new loader, it will reload whatever is reloadable, or fail if nothing is. If the input loaders have periodic reloading built-in, each one will reload at its own pace, and the changes will be reflected in the new config.

/** * Composes two existing config loaders to form a new one. * * <p>When the driver reads an option, the "primary" config will be queried first. If the option * is missing, then it will be looked up in the "fallback" config. * * <p>All execution profiles will be surfaced in the new config. If a profile is defined both in * the primary and the fallback config, its options will be merged using the same precedence rules * as described above. * * <p>The new config is reloadable if at least one of the input configs is. If you invoke {@link * DriverConfigLoader#reload()} on the new loader, it will reload whatever is reloadable, or fail * if nothing is. If the input loaders have periodic reloading built-in, each one will reload at * its own pace, and the changes will be reflected in the new config. */
@NonNull static DriverConfigLoader compose( @NonNull DriverConfigLoader primaryConfigLoader, @NonNull DriverConfigLoader fallbackConfigLoader) { return new CompositeDriverConfigLoader(primaryConfigLoader, fallbackConfigLoader); }
Loads the first configuration that will be used to initialize the driver.

If this loader supports reloading, this object should be mutable and reflect later changes when the configuration gets reloaded.

/** * Loads the first configuration that will be used to initialize the driver. * * <p>If this loader {@linkplain #supportsReloading() supports reloading}, this object should be * mutable and reflect later changes when the configuration gets reloaded. */
@NonNull DriverConfig getInitialConfig();
Called when the driver initializes. For loaders that periodically check for configuration updates, this is a good time to grab an internal executor and schedule a recurring task.
/** * Called when the driver initializes. For loaders that periodically check for configuration * updates, this is a good time to grab an internal executor and schedule a recurring task. */
void onDriverInit(@NonNull DriverContext context);
Triggers an immediate reload attempt and returns a stage that completes once the attempt is finished, with a boolean indicating whether the configuration changed as a result of this reload.

If so, it's also guaranteed that internal driver components have been notified by that time; note however that some react to the notification asynchronously, so they may not have completely applied all resulting changes yet.

If this loader does not support programmatic reloading — which you can check by calling supportsReloading() before this method — the returned stage should fail immediately with an UnsupportedOperationException. The default implementation of this interface does support programmatic reloading however, and never returns a failed stage.

/** * Triggers an immediate reload attempt and returns a stage that completes once the attempt is * finished, with a boolean indicating whether the configuration changed as a result of this * reload. * * <p>If so, it's also guaranteed that internal driver components have been notified by that time; * note however that some react to the notification asynchronously, so they may not have * completely applied all resulting changes yet. * * <p>If this loader does not support programmatic reloading &mdash; which you can check by * calling {@link #supportsReloading()} before this method &mdash; the returned stage should fail * immediately with an {@link UnsupportedOperationException}. The default implementation of this * interface does support programmatic reloading however, and never returns a failed stage. */
@NonNull CompletionStage<Boolean> reload();
Whether this implementation supports programmatic reloading with the reload() method.

The default implementation of this interface does support programmatic reloading and always returns true.

/** * Whether this implementation supports programmatic reloading with the {@link #reload()} method. * * <p>The default implementation of this interface does support programmatic reloading and always * returns <code>true</code>. */
boolean supportsReloading();
Called when the cluster closes. This is a good time to release any external resource, for example cancel a scheduled reloading task.
/** * Called when the cluster closes. This is a good time to release any external resource, for * example cancel a scheduled reloading task. */
@Override void close(); }