diff --git a/pulsar-functions/instance/pom.xml b/pulsar-functions/instance/pom.xml
index 0929d5ff2101b..b8d197c0683d3 100644
--- a/pulsar-functions/instance/pom.xml
+++ b/pulsar-functions/instance/pom.xml
@@ -153,8 +153,8 @@
- com.beust
- jcommander
+ info.picocli
+ picocli
diff --git a/pulsar-functions/localrun-shaded/pom.xml b/pulsar-functions/localrun-shaded/pom.xml
index e8ac0f2faf814..ac075f7ee26fb 100644
--- a/pulsar-functions/localrun-shaded/pom.xml
+++ b/pulsar-functions/localrun-shaded/pom.xml
@@ -133,7 +133,7 @@
org.rocksdb:*
org.eclipse.jetty*:*
org.apache.avro:avro
- com.beust:*
+ info.picocli:*
net.jodah:*
io.airlift:*
com.yahoo.datasketches:*
@@ -385,8 +385,8 @@
org.apache.pulsar.shaded.com.yahoo.sketches
- com.beust
- org.apache.pulsar.functions.runtime.shaded.com.beust
+ info.picocli
+ org.apache.pulsar.functions.runtime.shaded.info.picocli
diff --git a/pulsar-functions/localrun/src/main/java/org/apache/pulsar/functions/LocalRunner.java b/pulsar-functions/localrun/src/main/java/org/apache/pulsar/functions/LocalRunner.java
index 711fa33edb2a2..3b1c86a68c285 100644
--- a/pulsar-functions/localrun/src/main/java/org/apache/pulsar/functions/LocalRunner.java
+++ b/pulsar-functions/localrun/src/main/java/org/apache/pulsar/functions/LocalRunner.java
@@ -20,9 +20,6 @@
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import static org.apache.pulsar.common.functions.Utils.inferMissingArguments;
-import com.beust.jcommander.IStringConverter;
-import com.beust.jcommander.JCommander;
-import com.beust.jcommander.Parameter;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParser;
@@ -87,6 +84,10 @@
import org.apache.pulsar.functions.utils.functions.FunctionUtils;
import org.apache.pulsar.functions.utils.io.Connector;
import org.apache.pulsar.functions.utils.io.ConnectorUtils;
+import picocli.CommandLine;
+import picocli.CommandLine.ITypeConverter;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.TypeConversionException;
@Slf4j
public class LocalRunner implements AutoCloseable {
@@ -115,95 +116,95 @@ private static class UserCodeClassLoader {
boolean classLoaderCreated;
}
- public static class FunctionConfigConverter implements IStringConverter {
+ public static class FunctionConfigConverter implements ITypeConverter {
@Override
public FunctionConfig convert(String value) {
try {
return ObjectMapperFactory.getMapper().reader().readValue(value, FunctionConfig.class);
} catch (IOException e) {
- throw new RuntimeException("Failed to parse function config:", e);
+ throw new TypeConversionException(e.getMessage());
}
}
}
- public static class SourceConfigConverter implements IStringConverter {
+ public static class SourceConfigConverter implements ITypeConverter {
@Override
public SourceConfig convert(String value) {
try {
return ObjectMapperFactory.getMapper().reader().readValue(value, SourceConfig.class);
} catch (IOException e) {
- throw new RuntimeException("Failed to parse source config:", e);
+ throw new TypeConversionException(e.getMessage());
}
}
}
- public static class SinkConfigConverter implements IStringConverter {
+ public static class SinkConfigConverter implements ITypeConverter {
@Override
public SinkConfig convert(String value) {
try {
return ObjectMapperFactory.getMapper().reader().readValue(value, SinkConfig.class);
} catch (IOException e) {
- throw new RuntimeException("Failed to parse sink config:", e);
+ throw new TypeConversionException(e.getMessage());
}
}
}
- public static class RuntimeConverter implements IStringConverter {
+ public static class RuntimeConverter implements ITypeConverter {
@Override
public RuntimeEnv convert(String value) {
return RuntimeEnv.valueOf(value);
}
}
- @Parameter(names = "--functionConfig", description = "The json representation of FunctionConfig",
+ @Option(names = "--functionConfig", description = "The json representation of FunctionConfig",
hidden = true, converter = FunctionConfigConverter.class)
protected FunctionConfig functionConfig;
- @Parameter(names = "--sourceConfig", description = "The json representation of SourceConfig",
+ @Option(names = "--sourceConfig", description = "The json representation of SourceConfig",
hidden = true, converter = SourceConfigConverter.class)
protected SourceConfig sourceConfig;
- @Parameter(names = "--sinkConfig", description = "The json representation of SinkConfig",
+ @Option(names = "--sinkConfig", description = "The json representation of SinkConfig",
hidden = true, converter = SinkConfigConverter.class)
protected SinkConfig sinkConfig;
- @Parameter(names = "--stateStorageImplClass", description = "The implemenatation class "
+ @Option(names = "--stateStorageImplClass", description = "The implemenatation class "
+ "state storage service (by default Apache BookKeeper)", hidden = true, required = false)
protected String stateStorageImplClass;
- @Parameter(names = "--stateStorageServiceUrl", description = "The URL for the state storage service "
+ @Option(names = "--stateStorageServiceUrl", description = "The URL for the state storage service "
+ "(by default Apache BookKeeper)", hidden = true)
protected String stateStorageServiceUrl;
- @Parameter(names = "--brokerServiceUrl", description = "The URL for the Pulsar broker", hidden = true)
+ @Option(names = "--brokerServiceUrl", description = "The URL for the Pulsar broker", hidden = true)
protected String brokerServiceUrl;
- @Parameter(names = "--webServiceUrl", description = "The URL for the Pulsar web service", hidden = true)
+ @Option(names = "--webServiceUrl", description = "The URL for the Pulsar web service", hidden = true)
protected String webServiceUrl = null;
- @Parameter(names = "--clientAuthPlugin", description = "Client authentication plugin using which "
+ @Option(names = "--clientAuthPlugin", description = "Client authentication plugin using which "
+ "function-process can connect to broker", hidden = true)
protected String clientAuthPlugin;
- @Parameter(names = "--clientAuthParams", description = "Client authentication param", hidden = true)
+ @Option(names = "--clientAuthParams", description = "Client authentication param", hidden = true)
protected String clientAuthParams;
- @Parameter(names = "--useTls", description = "Use tls connection\n", hidden = true, arity = 1)
+ @Option(names = "--useTls", description = "Use tls connection\n", hidden = true, arity = "1")
protected boolean useTls;
- @Parameter(names = "--tlsAllowInsecureConnection", description = "Allow insecure tls connection\n",
- hidden = true, arity = 1)
+ @Option(names = "--tlsAllowInsecureConnection", description = "Allow insecure tls connection\n",
+ hidden = true, arity = "1")
protected boolean tlsAllowInsecureConnection;
- @Parameter(names = "--tlsHostNameVerificationEnabled", description = "Enable hostname verification", hidden = true
- , arity = 1)
+ @Option(names = "--tlsHostNameVerificationEnabled", description = "Enable hostname verification", hidden = true
+ , arity = "1")
protected boolean tlsHostNameVerificationEnabled;
- @Parameter(names = "--tlsTrustCertFilePath", description = "tls trust cert file path", hidden = true)
+ @Option(names = "--tlsTrustCertFilePath", description = "tls trust cert file path", hidden = true)
protected String tlsTrustCertFilePath;
- @Parameter(names = "--instanceIdOffset", description = "Start the instanceIds from this offset", hidden = true)
+ @Option(names = "--instanceIdOffset", description = "Start the instanceIds from this offset", hidden = true)
protected int instanceIdOffset = 0;
- @Parameter(names = "--runtime", description = "Function runtime to use (Thread/Process)", hidden = true,
+ @Option(names = "--runtime", description = "Function runtime to use (Thread/Process)", hidden = true,
converter = RuntimeConverter.class)
protected RuntimeEnv runtimeEnv;
- @Parameter(names = "--secretsProviderClassName",
+ @Option(names = "--secretsProviderClassName",
description = "Whats the classname of secrets provider", hidden = true)
protected String secretsProviderClassName;
- @Parameter(names = "--secretsProviderConfig",
+ @Option(names = "--secretsProviderConfig",
description = "Whats the config for the secrets provider", hidden = true)
protected String secretsProviderConfig;
- @Parameter(names = "--metricsPortStart", description = "The starting port range for metrics server. When running "
+ @Option(names = "--metricsPortStart", description = "The starting port range for metrics server. When running "
+ "instances as threads, one metrics server is used to host the stats for all instances.", hidden = true)
protected Integer metricsPortStart;
- @Parameter(names = "--exitOnError", description = "The starting port range for metrics server. When running "
+ @Option(names = "--exitOnError", description = "The starting port range for metrics server. When running "
+ "instances as threads, one metrics server is used to host the stats for all instances.", hidden = true)
protected boolean exitOnError;
@@ -212,11 +213,10 @@ public RuntimeEnv convert(String value) {
public static void main(String[] args) throws Exception {
LocalRunner localRunner = LocalRunner.builder().build();
- JCommander jcommander = new JCommander(localRunner);
- jcommander.setProgramName("LocalRunner");
+ CommandLine jcommander = new CommandLine(localRunner);
+ jcommander.setCommandName("LocalRunner");
- // parse args by JCommander
- jcommander.parse(args);
+ jcommander.parseArgs(args);
try {
localRunner.start(true);
} catch (Exception e) {
diff --git a/pulsar-functions/runtime/pom.xml b/pulsar-functions/runtime/pom.xml
index 4c14a4302f188..ec35c3169e814 100644
--- a/pulsar-functions/runtime/pom.xml
+++ b/pulsar-functions/runtime/pom.xml
@@ -46,8 +46,8 @@
- com.beust
- jcommander
+ info.picocli
+ picocli
diff --git a/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/JavaInstanceStarter.java b/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/JavaInstanceStarter.java
index e23838cb34396..06cfca6c41a2a 100644
--- a/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/JavaInstanceStarter.java
+++ b/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/JavaInstanceStarter.java
@@ -20,9 +20,6 @@
import static org.apache.pulsar.functions.utils.FunctionCommon.getSinkType;
import static org.apache.pulsar.functions.utils.FunctionCommon.getSourceType;
-import com.beust.jcommander.JCommander;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.converters.StringConverter;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.protobuf.Empty;
@@ -59,104 +56,104 @@
import org.apache.pulsar.functions.utils.FunctionCommon;
import org.apache.pulsar.functions.utils.functioncache.FunctionCacheManager;
import org.apache.pulsar.functions.utils.functioncache.FunctionCacheManagerImpl;
+import picocli.CommandLine;
+import picocli.CommandLine.Option;
@Slf4j
public class JavaInstanceStarter implements AutoCloseable {
- @Parameter(names = "--function_details", description = "Function details json\n", required = true)
+ @Option(names = "--function_details", description = "Function details json\n", required = true)
public String functionDetailsJsonString;
- @Parameter(
+ @Option(
names = "--jar",
- description = "Path to Jar\n",
- listConverter = StringConverter.class)
+ description = "Path to Jar\n")
public String jarFile;
- @Parameter(
+ @Option(
names = "--transform_function_jar",
- description = "Path to Transform Function Jar\n",
- listConverter = StringConverter.class)
+ description = "Path to Transform Function Jar\n")
public String transformFunctionJarFile;
- @Parameter(names = "--instance_id", description = "Instance Id\n", required = true)
+ @Option(names = "--instance_id", description = "Instance Id\n", required = true)
public int instanceId;
- @Parameter(names = "--function_id", description = "Function Id\n", required = true)
+ @Option(names = "--function_id", description = "Function Id\n", required = true)
public String functionId;
- @Parameter(names = "--function_version", description = "Function Version\n", required = true)
+ @Option(names = "--function_version", description = "Function Version\n", required = true)
public String functionVersion;
- @Parameter(names = "--pulsar_serviceurl", description = "Pulsar Service Url\n", required = true)
+ @Option(names = "--pulsar_serviceurl", description = "Pulsar Service Url\n", required = true)
public String pulsarServiceUrl;
- @Parameter(names = "--transform_function_id", description = "Transform Function Id\n")
+ @Option(names = "--transform_function_id", description = "Transform Function Id\n")
public String transformFunctionId;
- @Parameter(names = "--client_auth_plugin", description = "Client auth plugin name\n")
+ @Option(names = "--client_auth_plugin", description = "Client auth plugin name\n")
public String clientAuthenticationPlugin;
- @Parameter(names = "--client_auth_params", description = "Client auth param\n")
+ @Option(names = "--client_auth_params", description = "Client auth param\n")
public String clientAuthenticationParameters;
- @Parameter(names = "--use_tls", description = "Use tls connection\n")
+ @Option(names = "--use_tls", description = "Use tls connection\n")
public String useTls = Boolean.FALSE.toString();
- @Parameter(names = "--tls_allow_insecure", description = "Allow insecure tls connection\n")
+ @Option(names = "--tls_allow_insecure", description = "Allow insecure tls connection\n")
public String tlsAllowInsecureConnection = Boolean.FALSE.toString();
- @Parameter(names = "--hostname_verification_enabled", description = "Enable hostname verification")
+ @Option(names = "--hostname_verification_enabled", description = "Enable hostname verification")
public String tlsHostNameVerificationEnabled = Boolean.FALSE.toString();
- @Parameter(names = "--tls_trust_cert_path", description = "tls trust cert file path")
+ @Option(names = "--tls_trust_cert_path", description = "tls trust cert file path")
public String tlsTrustCertFilePath;
- @Parameter(names = "--state_storage_impl_class", description = "State Storage Service "
+ @Option(names = "--state_storage_impl_class", description = "State Storage Service "
+ "Implementation class\n", required = false)
public String stateStorageImplClass;
- @Parameter(names = "--state_storage_serviceurl", description = "State Storage Service Url\n", required = false)
+ @Option(names = "--state_storage_serviceurl", description = "State Storage Service Url\n", required = false)
public String stateStorageServiceUrl;
- @Parameter(names = "--port", description = "Port to listen on\n", required = true)
+ @Option(names = "--port", description = "Port to listen on\n", required = true)
public int port;
- @Parameter(names = "--metrics_port", description = "Port metrics will be exposed on\n", required = true)
+ @Option(names = "--metrics_port", description = "Port metrics will be exposed on\n", required = true)
public int metricsPort;
- @Parameter(names = "--max_buffered_tuples", description = "Maximum number of tuples to buffer\n", required = true)
+ @Option(names = "--max_buffered_tuples", description = "Maximum number of tuples to buffer\n", required = true)
public int maxBufferedTuples;
- @Parameter(names = "--expected_healthcheck_interval", description = "Expected interval in "
+ @Option(names = "--expected_healthcheck_interval", description = "Expected interval in "
+ "seconds between healtchecks", required = true)
public int expectedHealthCheckInterval;
- @Parameter(names = "--secrets_provider", description = "The classname of the secrets provider", required = false)
+ @Option(names = "--secrets_provider", description = "The classname of the secrets provider", required = false)
public String secretsProviderClassName;
- @Parameter(names = "--secrets_provider_config", description = "The config that needs to be "
+ @Option(names = "--secrets_provider_config", description = "The config that needs to be "
+ "passed to secrets provider", required = false)
public String secretsProviderConfig;
- @Parameter(names = "--cluster_name", description = "The name of the cluster this "
+ @Option(names = "--cluster_name", description = "The name of the cluster this "
+ "instance is running on", required = true)
public String clusterName;
- @Parameter(names = "--nar_extraction_directory", description = "The directory where "
+ @Option(names = "--nar_extraction_directory", description = "The directory where "
+ "extraction of nar packages happen", required = false)
public String narExtractionDirectory = NarClassLoader.DEFAULT_NAR_EXTRACTION_DIR;
- @Parameter(names = "--pending_async_requests", description = "Max pending async requests per instance",
+ @Option(names = "--pending_async_requests", description = "Max pending async requests per instance",
required = false)
public int maxPendingAsyncRequests = 1000;
- @Parameter(names = "--web_serviceurl", description = "Pulsar Web Service Url", required = false)
+ @Option(names = "--web_serviceurl", description = "Pulsar Web Service Url", required = false)
public String webServiceUrl = null;
- @Parameter(names = "--expose_pulsaradmin", description = "Whether the pulsar admin client "
+ @Option(names = "--expose_pulsaradmin", description = "Whether the pulsar admin client "
+ "exposed to function context, default is disabled.", required = false)
public Boolean exposePulsarAdminClientEnabled = false;
- @Parameter(names = "--ignore_unknown_config_fields",
+ @Option(names = "--ignore_unknown_config_fields",
description = "Whether to ignore unknown properties when deserializing the connector configuration.",
required = false)
public Boolean ignoreUnknownConfigFields = false;
@@ -176,9 +173,8 @@ public void start(String[] args, ClassLoader functionInstanceClassLoader, ClassL
throws Exception {
Thread.currentThread().setContextClassLoader(functionInstanceClassLoader);
- JCommander jcommander = new JCommander(this);
- // parse args by JCommander
- jcommander.parse(args);
+ CommandLine jcommander = new CommandLine(this);
+ jcommander.parseArgs(args);
InstanceConfig instanceConfig = new InstanceConfig();
instanceConfig.setFunctionId(functionId);
diff --git a/pulsar-io/docs/src/main/java/org/apache/pulsar/io/docs/ConnectorDocGenerator.java b/pulsar-io/docs/src/main/java/org/apache/pulsar/io/docs/ConnectorDocGenerator.java
index fec7b12087977..2e9d6a9f27acc 100644
--- a/pulsar-io/docs/src/main/java/org/apache/pulsar/io/docs/ConnectorDocGenerator.java
+++ b/pulsar-io/docs/src/main/java/org/apache/pulsar/io/docs/ConnectorDocGenerator.java
@@ -18,8 +18,6 @@
*/
package org.apache.pulsar.io.docs;
-import com.beust.jcommander.JCommander;
-import com.beust.jcommander.Parameter;
import com.google.common.base.Strings;
import java.io.File;
import java.io.FileOutputStream;
@@ -34,14 +32,19 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.Callable;
import lombok.extern.slf4j.Slf4j;
import org.apache.pulsar.io.core.annotations.Connector;
import org.apache.pulsar.io.core.annotations.FieldDoc;
import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Slf4j
-public class ConnectorDocGenerator {
+@Command(name = "connector-doc-gen")
+public class ConnectorDocGenerator implements Callable {
private static final String INDENT = " ";
@@ -118,41 +121,25 @@ private void generatorConnectorYamlFiles(String outputDir) throws IOException {
}
}
- /**
- * Args for stats generator.
- */
- private static class MainArgs {
- @Parameter(
- names = {"-o", "--output-dir"},
- description = "The output dir to dump connector docs",
- required = true)
- String outputDir = null;
-
- @Parameter(names = {"-h", "--help"}, description = "Show this help message")
- boolean help = false;
- }
+ @Option(
+ names = {"-o", "--output-dir"},
+ description = "The output dir to dump connector docs",
+ required = true)
+ String outputDir = null;
- public static void main(String[] args) throws Exception {
- MainArgs mainArgs = new MainArgs();
-
- JCommander commander = new JCommander();
- try {
- commander.setProgramName("connector-doc-gen");
- commander.addObject(mainArgs);
- commander.parse(args);
- if (mainArgs.help) {
- commander.usage();
- Runtime.getRuntime().exit(0);
- return;
- }
- } catch (Exception e) {
- commander.usage();
- Runtime.getRuntime().exit(1);
- return;
- }
+ @Option(names = {"-h", "--help"}, usageHelp = true, description = "Show this help message")
+ boolean help = false;
+ @Override
+ public Integer call() throws Exception {
ConnectorDocGenerator docGen = new ConnectorDocGenerator();
- docGen.generatorConnectorYamlFiles(mainArgs.outputDir);
+ docGen.generatorConnectorYamlFiles(outputDir);
+ return 0;
+ }
+
+ public static void main(String[] args) throws Exception {
+ CommandLine commander = new CommandLine(new ConnectorDocGenerator());
+ Runtime.getRuntime().exit(commander.execute(args));
}
}