DEV Community

Carlos Chacin ☕👽
Carlos Chacin ☕👽

Posted on • Originally published at cchacin.github.io on

3 1

Java 8 Type-Safe Configuration with default methods

There is a common requirement in most of the Java/JavaEE projects related to how to differentiate environment configurations like development, test, QA, production, etc. for that reason there are a lot of frameworks or libraries to resolve that:

Even there is a Java Specification Request (JSR) Proposal:

How those libraries resolve the problem

Most of those libraries require to have an injection point(s) for the configurations and also the source of the configuration(s), something like this:

dev.properties:

host=localhost
port=5432
schema=public
Enter fullscreen mode Exit fullscreen mode

prod.properties:

host=production.com
port=5432
schema=public
Enter fullscreen mode Exit fullscreen mode

ConfigurationResolver.java:

class ConfigurationResolver implements SomeLibraryInterface {
  @Override
  public String resolvePropertyFilename() {
    // probably do some trick to load a global/base configuration
    // if is not provided for the library
    return String.format("%s.properties", System.getProperty("MY_ENV", "dev"));
  }
}
Enter fullscreen mode Exit fullscreen mode

MyType.java:

class MyType {
  @Configuration(key = "host")
  String host;
  @Configuration(key = "port")
  int port;
  @Configuration(key = "schema", defaultValue = "public")
  String schema;
}
Enter fullscreen mode Exit fullscreen mode

Notice that all the granularity is only needed because of lack of support for custom types

Besides that, with the new Java 8 capabilities, specifically with default methods and some utility classes are easy to get this behavior.

With Java 8 default methods

DefaultConfiguration.java:

interface DefaultConfiguration {
  default DataSource datasource {
    // create the DS with host, port and schema
    return new MyDataSource("localhost", 5432, "public");
  }
}
Enter fullscreen mode Exit fullscreen mode

DevConfiguration.java:

class DevConfiguration implements DefaultConfiguration {
  // No need to override methods if they are the same
}
Enter fullscreen mode Exit fullscreen mode

ProdConfiguration:

class ProdConfiguration implements DefaultConfiguration {
  default DataSource datasource {
    return new MyDataSource("production.com", 5432, "public");
  }
}
Enter fullscreen mode Exit fullscreen mode

ConfigurationFactory.java:

abstract class ConfigurationFactory {
    private static final Map<String, DefaultConfiguration> configurations = new HashMap<>();

    static {
        configurations.put("development", new DevConfiguration());
        configurations.put("production", new ProdConfiguration());
    }

    public static DefaultConfiguration configuration() {
        return configurations.getOrDefault(System.getProperty("MY_ENV"), new DevConfiguration());
    }
}
Enter fullscreen mode Exit fullscreen mode

Notice that you can use an enumeration instead of a map as a configuration factory.

Pros

  • Typesafe configurations
  • Support for all kinds of types not only String, Date or primitives. you can specify or example DataSource, TimeUnits, JedisPool, etc.
  • No conversion/mapping from strings to types
  • No more .properties, .xml or .yml files
  • Possibility to use other sources to fill the properties like properties files, database, rest API's, etc.
  • No library/framework/dependency required in your app

Cons

  • Changes in the configuration require to compile/deploy (this shouldn’t be a problem in the 99% of the cases)

source code

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay