diff --git a/libraries-apache-commons-2/pom.xml b/libraries-apache-commons-2/pom.xml
index 0f00bf5d84..dd1627f3ed 100644
--- a/libraries-apache-commons-2/pom.xml
+++ b/libraries-apache-commons-2/pom.xml
@@ -44,6 +44,21 @@
${mockftpserver.version}
test
+
+ org.apache.commons
+ commons-configuration2
+ ${commons-configuration2.version}
+
+
+ commons-beanutils
+ commons-beanutils
+ ${commons-beanutils.version}
+
+
+ org.apache.commons
+ commons-jexl
+ ${commons-jexl.version}
+
org.tukaani
xz
@@ -63,6 +78,9 @@
1.10.0
3.6
2.7.1
+ 2.10.0
+ 1.9.4
+ 2.1.1
1.9
1.5.5-11
diff --git a/libraries-apache-commons-2/src/main/java/com/baeldung/commons/configuration/CustomDecoder.java b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/configuration/CustomDecoder.java
new file mode 100644
index 0000000000..909ce80df7
--- /dev/null
+++ b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/configuration/CustomDecoder.java
@@ -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));
+ }
+}
diff --git a/libraries-apache-commons-2/src/main/java/com/baeldung/commons/configuration/ExternalServices.java b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/configuration/ExternalServices.java
new file mode 100644
index 0000000000..ace4ac0c4a
--- /dev/null
+++ b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/configuration/ExternalServices.java
@@ -0,0 +1,7 @@
+package com.baeldung.commons.configuration;
+
+public class ExternalServices {
+
+ public static final String BAELDUNG_WEBSITE = "https://www.baeldung.com";
+
+}
diff --git a/libraries-apache-commons-2/src/test/java/com/baeldung/commons/configuration/ConfigurationClassUnitTest.java b/libraries-apache-commons-2/src/test/java/com/baeldung/commons/configuration/ConfigurationClassUnitTest.java
new file mode 100644
index 0000000000..f6e15b9809
--- /dev/null
+++ b/libraries-apache-commons-2/src/test/java/com/baeldung/commons/configuration/ConfigurationClassUnitTest.java
@@ -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 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 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