Repository: apache/gravitino (Java)

Issue:
[Improvement] Make sure ConfigBuilder integers, longs, doubles, and booleans with leading/trailing spaces are parsed correctly
### What would you like to be improved?

Currently, common/src/main/java/org/apache/gravitino/config/ConfigBuilder.java doesn't trim config values.

Here's a test to help:
```
  @Test
  public void testTrimmedValues() {
    Map<String, String> props = new HashMap<>();

    props.put("int.key", " 1 ");
    ConfigEntry<Integer> intEntry = new ConfigBuilder("int.key").intConf();
    Assertions.assertEquals(1, intEntry.readFrom(props));

    props.put("long.key", " 2 ");
    ConfigEntry<Long> longEntry = new ConfigBuilder("long.key").longConf();
    Assertions.assertEquals(2L, longEntry.readFrom(props));

    props.put("double.key", " 3.5 ");
    ConfigEntry<Double> doubleEntry = new ConfigBuilder("double.key").doubleConf();
    Assertions.assertEquals(3.5d, doubleEntry.readFrom(props));

    props.put("boolean.key", " true ");
    ConfigEntry<Boolean> boolEntry = new ConfigBuilder("boolean.key").booleanConf();
    Assertions.assertTrue(boolEntry.readFrom(props));
  }
```

### How should we improve?

Trim non-string values


Discussion:
Hi @justinmclean , I'm working on it.



Patch:
diff --git a/common/src/main/java/org/apache/gravitino/config/ConfigBuilder.java b/common/src/main/java/org/apache/gravitino/config/ConfigBuilder.java
index d42f445e10a..9d01b9f5970 100644
--- a/common/src/main/java/org/apache/gravitino/config/ConfigBuilder.java
+++ b/common/src/main/java/org/apache/gravitino/config/ConfigBuilder.java
@@ -130,10 +130,10 @@ public ConfigEntry<Integer> intConf() {
         new ConfigEntry<>(key, version, doc, alternatives, isPublic, isDeprecated);
     Function<String, Integer> func =
         s -> {
-          if (s == null || s.isEmpty()) {
+          if (s == null || s.trim().isEmpty()) {
             return null;
           } else {
-            return Integer.parseInt(s);
+            return Integer.parseInt(s.trim());
           }
         };
     conf.setValueConverter(func);
@@ -155,10 +155,10 @@ public ConfigEntry<Long> longConf() {
         new ConfigEntry<>(key, version, doc, alternatives, isPublic, isDeprecated);
     Function<String, Long> func =
         s -> {
-          if (s == null || s.isEmpty()) {
+          if (s == null || s.trim().isEmpty()) {
             return null;
           } else {
-            return Long.parseLong(s);
+            return Long.parseLong(s.trim());
           }
         };
     conf.setValueConverter(func);
@@ -180,10 +180,10 @@ public ConfigEntry<Double> doubleConf() {
         new ConfigEntry<>(key, version, doc, alternatives, isPublic, isDeprecated);
     Function<String, Double> func =
         s -> {
-          if (s == null || s.isEmpty()) {
+          if (s == null || s.trim().isEmpty()) {
             return null;
           } else {
-            return Double.parseDouble(s);
+            return Double.parseDouble(s.trim());
           }
         };
     conf.setValueConverter(func);
@@ -205,10 +205,10 @@ public ConfigEntry<Boolean> booleanConf() {
         new ConfigEntry<>(key, version, doc, alternatives, isPublic, isDeprecated);
     Function<String, Boolean> func =
         s -> {
-          if (s == null || s.isEmpty()) {
+          if (s == null || s.trim().isEmpty()) {
             return null;
           } else {
-            return Boolean.parseBoolean(s);
+            return Boolean.parseBoolean(s.trim());
           }
         };
     conf.setValueConverter(func);


Test patch:
diff --git a/core/src/test/java/org/apache/gravitino/TestConfig.java b/core/src/test/java/org/apache/gravitino/TestConfig.java
index 36d548ce2e6..560e7f05d3c 100644
--- a/core/src/test/java/org/apache/gravitino/TestConfig.java
+++ b/core/src/test/java/org/apache/gravitino/TestConfig.java
@@ -21,6 +21,8 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Optional;
 import java.util.Properties;
@@ -150,4 +152,25 @@ public void testGetAndSet() {
     intValue = config.get(intConf);
     Assertions.assertEquals(Optional.of(2), intValue);
   }
+
+  @Test
+  public void testTrimmedValues() {
+    Map<String, String> props = new HashMap<>();
+
+    props.put("int.key", " 1 ");
+    ConfigEntry<Integer> intEntry = new ConfigBuilder("int.key").intConf();
+    Assertions.assertEquals(1, intEntry.readFrom(props));
+
+    props.put("long.key", " 2 ");
+    ConfigEntry<Long> longEntry = new ConfigBuilder("long.key").longConf();
+    Assertions.assertEquals(2L, longEntry.readFrom(props));
+
+    props.put("double.key", " 3.5 ");
+    ConfigEntry<Double> doubleEntry = new ConfigBuilder("double.key").doubleConf();
+    Assertions.assertEquals(3.5d, doubleEntry.readFrom(props));
+
+    props.put("boolean.key", " true ");
+    ConfigEntry<Boolean> boolEntry = new ConfigBuilder("boolean.key").booleanConf();
+    Assertions.assertTrue(boolEntry.readFrom(props));
+  }
 }