or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

access.mdexceptions.mdindex.mdloading.mdoptions.mdresolution.mdvalues.md

options.mddocs/

0

# Options and Customization

1

2

Options and customization provide comprehensive control over parsing, resolution, and rendering behavior. The library offers extensive configuration through option classes and extension interfaces for custom includers, resolvers, and loading strategies.

3

4

## Parse Options

5

6

### ConfigParseOptions Class

7

8

Control configuration parsing behavior with comprehensive options.

9

10

```java { .api }

11

public final class ConfigParseOptions {

12

public static ConfigParseOptions defaults();

13

public ConfigParseOptions setSyntax(ConfigSyntax syntax);

14

public ConfigParseOptions setOriginDescription(String originDescription);

15

public ConfigParseOptions setAllowMissing(boolean allowMissing);

16

public ConfigParseOptions setClassLoader(ClassLoader loader);

17

public ConfigParseOptions setIncluder(ConfigIncluder includer);

18

public ConfigSyntax getSyntax();

19

public String getOriginDescription();

20

public boolean getAllowMissing();

21

public ClassLoader getClassLoader();

22

public ConfigIncluder getIncluder();

23

}

24

```

25

26

**Usage Examples:**

27

28

```java

29

// Parse with specific syntax

30

ConfigParseOptions jsonOptions = ConfigParseOptions.defaults()

31

.setSyntax(ConfigSyntax.JSON);

32

Config config = ConfigFactory.parseString(jsonString, jsonOptions);

33

34

// Allow missing files

35

ConfigParseOptions lenientOptions = ConfigParseOptions.defaults()

36

.setAllowMissing(true);

37

Config config = ConfigFactory.parseFile(optionalFile, lenientOptions);

38

39

// Custom origin description for debugging

40

ConfigParseOptions describedOptions = ConfigParseOptions.defaults()

41

.setOriginDescription("generated config from service discovery");

42

Config config = ConfigFactory.parseString(dynamicConfig, describedOptions);

43

44

// Custom classloader for resource loading

45

ConfigParseOptions loaderOptions = ConfigParseOptions.defaults()

46

.setClassLoader(pluginClassLoader);

47

Config config = ConfigFactory.parseResources("plugin.conf", loaderOptions);

48

```

49

50

### Syntax Options

51

52

Control file format interpretation with ConfigSyntax enum.

53

54

```java { .api }

55

public enum ConfigSyntax {

56

JSON, // Strict JSON format

57

CONF, // HOCON format (Human-Optimized Config Object Notation)

58

PROPERTIES // Java Properties format

59

}

60

```

61

62

**Usage Examples:**

63

64

```java

65

// Force JSON parsing (strict)

66

Config jsonConfig = ConfigFactory.parseString(jsonString,

67

ConfigParseOptions.defaults().setSyntax(ConfigSyntax.JSON));

68

69

// Force HOCON parsing (allows comments, includes, etc.)

70

Config hoconConfig = ConfigFactory.parseString(hoconString,

71

ConfigParseOptions.defaults().setSyntax(ConfigSyntax.CONF));

72

73

// Force Properties parsing

74

Config propsConfig = ConfigFactory.parseString(propsString,

75

ConfigParseOptions.defaults().setSyntax(ConfigSyntax.PROPERTIES));

76

77

// Auto-detect syntax (default behavior)

78

Config autoConfig = ConfigFactory.parseString(unknownFormat);

79

```

80

81

## Resolve Options

82

83

### ConfigResolveOptions Class

84

85

Control substitution resolution behavior.

86

87

```java { .api }

88

public final class ConfigResolveOptions {

89

public static ConfigResolveOptions defaults();

90

public static ConfigResolveOptions noSystem();

91

public ConfigResolveOptions setUseSystemEnvironment(boolean value);

92

public ConfigResolveOptions setAllowUnresolved(boolean value);

93

public ConfigResolveOptions appendResolver(ConfigResolver resolver);

94

public List<ConfigResolver> getResolvers();

95

public boolean getUseSystemEnvironment();

96

public boolean getAllowUnresolved();

97

}

98

```

99

100

**Usage Examples:**

101

102

```java

103

// Disable system environment variable resolution

104

ConfigResolveOptions noEnv = ConfigResolveOptions.defaults()

105

.setUseSystemEnvironment(false);

106

Config resolved = config.resolve(noEnv);

107

108

// Allow partial resolution (don't fail on unresolved substitutions)

109

ConfigResolveOptions partial = ConfigResolveOptions.defaults()

110

.setAllowUnresolved(true);

111

Config partiallyResolved = config.resolve(partial);

112

113

// Completely isolated resolution (no system integration)

114

ConfigResolveOptions isolated = ConfigResolveOptions.noSystem();

115

Config resolved = config.resolve(isolated);

116

117

// Add custom resolvers

118

ConfigResolver customResolver = new DatabaseConfigResolver();

119

ConfigResolveOptions withCustom = ConfigResolveOptions.defaults()

120

.appendResolver(customResolver);

121

Config resolved = config.resolve(withCustom);

122

```

123

124

## Render Options

125

126

### ConfigRenderOptions Class

127

128

Control configuration rendering to strings.

129

130

```java { .api }

131

public final class ConfigRenderOptions {

132

public static ConfigRenderOptions defaults();

133

public static ConfigRenderOptions concise();

134

public ConfigRenderOptions setComments(boolean value);

135

public ConfigRenderOptions setOriginComments(boolean value);

136

public ConfigRenderOptions setFormatted(boolean value);

137

public ConfigRenderOptions setJson(boolean value);

138

public ConfigRenderOptions setShowEnvVariableValues(boolean value);

139

public boolean getComments();

140

public boolean getOriginComments();

141

public boolean getFormatted();

142

public boolean getJson();

143

public boolean getShowEnvVariableValues();

144

}

145

```

146

147

**Usage Examples:**

148

149

```java

150

Config config = ConfigFactory.load();

151

152

// Default rendering (HOCON with comments and formatting)

153

String defaultRender = config.root().render();

154

155

// Compact JSON (no comments, minimal whitespace)

156

String json = config.root().render(ConfigRenderOptions.concise().setJson(true));

157

158

// Pretty-printed HOCON without comments

159

String clean = config.root().render(

160

ConfigRenderOptions.defaults()

161

.setComments(false)

162

.setFormatted(true)

163

);

164

165

// Include file/line origin information in comments

166

String withOrigins = config.root().render(

167

ConfigRenderOptions.defaults()

168

.setOriginComments(true)

169

);

170

171

// Hide environment variable values for security

172

String secure = config.root().render(

173

ConfigRenderOptions.defaults()

174

.setShowEnvVariableValues(false)

175

);

176

```

177

178

## Custom Includers

179

180

### ConfigIncluder Interface

181

182

Customize how `include` statements are processed in configuration files.

183

184

```java { .api }

185

public interface ConfigIncluder {

186

ConfigIncluder withFallback(ConfigIncluder fallback);

187

ConfigObject include(ConfigIncludeContext context, String what);

188

}

189

```

190

191

**Specialized Includer Interfaces:**

192

193

```java { .api }

194

public interface ConfigIncluderFile extends ConfigIncluder {

195

ConfigObject includeFile(ConfigIncludeContext context, File what);

196

}

197

198

public interface ConfigIncluderURL extends ConfigIncluder {

199

ConfigObject includeURL(ConfigIncludeContext context, URL what);

200

}

201

202

public interface ConfigIncluderClasspath extends ConfigIncluder {

203

ConfigObject includeResources(ConfigIncludeContext context, String what);

204

}

205

```

206

207

**Implementation Examples:**

208

209

```java

210

// Custom includer that loads from a database

211

public class DatabaseIncluder implements ConfigIncluder {

212

private final ConfigService configService;

213

214

public DatabaseIncluder(ConfigService service) {

215

this.configService = service;

216

}

217

218

@Override

219

public ConfigObject include(ConfigIncludeContext context, String what) {

220

try {

221

String configData = configService.getConfiguration(what);

222

if (configData != null) {

223

return ConfigFactory.parseString(configData,

224

context.parseOptions().setOriginDescription("database:" + what))

225

.root();

226

}

227

} catch (Exception e) {

228

throw new ConfigException.IO(context.parseOptions().getOriginDescription(),

229

"Failed to load from database: " + what, e);

230

}

231

return null; // Not found

232

}

233

234

@Override

235

public ConfigIncluder withFallback(ConfigIncluder fallback) {

236

return new FallbackConfigIncluder(this, fallback);

237

}

238

}

239

240

// Usage

241

ConfigIncluder dbIncluder = new DatabaseIncluder(myConfigService);

242

ConfigParseOptions options = ConfigParseOptions.defaults()

243

.setIncluder(dbIncluder);

244

245

Config config = ConfigFactory.parseString(configWithIncludes, options);

246

```

247

248

### ConfigIncludeContext Interface

249

250

Context information available during include processing.

251

252

```java { .api }

253

public interface ConfigIncludeContext {

254

ConfigIncludeContext relativeTo(String filename);

255

ConfigParseOptions parseOptions();

256

}

257

```

258

259

**Usage in Custom Includers:**

260

261

```java

262

@Override

263

public ConfigObject include(ConfigIncludeContext context, String what) {

264

// Get parse options from context

265

ConfigParseOptions options = context.parseOptions();

266

ClassLoader loader = options.getClassLoader();

267

268

// Create relative context for nested includes

269

ConfigIncludeContext relativeContext = context.relativeTo(what);

270

271

// Use context information for resolution

272

String resolvedPath = resolveRelativePath(what, context);

273

274

return loadFromPath(resolvedPath, relativeContext);

275

}

276

```

277

278

## Custom Resolvers

279

280

### ConfigResolver Interface

281

282

Provide custom substitution value sources.

283

284

```java { .api }

285

public interface ConfigResolver {

286

ConfigValue lookup(String path);

287

ConfigResolver withFallback(ConfigResolver fallback);

288

}

289

```

290

291

**Implementation Examples:**

292

293

```java

294

// Resolver that fetches values from external service

295

public class ServiceConfigResolver implements ConfigResolver {

296

private final ConfigurationService service;

297

private final Map<String, ConfigValue> cache = new ConcurrentHashMap<>();

298

299

public ServiceConfigResolver(ConfigurationService service) {

300

this.service = service;

301

}

302

303

@Override

304

public ConfigValue lookup(String path) {

305

return cache.computeIfAbsent(path, this::fetchFromService);

306

}

307

308

private ConfigValue fetchFromService(String path) {

309

try {

310

String value = service.getValue(path);

311

if (value != null) {

312

return ConfigValueFactory.fromAnyRef(value, "service:" + path);

313

}

314

} catch (Exception e) {

315

// Log but don't fail - allow fallback resolvers

316

logger.warn("Failed to resolve {} from service", path, e);

317

}

318

return null;

319

}

320

321

@Override

322

public ConfigResolver withFallback(ConfigResolver fallback) {

323

return new ChainedConfigResolver(this, fallback);

324

}

325

}

326

327

// Resolver for encrypted values

328

public class EncryptedConfigResolver implements ConfigResolver {

329

private final Cipher cipher;

330

331

@Override

332

public ConfigValue lookup(String path) {

333

// Only handle paths that start with "encrypted."

334

if (!path.startsWith("encrypted.")) {

335

return null;

336

}

337

338

try {

339

String encryptedValue = getEncryptedValue(path);

340

String decryptedValue = decrypt(encryptedValue);

341

return ConfigValueFactory.fromAnyRef(decryptedValue, "decrypted:" + path);

342

} catch (Exception e) {

343

throw new ConfigException.BadValue(path, "Failed to decrypt value", e);

344

}

345

}

346

}

347

```

348

349

## Custom Loading Strategy

350

351

### ConfigLoadingStrategy Interface

352

353

Override the default application configuration loading process.

354

355

```java { .api }

356

public interface ConfigLoadingStrategy {

357

Config parseApplicationConfig(ConfigParseOptions parseOptions);

358

}

359

```

360

361

**Implementation and Usage:**

362

363

```java

364

// Custom loading strategy that loads from multiple sources

365

public class MultiSourceLoadingStrategy implements ConfigLoadingStrategy {

366

@Override

367

public Config parseApplicationConfig(ConfigParseOptions parseOptions) {

368

Config base = ConfigFactory.parseResources("base.conf", parseOptions);

369

Config environment = loadEnvironmentConfig(parseOptions);

370

Config secrets = loadSecrets(parseOptions);

371

372

return secrets

373

.withFallback(environment)

374

.withFallback(base);

375

}

376

377

private Config loadEnvironmentConfig(ConfigParseOptions options) {

378

String env = System.getProperty("app.environment", "development");

379

return ConfigFactory.parseResources("environments/" + env + ".conf", options);

380

}

381

382

private Config loadSecrets(ConfigParseOptions options) {

383

// Load from secure storage

384

return secretsService.loadConfig(options);

385

}

386

}

387

388

// Register strategy via system property

389

System.setProperty("config.strategy",

390

"com.mycompany.config.MultiSourceLoadingStrategy");

391

392

// Strategy will be used automatically by ConfigFactory.load()

393

Config config = ConfigFactory.load();

394

```

395

396

## Extension Patterns

397

398

### Chaining Pattern

399

400

Many extension interfaces support chaining with fallback behavior.

401

402

```java

403

// Chain includers

404

ConfigIncluder primary = new DatabaseIncluder(dbService);

405

ConfigIncluder secondary = new S3Includer(s3Service);

406

ConfigIncluder fallback = ConfigIncluderFactory.newDefault();

407

408

ConfigIncluder chain = primary

409

.withFallback(secondary)

410

.withFallback(fallback);

411

412

// Chain resolvers

413

ConfigResolver encrypted = new EncryptedConfigResolver();

414

ConfigResolver service = new ServiceConfigResolver(configService);

415

ConfigResolver system = new SystemConfigResolver();

416

417

ConfigResolver resolverChain = encrypted

418

.withFallback(service)

419

.withFallback(system);

420

```

421

422

### Composite Pattern

423

424

Combine multiple extension instances into a single component.

425

426

```java

427

// Composite includer that delegates based on scheme

428

public class SchemeBasedIncluder implements ConfigIncluder {

429

private final Map<String, ConfigIncluder> includers = new HashMap<>();

430

431

public SchemeBasedIncluder() {

432

includers.put("http", new HttpIncluder());

433

includers.put("https", new HttpsIncluder());

434

includers.put("file", new FileIncluder());

435

includers.put("classpath", new ClasspathIncluder());

436

includers.put("database", new DatabaseIncluder());

437

}

438

439

@Override

440

public ConfigObject include(ConfigIncludeContext context, String what) {

441

URI uri = URI.create(what);

442

String scheme = uri.getScheme();

443

444

ConfigIncluder includer = includers.get(scheme);

445

if (includer != null) {

446

return includer.include(context, what);

447

}

448

449

throw new ConfigException.BadPath(what, "Unsupported include scheme: " + scheme);

450

}

451

}

452

```

453

454

## Option Validation

455

456

### Validation Patterns

457

458

Validate configuration after loading and resolution.

459

460

```java { .api }

461

public void checkValid(Config reference, String... restrictToPaths);

462

```

463

464

**Usage Examples:**

465

466

```java

467

// Load reference configuration (schema)

468

Config reference = ConfigFactory.parseResources("reference.conf");

469

470

// Load actual configuration

471

Config config = ConfigFactory.load().resolve();

472

473

// Validate against reference

474

try {

475

config.checkValid(reference);

476

// Configuration is valid

477

} catch (ConfigException.ValidationFailed e) {

478

// Handle validation errors

479

List<ConfigException.ValidationProblem> problems = e.problems();

480

for (ConfigException.ValidationProblem problem : problems) {

481

String path = problem.path();

482

String description = problem.problem();

483

System.err.println("Validation error at " + path + ": " + description);

484

}

485

}

486

487

// Validate only specific paths

488

config.checkValid(reference, "database", "server", "logging");

489

```

490

491

## Best Practices

492

493

1. **Use defaults as starting point**: Always start with `*.defaults()` and modify from there

494

2. **Chain extensions properly**: Use `withFallback()` to create robust fallback chains

495

3. **Handle errors gracefully**: Extension code should handle errors without failing the entire configuration loading process

496

4. **Cache expensive operations**: Cache results in custom resolvers and includers

497

5. **Provide meaningful origins**: Always include descriptive origin information for debugging

498

6. **Validate configurations**: Use `checkValid()` to catch configuration errors early

499

7. **Test extension code**: Thoroughly test custom includers and resolvers with various input scenarios

500

8. **Document custom behavior**: Clearly document any custom loading strategies or extensions for your team