It would be nice having a @ConditionalOnApplicationArgument("foobar")
annotation.
I know I can create my own class implements Condition
that could evaluate the ApplicationArguments
as follows:
public class ApplicationArgumentsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getBeanFactory()
.getBean(ApplicationArguments.class)
.getNonOptionArgs()
.contains("foobar");
}
}
But it would be much better if one could use program arguments the same way as @ConditionalOnProperty
.
Comment From: wilkinsona
Thanks for the suggestion. The application arguments are, by default, added to the environment in their own property source. Why do you want to be able to check for their presence specifically as application arguments rather than via any property source? You could achieve the latter using @ConditionalOnProperty
.
If we added @ConditionalOnApplicationArgument
, it would then seem logical to add @ConditionalOnSystemProperty
, @ConditionalOnEnvironmentVariable
and so on. I don't think we should do this as it rather goes against the idea of configuration being collected from different sources with well-defined precedence and then accessed from a single location, the Environment
.
Comment From: membersound
Well, it's a bit cleaner being able to simply send some program arguments, instead of having to set them via a -D
argument. Compare:
java -jar application.jar job1
java -jar application.jar job2
java -jar application.jar job3
java -jar -Dapp.job.name=job1 application.jar
java -jar -Dapp.job.name=job2 application.jar
java -jar -Dapp.job.name=job3 application.jar
Comment From: wilkinsona
They don't have to be system properties. Any option args will be available in the environment via Framework's SimpleCommandLinePropertySource
. For example the args --arg1 --arg2=value arg3
will result in arg1
and arg2
both being added to the environment with the values ""
and "value"
respectively.
Comment From: membersound
But can --arg
arguments be applied to @ConditionalOnProperty
or any other existing @Conditional
annotation?
Comment From: wilkinsona
Yes. As I described above, the application arguments are added to the environment so they can be checked by @ConditionalOnProperty
just like any other property. Here's an example:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
@SpringBootApplication
public class Gh28920Application {
public static void main(String[] args) {
SpringApplication.run(Gh28920Application.class, new String[] {"--arg1", "--arg2=value", "arg3"});
}
@Component
@ConditionalOnProperty(name = "arg1")
static class Example {
Example() {
System.out.println("arg1 was present");
}
}
}
This will output arg1 was present
when run. If you remove --arg1
from the arguments, arg1 was present
will not be output.
I'm going to close this one now as I can't see a need for separate handling application arguments.
Comment From: membersound
Okay I agree that your proposed solution is a good replacement for ApplicationArgument Condition!
Comment From: membersound
I can confirm now that switching to @ConditionalOnProperty("foobar")
was most easiest alternative, and can be tested with @SpringBootTest(args="--foobar")
as well.