Skip to main content

Create a configuration

Everything in Ocular starts with the Configurations class. You create it with Configurations.builder(...), which takes two things:

  1. a Key for your main configuration file,
  2. a DataFormat for that file.

Keys​

A Key describes one file. It knows the path of the file and how to create its default value.

Key<AppConfig> key = Key.builder(Path.of("config.yml"), AppConfig::new).build();

This key stands for the file config.yml inside the base directory of your configuration. The supplier creates the default value. Ocular calls it whenever it needs a fresh default, for example when the file does not exist yet. The value is not cached.

The builder also calls the supplier once right away. It uses the result to find out the class of your configuration. So the supplier must work at that point.

The class must be something Jackson can create, for example a class with a no-argument constructor.

Key options​

MethodWhat it doesDefault
name(String)A readable name for the file. It shows up in toString().The file name of the path
strict()Loading fails when the file cannot be read. The file stays as it is. See broken files.Not strict
rootPackage(String)The package of your configuration classes, used for nested overrides.The package of the configuration class

Two keys are equal when their paths are equal. A relative and an absolute path to the same file count as different keys, so stick to one style.

Paths​

A relative path is resolved against the base directory of the Configurations instance. An absolute path is used as it is and ignores the base directory.

Sub directories are fine. Ocular creates missing directories when it writes a file.

Key<Messages> messages = Key.builder(Path.of("lang", "messages.yml"), Messages::new).build();

Data formats​

Ocular ships three data formats:

ClassFormatFile endingsExtra dependency
JsonDataFormatJSONjsonnone
YamlDataFormatYAMLyaml, ymltools.jackson.dataformat:jackson-dataformat-yaml
TomlDataFormatTOMLtomltools.jackson.dataformat:jackson-dataformat-toml

See YAML and TOML for how to add the extra dependencies.

JsonDataFormat json = DataFormats.json();
JsonDataFormat prettyJson = DataFormats.json(true);
YamlDataFormat yaml = DataFormats.yaml();
TomlDataFormat toml = DataFormats.toml();

DataFormats checks that the module of a format is there. Without it, DataFormats.yaml() throws a MissingDataTypeInstallationException that names the dependency to add. Creating a format with new YamlDataFormat() works too, but then a missing module ends in a NoClassDefFoundError.

JsonDataFormat writes everything on one line by default. Pass true to get indented output.

{
"host" : "localhost",
"port" : 8080
}

YamlDataFormat writes files without the --- start marker and without native YAML type ids.

Which format reads a file​

Ocular picks the format by the end of the file path. Each format has a type and can have aliases. YAML has the type yaml and the alias yml, so both config.yaml and config.yml use it.

When several formats match, the first registered one wins. When none matches, Ocular throws an UnknownFormatException that lists the formats you registered:

No format for config.xml registered. Supported formats are: json, yaml (yml)

Make sure every file ending you use has a registered format.

Build the configuration​

Key<AppConfig> main = Key.builder(Path.of("config.json"), AppConfig::new).build();

Configurations<AppConfig> configurations = Configurations.builder(main, new JsonDataFormat())
.addFormat(new YamlDataFormat())
.setBase(Path.of("configurations"))
.build();

This instance reads and writes JSON and YAML files. All relative paths live in the configurations directory.

Builder options​

MethodWhat it doesDefault
setBase(Path)The directory that relative key paths are resolved against.Path.of("."), the working directory
addFormat(DataFormat)Registers one more data format.Only the format passed to builder(...)
addFormats(List<DataFormat<?, ?>>)Registers several data formats at once.
withClassLoader(ClassLoader)The class loader Jackson uses to find classes.The context class loader of the current thread
parent(Configurations)Another instance to fall back to. A file ending none of this instance's formats matches uses the parent's format, and the parent's modules are registered too.No parent
addModule(JacksonModule)Registers a Jackson module on every mapper. There is also a version that takes a collection.No modules
configureBuilder(...)Changes the Jackson mapper builder.
configureReaderBuilder(...)Changes the mapper builder for reading only.
configureWriterBuilder(...)Changes the mapper builder for writing only.

The configure... methods are explained in Customise the mapper.

If the Jackson module of a format is missing at runtime, Ocular fails as soon as you create or register that format.

The main key is just the first file. You can load as many other files as you like through the same instance. See Load and save files.