externalized-properties icon indicating copy to clipboard operation
externalized-properties copied to clipboard

A lightweight and extensible library to resolve application properties from various external sources.

trafficstars

Externalized Properties

License Gradle Build CodeQL Maven Central Coverage Status Quality Gate Status Maintainability Rating Reliability Rating Security Rating Vulnerabilities Coverage Discord

A lightweight and extensible library to resolve application properties from various external sources.

Like the project?

Please consider giving the repository a โญ. It means a lot! Thank you :)

Twelve Factor Methodology

Externalized Properties was inspired by the The Twelve Factor Methodology's section III. Config.

The goal of this library is to make it easy for applications to implement configuration best practices by providing easy-to-use APIs as well as providing the flexibility to choose where to store their configurations/properties.

๐Ÿ› ๏ธ Installation

Gradle

implementation "io.github.joel-jeremy.externalized-properties:externalized-properties-core:${version}"
// Optional/additional resolvers
implementation "io.github.joel-jeremy.externalized-properties:externalized-properties-database:${version}"
implementation "io.github.joel-jeremy.externalized-properties:externalized-properties-git:${version}"

Maven

<dependency>
  <groupId>io.github.joel-jeremy.externalized-properties</groupId>
  <artifactId>externalized-properties-core</artifactId>
  <version>${version}</version>
</dependency>
<!-- Optional/additional resolvers -->
<dependency>
  <groupId>io.github.joel-jeremy.externalized-properties</groupId>
  <artifactId>externalized-properties-database</artifactId>
  <version>${version}</version>
</dependency>
<dependency>
  <groupId>io.github.joel-jeremy.externalized-properties</groupId>
  <artifactId>externalized-properties-git</artifactId>
  <version>${version}</version>
</dependency>

๐Ÿงฉ Java 9 Module Names

Externalized Properties jars are published with Automatic-Module-Name manifest attribute:

  • Core - io.github.joeljeremy.externalizedproperties.core
  • Database Resolver - io.github.joeljeremy.externalizedproperties.database
  • Git Resolver - io.github.joeljeremy.externalizedproperties.git

Module authors can use above module names in their module-info.java:

module foo.bar {
  requires io.github.joeljeremy.externalizedproperties.core;
  requires io.github.joeljeremy.externalizedproperties.database;
  requires io.github.joeljeremy.externalizedproperties.git;
}

๐ŸŒŸ Features

Externalized Properties takes full advantage of Java's Dynamic Proxies (Why Dynamic Proxies?).

โœ”๏ธ Property Resolution

  • Map Properties to (Java Dynamic Proxy) Interface Methods
  • Default/Fallback Values
  • Support for Property Names Known at Runtime
  • Support for Various Configuration File/Resource Formats
  • Caching
  • Eager Loading
  • Custom Resolvers

โœ”๏ธ Conversion

  • Automatic Property Conversion
  • Conversion to Generic Types
  • Conversion of Arbitrary Values
  • Custom Converters

โœ”๏ธ Variable Expansion

  • Automatic Variable Expansion in Property Names
  • Automatic Variable Expansion in Properties
  • Variable Expansion in Arbitrary Values

โœ”๏ธ Processing

  • Targeted Processing of Properties
  • Custom Processors

โœ”๏ธ Profiles

  • Profile-Specific Configurations

โœ”๏ธ Ordinal Components

  • Ordinal Resolvers
  • Ordinal Converters

๐ŸŽ๏ธ Quick Start

Properties are mapped to proxy interface methods by using the @ExternalizedProperty annotation.

(For more advanced scenarios, please see the feature documentations.)

Given an interface:

public interface ApplicationProperties {
  @ExternalizedProperty("java.home")
  String javaHome();

  @ExternalizedProperty("encrypted.property")
  @Decrypt("MyDecryptor")
  String encryptedProperty();

  @ExternalizedProperty("java.version")
  int javaVersion();
}

We can initialize and start resolving external configurations/properties by:

public static void main(String[] args) {
  // 1. Configure and build the ExternalizedProperties instance.
  ExternalizedProperties externalizedProperties = buildExternalizedProperties();

  // 2. Initialize a proxy using the ExternalizedProperties.
  ApplicationProperties props = externalizedProperties.initialize(ApplicationProperties.class);

  // 3. Resolve the properties.
  String javaHome = props.javaHome();
  String encryptedProperty = props.encryptedProperty();
  int javaVersion = props.javaVersion();
}

private static ExternalizedProperties buildExternalizedProperties() {
  return ExternalizedProperties.builder()
      .defaults() 
      .resolvers(...)
      .processors(...)
      .converters(...) 
      .build();
}

๐Ÿงช Samples

More sample can be found here: https://github.com/joel-jeremy/externalized-properties-samples