I'm creating an annotation to attach an Aspect that would take care of authenticating an user before running a CLI command in my Spring Boot app.
Here are the components:
// The annotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Authenticated {}
// The aspec
@Aspect
@Component
@Order(Ordered.LOWEST_PRECEDENCE)
class AuthenticatedAspect {
@Around("@annotation(com.menighin.picoclijava.annotation.Authenticated)")
public Object doAuthentication(ProceedingJoinPoint joinPoint) throws Throwable {
return joinPoint.proceed();
}
}
// The PicoCLI command
@Component
@Command(name = "testing", description = "Testing command")
public class TestingCommandJava implements Runnable {
@Option(
names = {"-ci", "--creator-initials"},
description = "The initials of the creator",
required = true
)
private String creatorInitials;
// setters and getters
@Override
@Authenticated
public void run() {
System.out.println("hi!");
}
}
// The boot app
@SpringBootApplication
public class PicoclijavaApplication implements CommandLineRunner {
@Autowired
private TestingCommandJava testingCommand;
public static void main(String[] args) {
SpringApplication.run(PicoclijavaApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
var cmd = new CommandLine(testingCommand);
cmd.execute(args);
}
}
Before going further into the implementation itself Im already facing the issue where the creatorInitials
are not set when I have the aspect run.
Checking this and this answers by @kriegaex my understanding is this happens because:
TestingCommand
(I can verify this debugging)So my questions are:
Thanks!
I quickly copied your code and also checked PicoCLI's manual section about Spring Boot. It explicitly warns about the dynamic proxy situation and recommends setter injection:
Your source code mentions, that you have getters and setters anyway, so you can just move the annotation onto the setter:
@Option(
names = { "-ci", "--creator-initials" },
description = "The initials of the creator",
required = true
)
public void setCreatorInitials(String creatorInitials) {
this.creatorInitials = creatorInitials;
}
Now, it works flawlessly without any ugly reflection in the aspect.