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

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


The following commit(s) were added to refs/heads/main by this push:
     new 221db5e9a [server] Introduce 
plugin.classloader.parent-first-patterns.additional configuration (#1222)
221db5e9a is described below

commit 221db5e9a5a0cb2b003f2888b05390173d586c8b
Author: yuxia Luo <[email protected]>
AuthorDate: Mon Sep 22 15:14:26 2025 +0800

    [server] Introduce plugin.classloader.parent-first-patterns.additional 
configuration (#1222)
---
 .../org/apache/fluss/config/ConfigOptions.java     | 16 ++++++-
 .../java/org/apache/fluss/plugin/PluginConfig.java | 16 +++++--
 .../org/apache/fluss/plugin/PluginConfigTest.java  | 52 ++++++++++++++++++++++
 website/docs/maintenance/configuration.md          | 43 +++++++++---------
 4 files changed, 101 insertions(+), 26 deletions(-)

diff --git 
a/fluss-common/src/main/java/org/apache/fluss/config/ConfigOptions.java 
b/fluss-common/src/main/java/org/apache/fluss/config/ConfigOptions.java
index 07de50bfc..8b4664d70 100644
--- a/fluss-common/src/main/java/org/apache/fluss/config/ConfigOptions.java
+++ b/fluss-common/src/main/java/org/apache/fluss/config/ConfigOptions.java
@@ -112,7 +112,21 @@ public class ConfigOptions {
                     .withDescription(
                             "A (semicolon-separated) list of patterns that 
specifies which classes should always be"
                                     + " resolved through the plugin parent 
ClassLoader first. A pattern is a simple prefix that is checked "
-                                    + " against the fully qualified class 
name. This setting should generally not be modified.");
+                                    + " against the fully qualified class 
name. This setting should generally not be modified. To add another "
+                                    + " pattern we recommend to use 
\"plugin.classloader.parent-first-patterns.additional\" instead.");
+
+    public static final ConfigOption<List<String>>
+            PLUGIN_ALWAYS_PARENT_FIRST_LOADER_PATTERNS_ADDITIONAL =
+                    key("plugin.classloader.parent-first-patterns.additional")
+                            .stringType()
+                            .asList()
+                            .defaultValues()
+                            .withDescription(
+                                    "A (semicolon-separated) list of patterns 
that specifies which classes should always be"
+                                            + " resolved through the plugin 
parent ClassLoader first. A pattern is a simple prefix that is checked "
+                                            + " against the fully qualified 
class name. These patterns are appended to \""
+                                            + 
PLUGIN_ALWAYS_PARENT_FIRST_LOADER_PATTERNS.key()
+                                            + "\".");
 
     public static final ConfigOption<Duration> AUTO_PARTITION_CHECK_INTERVAL =
             key("auto-partition.check.interval")
diff --git 
a/fluss-common/src/main/java/org/apache/fluss/plugin/PluginConfig.java 
b/fluss-common/src/main/java/org/apache/fluss/plugin/PluginConfig.java
index 07cde050a..0f97085d7 100644
--- a/fluss-common/src/main/java/org/apache/fluss/plugin/PluginConfig.java
+++ b/fluss-common/src/main/java/org/apache/fluss/plugin/PluginConfig.java
@@ -17,16 +17,20 @@
 
 package org.apache.fluss.plugin;
 
-import org.apache.fluss.config.ConfigOptions;
 import org.apache.fluss.config.Configuration;
+import org.apache.fluss.shaded.guava32.com.google.common.collect.Iterables;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.nio.file.Path;
+import java.util.List;
 import java.util.Optional;
 
+import static 
org.apache.fluss.config.ConfigOptions.PLUGIN_ALWAYS_PARENT_FIRST_LOADER_PATTERNS;
+import static 
org.apache.fluss.config.ConfigOptions.PLUGIN_ALWAYS_PARENT_FIRST_LOADER_PATTERNS_ADDITIONAL;
+
 /** Stores the configuration for plugins mechanism. */
 @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
 public class PluginConfig {
@@ -62,9 +66,13 @@ public class PluginConfig {
     public static PluginConfig fromConfiguration(Configuration configuration) {
         return new PluginConfig(
                 getPluginsDir().map(File::toPath),
-                configuration
-                        
.get(ConfigOptions.PLUGIN_ALWAYS_PARENT_FIRST_LOADER_PATTERNS)
-                        .toArray(new String[0]));
+                getPluginParentFirstLoaderPatterns(configuration));
+    }
+
+    private static String[] getPluginParentFirstLoaderPatterns(Configuration 
config) {
+        List<String> base = 
config.get(PLUGIN_ALWAYS_PARENT_FIRST_LOADER_PATTERNS);
+        List<String> append = 
config.get(PLUGIN_ALWAYS_PARENT_FIRST_LOADER_PATTERNS_ADDITIONAL);
+        return Iterables.toArray(Iterables.concat(base, append), String.class);
     }
 
     public static Optional<File> getPluginsDir() {
diff --git 
a/fluss-common/src/test/java/org/apache/fluss/plugin/PluginConfigTest.java 
b/fluss-common/src/test/java/org/apache/fluss/plugin/PluginConfigTest.java
new file mode 100644
index 000000000..0510598d2
--- /dev/null
+++ b/fluss-common/src/test/java/org/apache/fluss/plugin/PluginConfigTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.fluss.plugin;
+
+import org.apache.fluss.config.Configuration;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static 
org.apache.fluss.config.ConfigOptions.PLUGIN_ALWAYS_PARENT_FIRST_LOADER_PATTERNS;
+import static 
org.apache.fluss.config.ConfigOptions.PLUGIN_ALWAYS_PARENT_FIRST_LOADER_PATTERNS_ADDITIONAL;
+import static org.assertj.core.api.Assertions.assertThat;
+
+/** Test for {@link PluginConfig} . */
+class PluginConfigTest {
+
+    @Test
+    void testFromConfig() {
+        // only set parent-first-patterns.default
+        Configuration config = new Configuration();
+        config.set(
+                PLUGIN_ALWAYS_PARENT_FIRST_LOADER_PATTERNS,
+                Arrays.asList("org.apache.fluss.", "java."));
+        PluginConfig pluginConfig = PluginConfig.fromConfiguration(config);
+        assertThat(pluginConfig.getAlwaysParentFirstPatterns())
+                .isEqualTo(new String[] {"org.apache.fluss.", "java."});
+        // also set parent-first-patterns.additional
+        config.set(
+                PLUGIN_ALWAYS_PARENT_FIRST_LOADER_PATTERNS_ADDITIONAL,
+                Collections.singletonList("org.apache.hadoop."));
+        pluginConfig = PluginConfig.fromConfiguration(config);
+        assertThat(pluginConfig.getAlwaysParentFirstPatterns())
+                .isEqualTo(new String[] {"org.apache.fluss.", "java.", 
"org.apache.hadoop."});
+    }
+}
diff --git a/website/docs/maintenance/configuration.md 
b/website/docs/maintenance/configuration.md
index d2fad94a1..0737fdf0e 100644
--- a/website/docs/maintenance/configuration.md
+++ b/website/docs/maintenance/configuration.md
@@ -26,27 +26,28 @@ during the Fluss cluster working.
 
 ## Common
 
-| Option                                           | Type       | Default      
                                                                                
                                                                         | 
Description                                                                     
                                                                                
                                                                                
                   [...]
-|--------------------------------------------------|------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [...]
-| bind.listeners           | String  | (None)  | The network address and port 
to which the server binds for accepting connections. This defines the interface 
and port where the server will listen for incoming requests. The format is 
`{listener_name}://{host}:{port}`, and multiple addresses can be specified, 
separated by commas. Use `0.0.0.0` for the `host` to bind to all available 
interfaces which is dangerous on production and not suggested for production 
usage. The `listener_name` serv [...]
-| advertised.listeners     | String  | (None)  | The externally advertised 
address and port for client connections. Required in distributed environments 
when the bind address is not publicly reachable. Format matches 
`bind.listeners` (`{listener_name}://{host}:{port}`). Defaults to the value of 
`bind.listeners` if not explicitly configured.                                  
                                                                                
                                     [...]
-| internal.listener.name   | String  | FLUSS   | The listener for server 
internal communication.                                                         
                                                                                
                                                                                
                                                                                
                                                                                
                    [...]
-| security.protocol.map                      | Map        |                 | 
A map defining the authentication protocol for each listener. The format is 
`listenerName1:protocol1,listenerName2:protocol2`, e.g., 
`INTERNAL:PLAINTEXT,CLIENT:GSSAPI`. Each listener can be associated with a 
specific authentication protocol. Listeners not included in the map will use 
PLAINTEXT by default, which does not require authentication.                    
                                                  [...]
-| `security.${protocol}.*`                         | String     | (none)       
                                                                                
                                                                         | 
Protocol-specific configuration properties. For example, 
security.sasl.jaas.config for SASL authentication settings.                     
                                                                                
                                          [...]
-| default.bucket.number                            | Integer    | 1            
                                                                                
                                                                         | The 
default number of buckets for a table in Fluss cluster. It's a cluster-level 
parameter and all the tables without specifying bucket number in the cluster 
will use the value as the bucket number.                                        
                     [...]
-| default.replication.factor                       | Integer    | 1            
                                                                                
                                                                         | The 
default replication factor for the log of a table in Fluss cluster. It's a 
cluster-level parameter, and all the tables without specifying replication 
factor in the cluster will use the value as replication factor.                 
                         [...]
-| remote.data.dir                                  | String     | (None)       
                                                                                
                                                                         | The 
directory used for storing the kv snapshot data files and remote log for log 
tiered storage in a Fluss supported filesystem.                                 
                                                                                
                  [...]
-| remote.fs.write-buffer-size                      | MemorySize | 4kb          
                                                                                
                                                                         | The 
default size of the write buffer for writing the local files to remote file 
systems.                                                                        
                                                                                
                   [...]
-| plugin.classloader.parent-first-patterns.default | String     | 
java.,<br/>org.apache.fluss.,<br/>javax.annotation.,<br/>org.slf4j,<br/>org.apache.log4j,<br/>org.apache.logging,<br/>org.apache.commons.logging,<br/>ch.qos.logback
 | A (semicolon-separated) list of patterns that specifies which classes should 
always be resolved through the plugin parent ClassLoader first. A pattern is a 
simple prefix that is checked against the fully qualified class name. This 
setting should generally not [...]
-| auto-partition.check.interval                    | Duration   | 10min        
                                                                                
                                                                         | The 
interval of auto partition check. The default value is 10 minutes.              
                                                                                
                                                                                
               [...]
-| allow.create.log.tables                          | Boolean    | true         
                                                                                
                                                                         | 
Whether to allow creation of log tables. When set to false, attempts to create 
log tables (tables without primary key) will be rejected. The default value is 
true.                                                                           
                     [...]
-| allow.create.kv.tables                           | Boolean    | true         
                                                                                
                                                                         | 
Whether to allow creation of kv tables (primary key tables). When set to false, 
attempts to create kv tables (tables with primary key) will be rejected. The 
default value is true.                                                          
                      [...]
-| max.partition.num                                | Integer    | 1000         
                                                                                
                                                                         | 
Limits the maximum number of partitions that can be created for a partitioned 
table to avoid creating too many partitions.                                    
                                                                                
                     [...]
-| max.bucket.num                                   | Integer    | 128000       
                                                                                
                                                                         | The 
maximum number of buckets that can be created for a table. The default value is 
128000.                                                                         
                                                                                
               [...]
-| acl.notification.expiration-time                 | Duration   | 15min        
                                                                                
                                                                         | The 
duration for which ACL notifications are valid before they expire. This 
configuration determines the time window during which an ACL notification is 
considered active. After this duration, the notification will no longer be 
valid and will be discarded. T [...]
-| authorizer.enabled                               | Boolean    | false        
                                                                                
                                                                         | 
Specifies whether to enable the authorization feature. If enabled, access 
control is enforced based on the authorization rules defined in the 
configuration. If disabled, all operations and resources are accessible to all 
users.                                [...]
-| authorizer.type                                  | String     | default      
                                                                                
                                                                         | 
Specifies the type of authorizer to be used for access control. This value 
corresponds to the identifier of the authorization plugin. The default value is 
`default`, which indicates the built-in authorizer implementation. Custom 
authorizers can be implemente [...]
-| super.users                                      | String     | (None)       
                                                                                
                                                                         | A 
semicolon-separated list of superusers who have unrestricted access to all 
operations and resources. Note that the delimiter is semicolon since SSL user 
names may contain comma, and each super user should be specified in the format 
`principal_type:principa [...]
+| Option                                              | Type               | 
Default                                                                         
                                                                                
        | Description                                                           
                                                                                
                                                                                
                [...]
+|-----------------------------------------------------|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [...]
+| bind.listeners                                      | String             | 
(None)                                                                          
                                                                                
        | The network address and port to which the server binds for accepting 
connections. This defines the interface and port where the server will listen 
for incoming requests. The format is `{listener_name}://{host}:{port}`, and 
multiple addresses can [...]
+| advertised.listeners                                | String             | 
(None)                                                                          
                                                                                
        | The externally advertised address and port for client connections. 
Required in distributed environments when the bind address is not publicly 
reachable. Format matches `bind.listeners` (`{listener_name}://{host}:{port}`). 
Defaults to the value o [...]
+| internal.listener.name                              | String             | 
FLUSS                                                                           
                                                                                
        | The listener for server internal communication.                       
                                                                                
                                                                                
                [...]
+| security.protocol.map                               | Map                | 
(none)                                                                          
                                                                                
        | A map defining the authentication protocol for each listener. The 
format is `listenerName1:protocol1,listenerName2:protocol2`, e.g., 
`INTERNAL:PLAINTEXT,CLIENT:GSSAPI`. Each listener can be associated with a 
specific authentication protocol. Lis [...]
+| `security.${protocol}.*`                            | String             | 
(none)                                                                          
                                                                                
        | Protocol-specific configuration properties. For example, 
security.sasl.jaas.config for SASL authentication settings.                     
                                                                                
                             [...]
+| default.bucket.number                               | Integer            | 1 
                                                                                
                                                                                
      | The default number of buckets for a table in Fluss cluster. It's a 
cluster-level parameter and all the tables without specifying bucket number in 
the cluster will use the value as the bucket number.                            
                    [...]
+| default.replication.factor                          | Integer            | 1 
                                                                                
                                                                                
      | The default replication factor for the log of a table in Fluss cluster. 
It's a cluster-level parameter, and all the tables without specifying 
replication factor in the cluster will use the value as replication factor.     
                        [...]
+| remote.data.dir                                     | String             | 
(None)                                                                          
                                                                                
        | The directory used for storing the kv snapshot data files and remote 
log for log tiered storage in a Fluss supported filesystem.                     
                                                                                
                 [...]
+| remote.fs.write-buffer-size                         | MemorySize         | 
4kb                                                                             
                                                                                
        | The default size of the write buffer for writing the local files to 
remote file systems.                                                            
                                                                                
                  [...]
+| plugin.classloader.parent-first-patterns.additional | List&lt;String&gt; | 
(None)                                                                          
                                                                                
        | A (semicolon-separated) list of patterns that specifies which classes 
should always be resolved through the plugin parent ClassLoader first. A 
pattern is a simple prefix that is checked against the fully qualified class 
name. These patterns are  [...]
+| plugin.classloader.parent-first-patterns.default    | String             | 
java.,<br/>org.apache.fluss.,<br/>javax.annotation.,<br/>org.slf4j,<br/>org.apache.log4j,<br/>org.apache.logging,<br/>org.apache.commons.logging,<br/>ch.qos.logback
    | A (semicolon-separated) list of patterns that specifies which classes 
should always be resolved through the plugin parent ClassLoader first. A 
pattern is a simple prefix that is checked against the fully qualified class 
name. This setting should [...]
+| auto-partition.check.interval                       | Duration           | 
10min                                                                           
                                                                                
        | The interval of auto partition check. The default value is 10 
minutes.                                                                        
                                                                                
                        [...]
+| allow.create.log.tables                             | Boolean            | 
true                                                                            
                                                                                
        | Whether to allow creation of log tables. When set to false, attempts 
to create log tables (tables without primary key) will be rejected. The default 
value is true.                                                                  
                 [...]
+| allow.create.kv.tables                              | Boolean            | 
true                                                                            
                                                                                
        | Whether to allow creation of kv tables (primary key tables). When set 
to false, attempts to create kv tables (tables with primary key) will be 
rejected. The default value is true.                                            
                       [...]
+| max.partition.num                                   | Integer            | 
1000                                                                            
                                                                                
        | Limits the maximum number of partitions that can be created for a 
partitioned table to avoid creating too many partitions.                        
                                                                                
                    [...]
+| max.bucket.num                                      | Integer            | 
128000                                                                          
                                                                                
        | The maximum number of buckets that can be created for a table. The 
default value is 128000.                                                        
                                                                                
                   [...]
+| acl.notification.expiration-time                    | Duration           | 
15min                                                                           
                                                                                
        | The duration for which ACL notifications are valid before they 
expire. This configuration determines the time window during which an ACL 
notification is considered active. After this duration, the notification will 
no longer be valid and will be [...]
+| authorizer.enabled                                  | Boolean            | 
false                                                                           
                                                                                
        | Specifies whether to enable the authorization feature. If enabled, 
access control is enforced based on the authorization rules defined in the 
configuration. If disabled, all operations and resources are accessible to all 
users.                   [...]
+| authorizer.type                                     | String             | 
default                                                                         
                                                                                
        | Specifies the type of authorizer to be used for access control. This 
value corresponds to the identifier of the authorization plugin. The default 
value is `default`, which indicates the built-in authorizer implementation. 
Custom authorizers can  [...]
+| super.users                                         | String             | 
(None)                                                                          
                                                                                
        | A semicolon-separated list of superusers who have unrestricted access 
to all operations and resources. Note that the delimiter is semicolon since SSL 
user names may contain comma, and each super user should be specified in the 
format `principal_ [...]
 
 
 ## CoordinatorServer

Reply via email to