7

Considering a Spring Boot CommandLineRunner Application, I would like to know how to filter the "switch" options passed to Spring Boot as externalized configuration.

For example, with:

@Component
public class FileProcessingCommandLine implements CommandLineRunner {
    @Override
    public void run(String... strings) throws Exception {
        for (String filename: strings) {
           File file = new File(filename);
           service.doSomething(file);
        }
    }
}

I can call java -jar myJar.jar /tmp/file1 /tmp/file2 and the service will be called for both files.

But if I add a Spring parameter, like java -jar myJar.jar /tmp/file1 /tmp/file2 --spring.config.name=myproject then the configuration name is updated (right!) but the service is also called for file ./--spring.config.name=myproject which of course doesn't exist.

I know I can filter manually on the filename with something like

if (!filename.startsWith("--")) ...

But as all of this components came from Spring, I wonder if there is not a option somewhere to let it manage it, and to ensure the strings parameter passed to the run method will not contain at all the properties options already parsed at the Application level.

JR Utily
  • 1,792
  • 1
  • 23
  • 38

4 Answers4

9

Thanks to @AndyWilkinson enhancement report, ApplicationRunner interface was added in Spring Boot 1.3.0 (still in Milestones at the moment, but will soon be released I hope)

Here the way to use it and solve the issue:

@Component
public class FileProcessingCommandLine implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {
        for (String filename : applicationArguments.getNonOptionArgs()) 
           File file = new File(filename);
           service.doSomething(file);
        }
    }
}
JR Utily
  • 1,792
  • 1
  • 23
  • 38
3

There's no support for this in Spring Boot at the moment. I've opened an enhancement issue so that we can consider it for a future release.

Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
1

One option is to use Commons CLI in the run() of your CommandLineRunner impl.

There is a related question that you may be interested.

Community
  • 1
  • 1
Arun Avanathan
  • 982
  • 4
  • 11
  • 26
  • Well, when you see the list of alternatives... this is exactly why I would like Spring to choose for me the way it is done without having to investigate all the possible means to do it. Thanks anyway ! – JR Utily Dec 22 '14 at 11:08
1

Here is another solution :

@Component
public class FileProcessingCommandLine implements CommandLineRunner {

    @Autowired
    private ApplicationConfig config;

    @Override
    public void run(String... strings) throws Exception {

        for (String filename: config.getFiles()) {
           File file = new File(filename);
           service.doSomething(file);
        }
    }
}


@Configuration
@EnableConfigurationProperties
public class ApplicationConfig {
    private String[] files;

    public String[] getFiles() {
        return files;
    }

    public void setFiles(String[] files) {
        this.files = files;
    }
}

Then run the program :

java -jar myJar.jar --files=/tmp/file1,/tmp/file2 --spring.config.name=myproject
Arun Avanathan
  • 982
  • 4
  • 11
  • 26
  • Thanks! But that is still a workaround, and I think we would lose here the interest of having a CommandLineRunner interface provided by Spring. – JR Utily Dec 29 '14 at 23:21