I'm setting up a SpringBoot application, which should be executed on the commandline. The application contains multiple CommandLineRunners, which run their specific logic if the needed option was passed by through the commandline execution. I use Gradle as build-tool.
There was one initialization-method in every runner to parse the options and print out the help-statement if no option was passed by, which I had outsourced into an aspect-class.
And that's how the problem starts.
At first, I had already tried it successfully with Spring AOP, but this isn't an option, because I want to bind also private methods with my aspects. So I must use the more powerful AspectJ to achieve this.
Unfortunately, AspectJ Load-Time Weaving isn't an option for me, because it requires to pass in jvm-arguments to the commandline when the jar is getting executed, which I want to avoid.
So from what I have seen now, there's only AspectJ Compile-Time Weaving and AspectJ Post-Compile-Time Weaving left.
The AspectJ Compile-Time Weaving looks the best fitting for me, but unfortunately one has to apply a plugin like the following from io.freefair.
Link: https://plugins.gradle.org/plugin/io.freefair.aspectj.compile-time-weaving
I've tried that and it had worked properly,
but my goal is to avoid adding external dependencies to my project, hence I'm trying to find a solution from the Spring or standard Java family.
Same for the Post-Compile-Time Weaving.
Every tutorial or answer concerning Compile-Time Weaving I've read was about applying a plugin.
I am wondering that I found no method to resolve my use case, except for the io.freefair plugin above.
The MainClass:
@SpringBootApplication
@ImportResource("classpath:spring/applicationContext.xml")
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
public class MainClass {
/**
* The main method.
*
* @param args the arguments
*/
public static void main(String[] args) {
SpringApplication.run(MainClass.class, args);
}
}
My aspect class looks like this:
@Aspect
public class ConfigurationsAspect {
private static final Logger logger = Logger.getLogger(ConfigurationsAspect.class);
@Autowired
private ConnectionWrapper connection;
@Autowired
private OptionHandler optionHandler;
/**
* Closes the connection to the Server if there were an initialized connection.
*/
@After("execution(void tools.cli.MainClass.main(*))")
public void closeConnection() {
if (this.connection.isConnected()) {
logger.debug("Closing connection");
this.connection.close();
}
}
/**
* Parses the options if not parsed before.
*
* @param jp The actual point of execution.
*/
@Before("execution(* tools.runners.tasks.*.run(*))")
public void parseOptions(JoinPoint jp) {
if (!this.optionHandler.isParsed()) {
String[] args = (String[]) jp.getArgs()[0];
this.optionHandler.parseParameters(args);
}
}
}
The involved beans are described in the applicationContext.xml like (Snippet):
<bean class="tools.aspects.ConfigurationsAspect" factory-method="aspectOf"/>
<bean class="tools.cli.options.OptionHandler"/>
<bean class="tools.connection.ConnectionWrapper" />
My build.gradle looks like this (Snippet):
plugins {
id 'org.springframework.boot' version '2.1.3.RELEASE'
id 'java'
}
apply plugin: 'application'
apply plugin: 'io.spring.dependency-management'
dependencies {
compile('commons-io:commons-io:2.5')
compile('commons-cli:commons-cli:1.4')
compile('org.springframework.boot:spring-boot-starter')
compile('org.springframework:spring-oxm')
testCompile('org.springframework:spring-oxm')
compile 'org.aspectj:aspectjrt:1.9.2'
compile 'org.aspectj:aspectjweaver:1.9.2'
}
I'm getting a following error message when I don't apply the io.freefair plugin.
ERROR org.springframework.boot.SpringApplication: 858 - Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tools.aspects.ConfigurationsAspect#0' defined in class path resource [spring/applicationContext.xml]: No matching factory method found: factory method 'aspectOf()'. Check that a method with the specified name exists and that it is static.
AspectJ should create an instance of my ConfigurationsAspect and inserted the aspectOf()-method, which Spring is searching for if it had worked properly.
Leading to my Question:
Is there an opportunity to achieve the AspectJ Compile-Time (or Post-Compile-Time) Weaving without applying external dependencies?
If not then, even though I prefer Compile-Time Weaving, is there an opportunity to achieve the Load-Time Weaving without the obligation of passing in JVM arguments to run the jar correctly?
Thanks and Greetings.