WBLord
WBLord

Reputation: 1025

小ustom port and other arguments for the Spring application

I have seen many solutions for the problem of getting a port from the command line. But I am interested in the following problem. I want the launch to be a line

-p 9030 -t JDBC -sql postgresql

As you can see, it is important for me that the port is set using the "-p " parameter.

NOT

-Dspring-boot.run.arguments=--server.port=8085

I have some variables that need to be retrieved, before running the spring context. I have a crutch solution, directly catching arguments and overwriting them. But I have a large number of input parameters and my solution looks ugly (see the picture) I will be glad to hear your advice.

enter image description here

Upvotes: 0

Views: 1873

Answers (2)

Matt Ke
Matt Ke

Reputation: 3739

You could also use Airline 2. Airline 2 is a Java library providing an annotation-based framework for parsing command line interfaces.

Airline 2 is focused on building command-line applications, so it might be an overkill if you just want to parse some arguments. 馃檪

Definition of a command with its arguments:

@Command(name = "run", description = "Run application")
public static class RunCmd implements Runnable {

    @Option(name = {"-p", "--port"}, description = "The server's port.")
    public int port = 8080;

    public void run() {
        runCmd = this;
        SpringApplication.run(App.class);
    }

}

Here's a example which uses TomcatServletWebServerFactory to configure the server port:

@Cli(name = "App", commands = {App.RunCmd.class})
@SpringBootApplication
public class App {

    @Command(name = "run", description = "Run application")
    public static class RunCmd implements Runnable {

        @Option(name = { "-p", "--port" }, description = "The server's port.")
        public int port = 8080;

        public void run() {
            runCmd = this;
            SpringApplication.run(App.class);
        }

    }

    private static com.github.rvesse.airline.Cli<Runnable> cli;
    private static RunCmd runCmd;

    public static void main(String[] args) throws IOException {
        cli = new com.github.rvesse.airline.Cli<>(App.class);

        ParseResult<Runnable> parseResult = parseArguments(args);
        if (parseResult != null) {
            executeCommand(parseResult);
        } else {
            showUsage();
        }
    }

    private static ParseResult<Runnable> parseArguments(String[] args) {
        try {
            return cli.parseWithResult(args);
        } catch (ParseCommandMissingException e) {
            return null;
        } catch (ParseException e) {
            System.out.println("Invalid arguments: " + e.getMessage());
            throw e;
        }
    }

    private static void executeCommand(ParseResult<Runnable> parseResult) {
        Runnable r = parseResult.getCommand();
        r.run();
    }

    private static void showUsage() throws IOException {
        GlobalUsageGenerator<Runnable> helpGenerator = new CliGlobalUsageGenerator<>();
        helpGenerator.usage(cli.getMetadata(), System.out);
    }

    @Bean
    public ConfigurableServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        factory.addConnectorCustomizers(connector -> connector.setPort(runCmd.port));
        return factory;
    }

}

Upvotes: 2

Matt Ke
Matt Ke

Reputation: 3739

You can use TomcatServletWebServerFactory to configure the server port.

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.addConnectorCustomizers(connector -> connector.setPort(port));
    return factory;
}

Here's a little example which uses a static field to hold the port number, so it can later be used at the bean creation.

@SpringBootApplication
public class App {

    private static int port;

    public static void main(String[] args) throws Exception {
        Options options = createOptions();

        parseOptions(options, args);

        SpringApplication.run(App.class);
    }

    private static Options createOptions() {
        Option portOption = Option.builder("p")
                .desc("The server's port")
                .longOpt("port")
                .hasArg(true)
                .type(Integer.class)
                .required(true)
                .build();

        Options options = new Options();
        options.addOption(portOption);
        return options;
    }

    private static void parseOptions(Options options, String[] args) throws Exception {
        CommandLineParser parser = new DefaultParser();
        CommandLine commandLine;
        try {
            commandLine = parser.parse(options, args);
        } catch (ParseException e) {
            System.out.println("Could not parse arguments!");
            throw e;
        }

        try {
            port = Integer.parseInt(commandLine.getOptionValue("p"));
        } catch (NumberFormatException e) {
            System.out.println("Could not parse port argument value!");
            throw e;
        }
    }

    @Bean
    public ConfigurableServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        factory.addConnectorCustomizers(connector -> connector.setPort(port));
        return factory;
    }

}

Upvotes: 1

Related Questions