This is an automated email from the ASF dual-hosted git repository.

roryqi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 235b8f876a [MINOR] improvement(server): expose schema separator via 
the /configs endpoint (#11322)
235b8f876a is described below

commit 235b8f876a18c4d93b2000e78082cf807c152533
Author: roryqi <[email protected]>
AuthorDate: Tue Jun 2 12:51:43 2026 +0800

    [MINOR] improvement(server): expose schema separator via the /configs 
endpoint (#11322)
    
    ### What changes were proposed in this pull request?
    
    - Expose the `gravitino.schema.separator` server config through
    Gravitino's `/configs` endpoint (`ConfigServlet`) by adding it to the
    always-exposed `basicConfigEntries`.
    - Update `TestConfigServlet` expectations and add a test verifying a
    custom separator value is reflected in the response.
    
    ### Why are the changes needed?
    
    The schema separator determines how hierarchical (multi-level) schema
    names are represented at the API boundary (e.g. `:` in `A:B:C`). Clients
    and the web UI need to discover the configured separator to correctly
    construct and parse hierarchical schema names. Previously it was only a
    server-side config and was not exposed to clients.
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes. The `/configs` endpoint now includes the
    `gravitino.schema.separator` key (default `:`).
    
    ### How was this patch tested?
    
    Added/updated unit tests in `TestConfigServlet`; `./gradlew :server:test
    --tests "org.apache.gravitino.server.web.TestConfigServlet"` passes (8
    tests).
---
 .../apache/gravitino/server/web/ConfigServlet.java |  3 +-
 .../gravitino/server/web/TestConfigServlet.java    | 84 +++++++++++-----------
 2 files changed, 46 insertions(+), 41 deletions(-)

diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java 
b/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java
index a567a0ddcf..b8bdbfaa1b 100644
--- a/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java
+++ b/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java
@@ -49,7 +49,8 @@ public class ConfigServlet extends HttpServlet {
           OAuthConfig.SCOPE);
 
   private static final ImmutableSet<ConfigEntry<?>> basicConfigEntries =
-      ImmutableSet.of(Configs.AUTHENTICATORS, Configs.ENABLE_AUTHORIZATION);
+      ImmutableSet.of(
+          Configs.AUTHENTICATORS, Configs.ENABLE_AUTHORIZATION, 
Configs.SCHEMA_SEPARATOR);
 
   private final Map<String, Object> configs = Maps.newHashMap();
 
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/TestConfigServlet.java 
b/server/src/test/java/org/apache/gravitino/server/web/TestConfigServlet.java
index 24f3ac5122..a3ddee599f 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/TestConfigServlet.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/TestConfigServlet.java
@@ -25,9 +25,11 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.google.common.collect.Lists;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.Map;
 import javax.servlet.http.HttpServletResponse;
 import org.apache.gravitino.Configs;
 import org.apache.gravitino.auth.AuthenticatorType;
@@ -36,23 +38,28 @@ import org.apache.gravitino.config.ConfigConstants;
 import org.apache.gravitino.config.ConfigEntry;
 import org.apache.gravitino.server.ServerConfig;
 import org.apache.gravitino.server.authentication.OAuthConfig;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
 
 public class TestConfigServlet {
 
   @Test
   public void testConfigServlet() throws Exception {
+    Map<String, Object> configs = fetchConfigs(new ServerConfig());
+    Assertions.assertEquals(
+        Lists.newArrayList("simple"), 
configs.get(Configs.AUTHENTICATORS.getKey()));
+    Assertions.assertEquals(false, 
configs.get(Configs.ENABLE_AUTHORIZATION.getKey()));
+    Assertions.assertEquals(":", 
configs.get(Configs.SCHEMA_SEPARATOR.getKey()));
+  }
+
+  @Test
+  public void testConfigServletExposesCustomSchemaSeparator() throws Exception 
{
+    // The schema separator must reflect the configured value, not a 
hard-coded default.
     ServerConfig serverConfig = new ServerConfig();
-    ConfigServlet configServlet = new ConfigServlet(serverConfig);
-    configServlet.init();
-    HttpServletResponse res = mock(HttpServletResponse.class);
-    PrintWriter writer = mock(PrintWriter.class);
-    when(res.getWriter()).thenReturn(writer);
-    configServlet.doGet(null, res);
-    verify(writer)
-        .write(
-            
"{\"gravitino.authorization.enable\":false,\"gravitino.authenticators\":[\"simple\"]}");
-    configServlet.destroy();
+    serverConfig.set(Configs.SCHEMA_SEPARATOR, "|");
+    Map<String, Object> configs = fetchConfigs(serverConfig);
+    Assertions.assertEquals("|", 
configs.get(Configs.SCHEMA_SEPARATOR.getKey()));
   }
 
   @Test
@@ -61,16 +68,9 @@ public class TestConfigServlet {
     // absent from the response (no crash) rather than null or empty.
     ServerConfig serverConfig = new ServerConfig();
     serverConfig.set(Configs.ENABLE_AUTHORIZATION, true);
-    ConfigServlet configServlet = new ConfigServlet(serverConfig);
-    configServlet.init();
-    HttpServletResponse res = mock(HttpServletResponse.class);
-    PrintWriter writer = mock(PrintWriter.class);
-    when(res.getWriter()).thenReturn(writer);
-    configServlet.doGet(null, res);
-    verify(writer)
-        .write(
-            
"{\"gravitino.authorization.enable\":true,\"gravitino.authenticators\":[\"simple\"]}");
-    configServlet.destroy();
+    Map<String, Object> configs = fetchConfigs(serverConfig);
+    Assertions.assertEquals(true, 
configs.get(Configs.ENABLE_AUTHORIZATION.getKey()));
+    
Assertions.assertFalse(configs.containsKey(Configs.SERVICE_ADMINS.getKey()));
   }
 
   @Test
@@ -78,16 +78,10 @@ public class TestConfigServlet {
     ServerConfig serverConfig = new ServerConfig();
     serverConfig.set(Configs.ENABLE_AUTHORIZATION, true);
     serverConfig.set(Configs.SERVICE_ADMINS, Lists.newArrayList("admin1", 
"admin2"));
-    ConfigServlet configServlet = new ConfigServlet(serverConfig);
-    configServlet.init();
-    HttpServletResponse res = mock(HttpServletResponse.class);
-    PrintWriter writer = mock(PrintWriter.class);
-    when(res.getWriter()).thenReturn(writer);
-    configServlet.doGet(null, res);
-    verify(writer)
-        .write(
-            
"{\"gravitino.authorization.enable\":true,\"gravitino.authenticators\":[\"simple\"],\"gravitino.authorization.serviceAdmins\":[\"admin1\",\"admin2\"]}");
-    configServlet.destroy();
+    Map<String, Object> configs = fetchConfigs(serverConfig);
+    Assertions.assertEquals(true, 
configs.get(Configs.ENABLE_AUTHORIZATION.getKey()));
+    Assertions.assertEquals(
+        Lists.newArrayList("admin1", "admin2"), 
configs.get(Configs.SERVICE_ADMINS.getKey()));
   }
 
   @Test
@@ -103,16 +97,8 @@ public class TestConfigServlet {
 
     serverConfig.set(customConfig, "test");
     serverConfig.set(Configs.VISIBLE_CONFIGS, 
Lists.newArrayList(customConfig.getKey()));
-    ConfigServlet configServlet = new ConfigServlet(serverConfig);
-    configServlet.init();
-    HttpServletResponse res = mock(HttpServletResponse.class);
-    PrintWriter writer = mock(PrintWriter.class);
-    when(res.getWriter()).thenReturn(writer);
-    configServlet.doGet(null, res);
-    verify(writer)
-        .write(
-            
"{\"gravitino.extended.custom.config\":\"test\",\"gravitino.authorization.enable\":false,\"gravitino.authenticators\":[\"simple\"]}");
-    configServlet.destroy();
+    Map<String, Object> configs = fetchConfigs(serverConfig);
+    Assertions.assertEquals("test", configs.get(customConfig.getKey()));
   }
 
   @Test
@@ -157,4 +143,22 @@ public class TestConfigServlet {
     verify(res).setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
     configServlet.destroy();
   }
+
+  /**
+   * Invokes the servlet and parses the JSON it writes back into a map, so 
tests can assert on
+   * individual config entries instead of matching a brittle, order-dependent 
JSON string.
+   */
+  private Map<String, Object> fetchConfigs(ServerConfig serverConfig) throws 
Exception {
+    ConfigServlet configServlet = new ConfigServlet(serverConfig);
+    configServlet.init();
+    HttpServletResponse res = mock(HttpServletResponse.class);
+    PrintWriter writer = mock(PrintWriter.class);
+    when(res.getWriter()).thenReturn(writer);
+    configServlet.doGet(null, res);
+    ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
+    verify(writer).write(captor.capture());
+    configServlet.destroy();
+    return ObjectMapperProvider.objectMapper()
+        .readValue(captor.getValue(), new TypeReference<Map<String, Object>>() 
{});
+  }
 }

Reply via email to