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

com.netflix.archaius.DefaultAppConfig Maven / Gradle / Ivy

There is a newer version: 2.0.0-rc.7
Show newest version
/**
 * Copyright 2015 Netflix, 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.netflix.archaius;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.netflix.archaius.cascade.SimpleCascadeStrategy;
import com.netflix.archaius.config.CascadingCompositeConfig;
import com.netflix.archaius.config.EnvironmentConfig;
import com.netflix.archaius.config.SimpleDynamicConfig;
import com.netflix.archaius.config.SystemConfig;
import com.netflix.archaius.exceptions.ConfigException;
import com.netflix.archaius.interpolate.CommonsStrInterpolatorFactory;
import com.netflix.archaius.loaders.PropertiesConfigReader;
import com.netflix.archaius.property.DefaultPropertyContainer;
import com.netflix.archaius.property.PropertyFactoryDynamicConfigListener;

/**
 * Main AppConfig to be used as the top level entry point for application configuration.
 * This implementation is provided as a best practices approach to dealing with 
 * application configuration by extending composite configuration for a specific override
 * structure.  
 * 
 * 

Override structure

* The {@link DefaultAppConfig} is a CompositeConfig and as such serves as the top level container * for retrieving configurations. Configurations follow a specific override structure, * * RUNTIME - Properties set via code have absolute priority * OVERRIDE - Properties loaded from a remote override service. DynamicConfig derived * objects are added to this layer by calling {@link DefaultAppConfig#addConfigXXX()} * SYSTEM - System.getProperties() * ENVIRONMENT - System.getenv() * APPLICATION - Properties loaded at startup from 'config.properties' and variants * LIBRARY - Properties loaded by libraries or subsystems of the application. * Calling {@link DefaultAppConfig#addConfigXXX()} loads Configs into this layer. * *

Dynamic configuration

* * In addition to static configurations AppConfig exposes an API to fetch {@link PropertyDsl} * objects through which client code can receive update notification for properties. Note that * updates to ObservableProperty are pushed once an underlying DynamicConfig configuration * changes. Multiple DynamicConfig's may be added to the ConfigManager and all will be automatically * subscribed to for configuration changes. * * @author elandau * */ public class DefaultAppConfig extends CascadingCompositeConfig implements AppConfig { private static final Logger LOG = LoggerFactory.getLogger(DefaultAppConfig.class); private static final String DEFAULT_APP_CONFIG_NAME = "config"; private static final String NAME = "ROOT"; private static final String OVERRIDE_LAYER = "OVERRIDE"; private static final String DYNAMIC_LAYER = "DYNAMIC"; private static final String APPLICATION_LAYER = "APPLICATION"; private static final String LIBRARY_LAYER = "LIBRARY"; private static final SimpleCascadeStrategy DEFAULT_CASCADE_STRATEGY = new SimpleCascadeStrategy(); public static class Builder { private StrInterpolatorFactory interpolator; private final List loaders = new ArrayList(); private CascadeStrategy defaultStrategy = DEFAULT_CASCADE_STRATEGY; private boolean failOnFirst = true; private boolean enableSystemLayer = true; private boolean enableEnvironmentLayer = true; private boolean enableOverrideLayer = true; private String configName = DEFAULT_APP_CONFIG_NAME; private Properties props; private Decoder decoder; public Builder withStrInterpolator(StrInterpolatorFactory interpolator) { this.interpolator = interpolator; return this; } /** * Call to include or exclude SystemConfig. Default is true. */ public Builder withSystemLayer(boolean flag) { this.enableSystemLayer = flag; return this; } /** * Call to include or exclude EnvironmentConfig. Default is true. */ public Builder withEnvironmentLayer(boolean flag) { this.enableEnvironmentLayer = flag; return this; } /** * Call to include or exclude DynamicConfig. Default is true. */ public Builder withOverrideLayer(boolean flag) { this.enableOverrideLayer = flag; return this; } /** * Can be called multiple times to add multiple ConfigLoader to be used when * loading application and library properties. If no loaders are added AppConfig * will use PropertiesConfigLoader. */ public Builder withConfigReader(ConfigReader loader) { this.loaders.add(loader); return this; } /** * Default cascade strategy to use for loading application and library properties. * Library cascade strategies may be configured on the loader returned by newLoader. */ public Builder withDefaultCascadingStrategy(CascadeStrategy strategy) { this.defaultStrategy = strategy; return this; } /** * Enable/disable failure if the first file in a cascade list of properties fails * to load. */ public Builder withFailOnFirst(boolean flag) { this.failOnFirst = flag; return this; } /** * Properties to load into the runtime layer at startup. */ public Builder withProperties(Properties props) { this.props = props; return this; } /** * Name of application configuration to load at startup. Default is 'config'. */ public Builder withApplicationConfigName(String name) { this.configName = name; return this; } /** * Decoder used to decode properties to arbitrary types. */ public Builder withDecoder(Decoder decoder) { this.decoder = decoder; return this; } public DefaultAppConfig build() { if (this.interpolator == null) { this.interpolator = new CommonsStrInterpolatorFactory(); } if (this.loaders.isEmpty()) { this.loaders.add(new PropertiesConfigReader()); } return new DefaultAppConfig(this); } } public static Builder builder() { return new Builder(); } public static DefaultAppConfig createDefault() { return new Builder().build(); } private final SimpleDynamicConfig runtime; private final CascadingCompositeConfig override; private final CascadingCompositeConfig library; private final DefaultConfigLoader loader; private final PropertyFactoryDynamicConfigListener dynamicObserver; public DefaultAppConfig(Builder builder) { super(NAME); try { if (builder.decoder != null) { setDecoder(builder.decoder); } this.setStrInterpolator(builder.interpolator.create(this)); // The following are added first, before application configuration // to allow for replacements in the application configuration cascade // loading. super.addConfig(runtime = new SimpleDynamicConfig(OVERRIDE_LAYER)); runtime.setProperties(builder.props); if (builder.enableOverrideLayer) { super.addConfig(override = new CascadingCompositeConfig(DYNAMIC_LAYER)); } else { override = null; } if (builder.enableSystemLayer) { super.addConfig(new SystemConfig()); } if (builder.enableEnvironmentLayer) { super.addConfig(new EnvironmentConfig()); } loader = DefaultConfigLoader.builder() .withConfigReader(builder.loaders) .withDefaultCascadingStrategy(builder.defaultStrategy) .withFailOnFirst(builder.failOnFirst) .withStrInterpolator(getStrInterpolator()) .build(); super.addConfig(loader.newLoader().withName(APPLICATION_LAYER).load(builder.configName)); super.addConfig(library = new CascadingCompositeConfig(LIBRARY_LAYER)); this.dynamicObserver = new PropertyFactoryDynamicConfigListener(new PropertyFactory() { @Override public PropertyContainer getProperty(String propName) { return new DefaultPropertyContainer(propName, DefaultAppConfig.this); } }); library.addListener(dynamicObserver); if (override != null) { override.addListener(dynamicObserver); } } catch (Exception e) { throw new RuntimeException(e); } } @Override public void addOverrideConfig(Config child) throws ConfigException { LOG.info("Adding configuration : " + child.getName()); this.override.addConfig(child); } @Override public void addConfig(Config child) throws ConfigException { LOG.info("Adding configuration : " + child.getName()); this.library.addConfig(child); } public Loader newLoader() { return loader.newLoader(); } @Override public PropertyContainer getProperty(String propName) { return dynamicObserver.create(propName); } @Override public void setProperty(String propName, Object propValue) { PropertyContainer prop = dynamicObserver.get(propName); runtime.setProperty(propName, propValue); if (prop != null) { prop.update(); } } @Override public void clearProperty(String propName) { PropertyContainer prop = dynamicObserver.get(propName); runtime.clearProperty(propName); if (prop != null) { prop.update(); } } @Override public void setProperties(Properties properties) { runtime.setProperties(properties); dynamicObserver.invalidate(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy