Prev Next

Spring / Spring boot: Difference between CommandLineRunner and ApplicationRunner

Requisite: Some basic knowledge for Spring Boot and Gradle.

Both interfaces, CommandLineRunner and ApplicationRunner works in the same way and offer a single run method.

The difference is, the CommandLineRunner interface provides access to the application arguments as a simple String array, while ApplcationRunner uses the ApplicationArguments interface, which provides access to both the raw String[] arguments as well as parsed option and non-option arguments.

Using CommandLineRunner.

package net.javapedia.springboot;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


public class SpringBootAppCommandLineRunner implements CommandLineRunner {
private static Logger logger = LoggerFactory.getLogger (SpringBootAppCommandLineRunner.class);
    public static void main(String[] args) {
        logger.debug("Main started.");
        SpringApplication.run (SpringBootAppCommandLineRunner.class, args);
        logger.debug("Main completed.");

    }

    @Override
    public void run(String... args) throws Exception {
        logger.info("Run executed.");

        for (String item: args) {
            logger.info(" args : {}", item);
        }
    }
}

Output:

4:57:34 PM: Executing task 'SpringBootAppCommandLineRunner.main()'...

> Task :compileJava UP-TO-DATE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE

> Task :SpringBootAppCommandLineRunner.main()
16:57:36.151 [main] DEBUG net.javapedia.springboot.SpringBootAppCommandLineRunner - Main started.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.9.RELEASE)

2019-10-13 16:57:36.962  INFO 7456 --- [           main] n.j.s.SpringBootAppCommandLineRunner     : Starting SpringBootAppCommandLineRunner on Home-PC with PID 7456 (C:\Users\Owner\Downloads\akka-quickstart-java\Spring-boot-Examples\build\classes\java\main started by Owner in C:\Users\Owner\Downloads\akka-quickstart-java\Spring-boot-Examples)
2019-10-13 16:57:36.966  INFO 7456 --- [           main] n.j.s.SpringBootAppCommandLineRunner     : No active profile set, falling back to default profiles: default
2019-10-13 16:57:37.123  INFO 7456 --- [           main] n.j.s.SpringBootAppCommandLineRunner     : Started SpringBootAppCommandLineRunner in 0.787 seconds (JVM running for 1.352)
2019-10-13 16:57:37.125  INFO 7456 --- [           main] n.j.s.SpringBootAppCommandLineRunner     : Run executed.
2019-10-13 16:57:37.126  INFO 7456 --- [           main] n.j.s.SpringBootAppCommandLineRunner     :  args : -pArg=1
2019-10-13 16:57:37.127  INFO 7456 --- [           main] n.j.s.SpringBootAppCommandLineRunner     :  args : -pArg2=2
2019-10-13 16:57:37.127  INFO 7456 --- [           main] n.j.s.SpringBootAppCommandLineRunner     :  args : --pArg3=3
2019-10-13 16:57:37.127  INFO 7456 --- [           main] n.j.s.SpringBootAppCommandLineRunner     :  args : pArg4=4

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.2.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 2s
2 actionable tasks: 1 executed, 1 up-to-date
4:57:37 PM: Task execution finished 'SpringBootAppCommandLineRunner.main()'.

You may observe that the program arguments are parsed and printed however the VM argument is missing with the CommandLineRunner.

Using ApplicationRunner.

package net.javapedia.springboot;

import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;

public class SpringBootApplicationRunner implements ApplicationRunner {
    private static Logger logger = LoggerFactory.getLogger(SpringBootApplicationRunner.class);
    @Override
    public void run(final ApplicationArguments args) throws Exception {
        logger.info(" Total NonOptionArgs: {}", args.getNonOptionArgs().size());
        args.getNonOptionArgs().forEach( logger::info);
        logger.info(" Totla OptionArgs: {}", args.getOptionNames().size());
        args.getOptionNames().forEach(name -> logger.info("{} = {}",name, args.getOptionValues(name)));
    }

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

You can see that ApplicationRunner can parse NonOptionArgs and OptionArgs:

  • When you pass --optionName=optionValue as program arguments, then the optionName is recognized as an optionArgs,
  • otherwise they are parsed as NonOptionArgs.

If I pass --pArg3=3,2,1,0 as the Program arguments, an optionArg will be crated with the name pArg3 and option Values will return an List< String> .

2019-10-13 18:43:51.648  INFO 10408 --- [           main] n.j.s.SpringBootApplicationRunner        : pArg4=4
2019-10-13 18:43:51.648  INFO 10408 --- [           main] n.j.s.SpringBootApplicationRunner        :  Totla OptionArgs: 1
2019-10-13 18:43:51.649  INFO 10408 --- [           main] n.j.s.SpringBootApplicationRunner        : pArg3 = [3,2,1,0]
«
»
Spring boot convert HTTP Request JSON To XML using Jackson

Comments & Discussions