Access Command-Line Arguments in Spring Boot

Learn to read Spring Boot command-line arguments with ApplicationArguments, validate options, and override configuration properties with a runnable example.

spring boot logo

Spring Boot’s ApplicationArguments separates named options from positional arguments passed at startup. Use it when a startup task needs to inspect the original arguments, including whether an option was present or repeated. If an option represents ordinary application configuration, Spring Boot also adds it to the Environment, where @Value and configuration properties can read it.

1. Pass Arguments to a Startup Job

Consider an import application that accepts a source path, a region, an optional dry-run switch, and a batch size. We can launch its packaged JAR as follows:

java -jar target/spring-boot-arguments-demo-1.0.0.jar orders.csv --region=west --dry-run --import.batch-size=50

Here, orders.csv is a non-option argument because it has no -- prefix. The other three tokens are option arguments. The --region=west option has a value, while --dry-run marks presence without supplying one. The batch-size option is also a command-line property and overrides the value in application.properties. The sample previews these inputs; it does not open the CSV file.

2. Read Options and Non-Option Arguments

The application implements CommandLineRunner, whose run() method executes after the Spring application context has started. Spring injects ApplicationArguments through the constructor, so the runner can read the parsed arguments when it runs. The same constructor receives the resolved batch-size property.

package com.howtodoinjava.arguments;

import java.util.List;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ImportApplication implements CommandLineRunner {
    private final ApplicationArguments arguments;
    private final int batchSize;

    public ImportApplication(ApplicationArguments arguments,
            @Value("${import.batch-size}") int batchSize) {
        this.arguments = arguments;
        this.batchSize = batchSize;
    }

    public static void main(String[] args) {
        SpringApplication.run(ImportApplication.class, args);
    }

    @Override
    public void run(String... rawArgs) {
        List<String> paths = arguments.getNonOptionArgs();
        if (paths.size() != 1) {
            throw new IllegalArgumentException("Provide one source path");
        }

        List<String> regions = arguments.getOptionValues("region");
        if (regions == null || regions.size() != 1 || regions.get(0).isBlank()) {
            throw new IllegalArgumentException("Provide one --region=value option");
        }

        System.out.println("source=" + paths.get(0));
        System.out.println("region=" + regions.get(0));
        System.out.println("dryRun=" + arguments.containsOption("dry-run"));
        System.out.println("batchSize=" + batchSize);
    }
}

The getNonOptionArgs() call returns the path. getOptionValues(“region”) returns the values supplied for --region, while containsOption(“dry-run”) checks whether the switch appeared. The raw run() parameter is available too, but ApplicationArguments saves us from parsing each -- token ourselves. Constructor injection also avoids reading a field-injected dependency before Spring has populated it.

With the launch command above, the application prints these values after its startup log:

source=orders.csv
region=west
dryRun=true
batchSize=50

3. Validate Missing and Repeated Options

getOptionValues() can return null when an option is absent. It can also return multiple values when the caller repeats an option. This import job accepts exactly one region, so its validation rejects both cases instead of silently choosing a value.

java -jar target/spring-boot-arguments-demo-1.0.0.jar orders.csv
java -jar target/spring-boot-arguments-demo-1.0.0.jar orders.csv --region=west --region=east

Each command fails during the runner with the same message:

java.lang.IllegalArgumentException: Provide one --region=value option

This check matters when a script assembles command lines from several sources. Otherwise a duplicate option may make the selected region ambiguous. A flag such as --dry-run uses containsOption() instead; its presence is the intended input, so the example does not require a value for it.

4. Override an Application Property

The default batch size belongs to normal application configuration. Put it in src/main/resources/application.properties:

import.batch-size=100

Without a command-line override, the constructor’s @Value("${import.batch-size}") parameter receives 100. Adding --import.batch-size=50 to the JAR command supplies a higher-priority command-line property, and the same parameter receives 50. ApplicationArguments still knows that the option was passed, but @Value reads the resolved property from Spring’s Environment. This distinction is useful when configuration may come from a file, environment variable, or startup command rather than only from the argument list.

java -jar target/spring-boot-arguments-demo-1.0.0.jar orders.csv --region=west
# batchSize=100

java -jar target/spring-boot-arguments-demo-1.0.0.jar orders.csv --region=west --import.batch-size=50
# batchSize=50

For several related settings, consider type-safe configuration properties instead of separate @Value parameters.

5. Supply Arguments with Maven

The Spring Boot Maven plugin accepts application arguments through spring-boot.run.arguments. Pass the same input to spring-boot:run like this:

mvn spring-boot:run -Dspring-boot.run.arguments="orders.csv --region=west --dry-run --import.batch-size=50"

The plugin forwards those tokens to the application. This Maven property is different from a JVM system property supplied with spring-boot.run.jvmArguments. A JVM -D flag affects the Java process itself; an application option such as --region=west is parsed by ApplicationArguments. When running a packaged JAR, put JVM options before -jar and application arguments after the JAR filename:

java -Dfile.encoding=UTF-8 -jar target/spring-boot-arguments-demo-1.0.0.jar orders.csv --region=west

See the Spring Boot Maven plugin run reference for its argument and JVM option parameters.

6. FAQs

6.1. Does a single hyphen make an ApplicationArguments option?

No. Spring’s option syntax uses two leading hyphens, as in --region=west. A token such as -x is not parsed as the x option by ApplicationArguments. Check the exact launch syntax before assuming that a shell or Maven property was forwarded as an application option.

6.2. Should I use ApplicationRunner instead of CommandLineRunner?

Use ApplicationRunner when the runner method itself should receive ApplicationArguments. CommandLineRunner receives the raw String... tokens. Both run after startup; this sample uses constructor-injected ApplicationArguments to keep the parsed view available in the class. For a simple task, either form works.

@Component
class ImportRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) {
        System.out.println(args.getNonOptionArgs());
    }
}

The snippet illustrates the alternative signature. Do not add it to the example application alongside the existing runner unless you intend both runners to execute.

7. Conclusion

Use ApplicationArguments when the startup task needs positional inputs, option presence, or repeated values. Use the Environment for settings with defaults and external overrides. Validate the arguments your job requires before doing any work, so an incomplete launch fails with a clear message.

Happy Learning!

The complete runnable example is in the Spring Boot application arguments project folder.

Leave a Comment

    • @Component is a general-purpose class-level annotation that marks a class as eligible for Spring’s auto-detection and auto-configuration mechanisms. Spring will automatically detect and register it as a bean.

      @Bean is a method-level annotation used within a @Configuration classes where the return value of that method is registered as a bean in the Spring IoC container.

  1. You can insert the URL and endpoint directly in the constructor like this

    private final UriTemplate orderSearchUrl;
    
    public OrderServiceProxy(@Value("${service.order.baseUrl}${service.order.searchEndPoint}") UriTemplate orderSearchUrl) {
        this.orderSearchUrl = orderSearchUrl;
    }
    
    service:
      order:
        baseUrl: http://order-service.com/v1
        searchEndPoint: /orderId/{orderId}/cafeId/{cafeId}
    

Comments are closed.

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.