4

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.

Monac
  • 108
  • 9

0 Answers0