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

Synthetic monitoring. Built for developers.

Join Vercel, Render, and thousands of other teams that trust Checkly to streamline monitor creation and configuration with Monitoring as Code.

Start Monitoring

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay