BAEL-7617: Intro to Apache Commons Configuration (#16281)
* BAEL-7617: Intro to Apache Commons Configuration * BAEL-7617: Review Comments * BAEL-7617: Review Comments * BAEL-7617: Review Comments
This commit is contained in:
parent
639614cd65
commit
3240f5b820
|
@ -44,6 +44,21 @@
|
|||
<version>${mockftpserver.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-configuration2</artifactId>
|
||||
<version>${commons-configuration2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>${commons-beanutils.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-jexl</artifactId>
|
||||
<version>${commons-jexl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.tukaani</groupId>
|
||||
<artifactId>xz</artifactId>
|
||||
|
@ -63,6 +78,9 @@
|
|||
<apache-commons-text.version>1.10.0</apache-commons-text.version>
|
||||
<commons-net.version>3.6</commons-net.version>
|
||||
<mockftpserver.version>2.7.1</mockftpserver.version>
|
||||
<commons-configuration2.version>2.10.0</commons-configuration2.version>
|
||||
<commons-beanutils.version>1.9.4</commons-beanutils.version>
|
||||
<commons-jexl.version>2.1.1</commons-jexl.version>
|
||||
<xz.version>1.9</xz.version>
|
||||
<zstd-jni.version>1.5.5-11</zstd-jni.version>
|
||||
</properties>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.baeldung.commons.configuration;
|
||||
|
||||
import org.apache.commons.configuration2.ConfigurationDecoder;
|
||||
import org.apache.commons.net.util.Base64;
|
||||
|
||||
public class CustomDecoder implements ConfigurationDecoder {
|
||||
|
||||
@Override
|
||||
public String decode(String encodedValue) {
|
||||
return new String(Base64.decodeBase64(encodedValue));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.baeldung.commons.configuration;
|
||||
|
||||
public class ExternalServices {
|
||||
|
||||
public static final String BAELDUNG_WEBSITE = "https://www.baeldung.com";
|
||||
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
package com.baeldung.commons.configuration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.apache.commons.configuration2.AbstractConfiguration;
|
||||
import org.apache.commons.configuration2.Configuration;
|
||||
import org.apache.commons.configuration2.PropertiesConfiguration;
|
||||
import org.apache.commons.configuration2.XMLConfiguration;
|
||||
import org.apache.commons.configuration2.builder.fluent.Configurations;
|
||||
import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
|
||||
import org.apache.commons.configuration2.ex.ConfigurationException;
|
||||
import org.apache.commons.configuration2.ex.ConversionException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ConfigurationClassUnitTest {
|
||||
|
||||
@Test
|
||||
void givenPropertiesFile_whenReadingWithConfigurationClass_thenIsLoaded() throws ConfigurationException {
|
||||
Configurations configs = new Configurations();
|
||||
Configuration config = configs.properties(new File("src/test/resources/configuration/file.properties"));
|
||||
String dbHost = config.getString("db.host");
|
||||
int dbPort = config.getInt("db.port");
|
||||
String dbUser = config.getString("db.user");
|
||||
String dbPassword = config.getString("undefinedKey", "defaultValue");
|
||||
assertEquals("baeldung.com", dbHost);
|
||||
assertEquals(9999, dbPort);
|
||||
assertEquals("admin", dbUser);
|
||||
assertEquals("defaultValue", dbPassword);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenXMLFile_whenReadingWithConfigurationClass_thenIsLoaded() throws ConfigurationException {
|
||||
Configurations configs = new Configurations();
|
||||
XMLConfiguration config = configs.xml(new File("src/test/resources/configuration/hierarchical.xml"));
|
||||
String appender = config.getString("appender[@name]");
|
||||
List<String> encoderPatterns = config.getList(String.class, "appender.encoder.pattern");
|
||||
String pattern1 = config.getString("appender.encoder.pattern(0)");
|
||||
assertEquals("STDOUT", appender);
|
||||
assertEquals(2, encoderPatterns.size());
|
||||
assertEquals("Pattern1", pattern1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenPropertiesFile_whenCopyingConfiguration_thenIsSuccessful() throws ConfigurationException {
|
||||
Configurations configs = new Configurations();
|
||||
Configuration baseConfig = configs.properties(new File("src/test/resources/configuration/file.properties"));
|
||||
Configuration subConfig = new PropertiesConfiguration();
|
||||
subConfig.addProperty("db.host", "baeldung");
|
||||
subConfig.addProperty("db.driver", "dummyDriver");
|
||||
((AbstractConfiguration) subConfig).copy(baseConfig);
|
||||
String dbHost = subConfig.getString("db.host");
|
||||
String dbDriver = subConfig.getString("db.driver");
|
||||
int dbPort = subConfig.getInt("db.port");
|
||||
String dbUser = subConfig.getString("db.user");
|
||||
assertEquals("baeldung.com", dbHost);
|
||||
assertEquals(9999, dbPort);
|
||||
assertEquals("admin", dbUser);
|
||||
assertEquals("dummyDriver", dbDriver);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPropertiesFile_whenAppendingConfiguration_thenIsSuccessful() throws ConfigurationException {
|
||||
Configurations configs = new Configurations();
|
||||
Configuration baseConfig = configs.properties(new File("src/test/resources/configuration/file.properties"));
|
||||
Configuration subConfig = new PropertiesConfiguration();
|
||||
subConfig.addProperty("db.host", "baeldung");
|
||||
subConfig.addProperty("db.driver", "dummyDriver");
|
||||
((AbstractConfiguration) subConfig).append(baseConfig);
|
||||
String dbHost = subConfig.getString("db.host");
|
||||
String dbDriver = subConfig.getString("db.driver");
|
||||
int dbPort = subConfig.getInt("db.port");
|
||||
String dbUser = subConfig.getString("db.user");
|
||||
assertEquals("baeldung", dbHost);
|
||||
assertEquals(9999, dbPort);
|
||||
assertEquals("admin", dbUser);
|
||||
assertEquals("dummyDriver", dbDriver);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenXMLFile_whenCloningConfiguration_thenIsSuccessful() throws ConfigurationException {
|
||||
Configurations configs = new Configurations();
|
||||
XMLConfiguration baseConfig = configs.xml(new File("src/test/resources/configuration/hierarchical.xml"));
|
||||
XMLConfiguration subConfig = new XMLConfiguration();
|
||||
//subConfig = (XMLConfiguration) baseConfig.clone();
|
||||
subConfig = new XMLConfiguration(baseConfig);
|
||||
String appender = subConfig.getString("appender[@name]");
|
||||
List<String> encoderPatterns = subConfig.getList(String.class, "appender.encoder.pattern");
|
||||
String pattern1 = subConfig.getString("appender.encoder.pattern(0)");
|
||||
assertEquals("STDOUT", appender);
|
||||
assertEquals(2, encoderPatterns.size());
|
||||
assertEquals("Pattern1", pattern1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEncodedProperty_whenCustomDecoderImplemented_thenIsSuccessful() throws ConfigurationException {
|
||||
Configurations configs = new Configurations();
|
||||
Configuration config = configs.properties(new File("src/test/resources/configuration/file.properties"));
|
||||
((AbstractConfiguration) config).setConfigurationDecoder(new CustomDecoder());
|
||||
assertEquals("mySecretString", config.getEncodedString("db.password"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenDataTypeConversionAttempted_thenIsSuccessful() {
|
||||
Configuration config = new PropertiesConfiguration();
|
||||
config.addProperty("stringProperty", "This is a string");
|
||||
config.addProperty("numericProperty", "9999");
|
||||
config.addProperty("booleanProperty", "true");
|
||||
assertEquals("This is a string", config.getString("stringProperty"));
|
||||
assertEquals(9999, config.getInt("numericProperty"));
|
||||
assertTrue(config.getBoolean("booleanProperty"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenDataTypeConversionAttempted_thenThrowsException() {
|
||||
Configuration config = new PropertiesConfiguration();
|
||||
config.addProperty("numericProperty", "9999a");
|
||||
assertThrows(ConversionException.class, () -> config.getInt("numericProperty"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenInterpolationIsAttempted_thenIsSuccessful() throws ConfigurationException {
|
||||
System.setProperty("user.name", "Baeldung");
|
||||
Configurations configs = new Configurations();
|
||||
Configuration config = configs.properties(new File("src/test/resources/configuration/file.properties"));
|
||||
String dbUrl = config.getString("db.url");
|
||||
String userName = config.getString("db.username");
|
||||
String externalService = config.getString("db.external-service");
|
||||
assertEquals("baeldung.com:9999", dbUrl);
|
||||
assertEquals("Baeldung", userName);
|
||||
assertEquals("https://www.baeldung.com", externalService);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenDelimiterIsSpecified_thenMultiValuePropertyIsLoaded() {
|
||||
PropertiesConfiguration propertiesConfig = new PropertiesConfiguration();
|
||||
propertiesConfig.setListDelimiterHandler(new DefaultListDelimiterHandler(';'));
|
||||
propertiesConfig.addProperty("delimitedProperty", "admin;read-only;read-write");
|
||||
propertiesConfig.addProperty("arrayProperty", "value1;value2");
|
||||
List<Object> delimitedProperties = propertiesConfig.getList("delimitedProperty");
|
||||
String[] arrayProperties = propertiesConfig.getStringArray("arrayProperty");
|
||||
assertEquals(3, delimitedProperties.size());
|
||||
assertEquals("admin", delimitedProperties.get(0));
|
||||
assertEquals(2, arrayProperties.length);
|
||||
assertEquals("value1", propertiesConfig.getString("arrayProperty"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPropertiesAreMissing_thenIsHandled() {
|
||||
PropertiesConfiguration propertiesConfig = new PropertiesConfiguration();
|
||||
String objectProperty = propertiesConfig.getString("anyProperty");
|
||||
int primitiveProperty = propertiesConfig.getInt("anyProperty", 1);
|
||||
assertNull(objectProperty);
|
||||
assertEquals(1, primitiveProperty);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPropertiesAreMissing_thenExceptionIsThrown() {
|
||||
PropertiesConfiguration propertiesConfig = new PropertiesConfiguration();
|
||||
assertThrows(NoSuchElementException.class, () -> propertiesConfig.getInt("anyProperty"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.baeldung.commons.configuration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.configuration2.Configuration;
|
||||
import org.apache.commons.configuration2.FileBasedConfiguration;
|
||||
import org.apache.commons.configuration2.PropertiesConfiguration;
|
||||
import org.apache.commons.configuration2.XMLConfiguration;
|
||||
import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
|
||||
import org.apache.commons.configuration2.builder.fluent.Parameters;
|
||||
import org.apache.commons.configuration2.ex.ConfigurationException;
|
||||
import org.apache.commons.configuration2.interpol.ConfigurationInterpolator;
|
||||
import org.apache.commons.configuration2.interpol.ExprLookup;
|
||||
import org.apache.commons.configuration2.interpol.Lookup;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class FileBasedConfigurationBuilderUnitTest {
|
||||
|
||||
@Test
|
||||
void whenReadingPropertiesFile_thenIsSuccessful() throws ConfigurationException {
|
||||
Parameters params = new Parameters();
|
||||
FileBasedConfigurationBuilder<FileBasedConfiguration> builder = new FileBasedConfigurationBuilder<FileBasedConfiguration>(
|
||||
PropertiesConfiguration.class).configure(params.properties()
|
||||
.setFileName("src/test/resources/configuration/file1.properties"));
|
||||
Configuration config = builder.getConfiguration();
|
||||
String dbHost = config.getString("db.host");
|
||||
int dbPort = config.getInt("db.port");
|
||||
String dbUser = config.getString("db.user");
|
||||
assertEquals("baeldung.com", dbHost);
|
||||
assertEquals(9999, dbPort);
|
||||
assertEquals("admin", dbUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenReadingXMLFile_thenIsSuccessful() throws ConfigurationException {
|
||||
Parameters params = new Parameters();
|
||||
FileBasedConfigurationBuilder<XMLConfiguration> builder = new FileBasedConfigurationBuilder<>(XMLConfiguration.class).configure(params.xml()
|
||||
.setFileName("src/test/resources/configuration/hierarchical.xml")
|
||||
.setValidating(true));
|
||||
XMLConfiguration config = builder.getConfiguration();
|
||||
String appender = config.getString("appender[@name]");
|
||||
List<String> encoderPatterns = config.getList(String.class, "appender.encoder.pattern");
|
||||
assertEquals("STDOUT", appender);
|
||||
assertEquals(2, encoderPatterns.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenExpressionEvaluationIsAttempted_thenIsSuccessful() throws ConfigurationException {
|
||||
System.setProperty("user.home", "/usr/lib");
|
||||
Parameters params = new Parameters();
|
||||
Map<String, Lookup> lookups = new HashMap<>(ConfigurationInterpolator.getDefaultPrefixLookups());
|
||||
ExprLookup.Variables variables = new ExprLookup.Variables();
|
||||
variables.add(new ExprLookup.Variable("System", "Class:java.lang.System"));
|
||||
ExprLookup exprLookup = new ExprLookup(variables);
|
||||
exprLookup.setInterpolator(new ConfigurationInterpolator());
|
||||
lookups.put("expr", exprLookup);
|
||||
FileBasedConfigurationBuilder<FileBasedConfiguration> builder = new FileBasedConfigurationBuilder<FileBasedConfiguration>(
|
||||
PropertiesConfiguration.class).configure(params.properties()
|
||||
.setFileName("src/test/resources/configuration/file1.properties")
|
||||
.setPrefixLookups(lookups));
|
||||
Configuration config = builder.getConfiguration();
|
||||
String dbDumpLocation = config.getString("db.data-dump-location");
|
||||
assertEquals("/usr/lib/dump.dat", dbDumpLocation);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.baeldung.commons.configuration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.apache.commons.configuration2.Configuration;
|
||||
import org.apache.commons.configuration2.PropertiesConfiguration;
|
||||
import org.apache.commons.configuration2.builder.combined.MultiFileConfigurationBuilder;
|
||||
import org.apache.commons.configuration2.builder.fluent.Parameters;
|
||||
import org.apache.commons.configuration2.ex.ConfigurationException;
|
||||
import org.apache.commons.configuration2.interpol.ConfigurationInterpolator;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class MultiFileConfigurationBuilderUnitTest {
|
||||
|
||||
@Test
|
||||
void givenMultiplePropertyFiles_whenReadingWithMultiFileConfigurationBuilder_thenIsLoaded() throws ConfigurationException {
|
||||
System.setProperty("tenant", "A");
|
||||
String filePattern = "src/test/resources/configuration/tenant-${sys:tenant}.properties";
|
||||
MultiFileConfigurationBuilder<PropertiesConfiguration> builder = new MultiFileConfigurationBuilder<>(PropertiesConfiguration.class).configure(
|
||||
new Parameters().multiFile()
|
||||
.setFilePattern(filePattern)
|
||||
.setPrefixLookups(ConfigurationInterpolator.getDefaultPrefixLookups()));
|
||||
Configuration config = builder.getConfiguration();
|
||||
String tenantAName = config.getString("name");
|
||||
|
||||
assertEquals("Tenant A", tenantAName);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
db.host=baeldung.com
|
||||
db.port=9999
|
||||
db.user=admin
|
||||
db.password=bXlTZWNyZXRTdHJpbmc=
|
||||
db.url=${db.host}:${db.port}
|
||||
db.username=${sys:user.name}
|
||||
db.external-service=${const:com.baeldung.commons.configuration.ExternalServices.BAELDUNG_WEBSITE}
|
||||
db.data-dump-location=${expr:System.getProperty("user.home")}/dump.dat
|
|
@ -0,0 +1,4 @@
|
|||
db.host=baeldung.com
|
||||
|
||||
include=file.properties
|
||||
includeOptional=file2.properties
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE configuration SYSTEM "validation-sample.dtd">
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>Pattern1</pattern>
|
||||
<pattern>Pattern2</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root>
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -0,0 +1 @@
|
|||
name=Tenant A
|
|
@ -0,0 +1,13 @@
|
|||
<!ELEMENT configuration (appender+, root)>
|
||||
<!ELEMENT appender (encoder?)>
|
||||
<!ATTLIST appender
|
||||
name CDATA #REQUIRED
|
||||
class CDATA #REQUIRED
|
||||
>
|
||||
<!ELEMENT encoder (pattern+)>
|
||||
<!ELEMENT pattern (#PCDATA)>
|
||||
<!ELEMENT root (appender-ref+)>
|
||||
<!ELEMENT appender-ref EMPTY>
|
||||
<!ATTLIST appender-ref
|
||||
ref CDATA #REQUIRED
|
||||
>
|
Loading…
Reference in New Issue