3

My goal is to get a bare bones aspectj+spring aop setup such that I can use @Configurable on one class. One additional restriction is that it needs to use load-time weaving as Lombok doesn't work with CTW.

The good news: I have it working!

The bad news: The console is flooded with [Xlint:cantFindType] errors. See results section below.

The Environment

I have a single class annotated with @Configurable. It is a class used by and instantiated by Jackson, hence the need for AOP. It's not very interesting so I won't show it here. It's just a normal class with the single annotation of Configurable, and an @Autowired bean inside.

SpringBootApplication

My Application class has the usual annotations:

@SpringBootApplication
@EnableSpringConfigured
@EnableLoadTimeWeaving
public class MyApplication {

build.gradle

My build.gradle has all the usual suspects. Sample:

configurations {
    springinstrument
}

dependencies {
    compile('org.projectlombok:lombok')

    compile('org.springframework.boot:spring-boot-starter-aop')
    compile("org.springframework.boot:spring-boot-starter-data-rest")
    compile('org.springframework.data:spring-data-rest-hal-browser')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-security')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.boot:spring-boot-devtools')
    compile('org.springframework.plugin:spring-plugin:1.2.0.RELEASE')
..snip..
    runtime('org.springframework:spring-instrument:4.+')
    springinstrument "org.springframework:spring-instrument:4.+"
    runtime configurations.springinstrument.dependencies
}

test.doFirst {
    jvmArgs "-javaagent:${configurations.springinstrument.asPath}"
}

jvm args

I am running a JUnit test with the following args (via Intellij's run config)

-ea
-javaagent:/Users/me/.gradle/caches/modules-2/files-2.1/org.springframework/spring-instrument/4.3.3.RELEASE/5db399fa5546172b9c107817b4abaae6b379bb8c/spring-instrument-4.3.3.RELEASE.jar

aop.xml

I have a src/main/resources/META-INF/aop.xml containing:

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
        <weaver options="-Xreweavable -showWeaveInfo">
        <!-- only weave classes with @Configurable interface -->
        <include within="@org.springframework.beans.factory.annotation.Configurable */>
    </weaver>
</aspectj>

However, my suspicion is that this file is not being picked up. It doesn't matter what I put in the file, the results are always the same. Even if I put random non-valid XML.

The Test

The junit test is a simple Jackson serialize-deserialize test using the @Configurable annotated class.

The test class has the annotations:

@SpringBootTest
@RunWith(SpringRunner.class)

The Results

When running a junit test via Intellij -> It Works, but..

The LTW is actual working and my test is passing when run via Intellij with the jvm args above.

However the boot time of the app is significantly longer and the log is flooded with Xlint:cantFindType errors

Example:

2016-11-07 19:28:21.944  INFO 45213 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
[AppClassLoader@18b4aac2] error can't determine implemented interfaces of missing type org.springframework.security.ldap.authentication.LdapAuthenticationProvider
when weaving type org.springframework.security.config.annotation.authentication.configurers.ldap.LdapAuthenticationProviderConfigurer
when weaving classes 
when weaving 
 [Xlint:cantFindType]
[AppClassLoader@18b4aac2] error can't determine implemented interfaces of missing type io.undertow.server.handlers.accesslog.AccessLogHandler
when weaving type org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory
when weaving classes 
when weaving 
 [Xlint:cantFindType]
[AppClassLoader@18b4aac2] error can't determine implemented interfaces of missing type io.undertow.server.handlers.accesslog.AccessLogHandler
when weaving type org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory
when weaving classes 
when weaving 
 [Xlint:cantFindType]
[AppClassLoader@18b4aac2] error can't determine implemented interfaces of missing type io.undertow.server.handlers.accesslog.AccessLogHandler
when weaving type org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory
when weaving classes 
when weaving 
 [Xlint:cantFindType]
.. many more.. all in the org.springframework.boot package

When running a test via gradle command line -> works, sort of.

When I run the test with gradle test --tests *MyTestClass, the test fails because of a NullPointerException on.. guess what, the @Autowired bean I'm expecting to be injected automatically.

I got it working with gradle test config, huzzah! I've updated the configuration above. But.. it suffers from the same problem as running it in my IDE: the Xlint:cantFindType


So the issues:

  1. The gradle configuration is wrong, so running the app via gradle fails. How do I fix the gradle config?

  2. The Xlint:cantFindType errors. Is the aop.xml not being picked up? How to resolve this?

I have yet to find a simple spring-boot+gradle+ @Configurable sample that uses aop.xml

cb4
  • 6,689
  • 7
  • 45
  • 57
Casey
  • 6,166
  • 3
  • 35
  • 42
  • Did you try using `-javaagent:aspectjweaver.jar` instead of `-javaagent:spring-instrument.jar`? – Nándor Előd Fekete Nov 07 '16 at 20:02
  • I did actually, I had it working first with aspectjweaver, and I encountered the same problem. I switched it to spring-instrument thinking that might solve it. – Casey Nov 07 '16 at 20:06

1 Answers1

7

I solved the problem, and it's rather embarrassing.

  1. It was due to the fact that the aop.xml wasn't being picked up.
  2. The file wasn't being detected because it was in a directory named META_INF/ on the class path, not META-INF/. That's a pretty important difference.

Anyways, I've updated the question with the minimal configuration needed to get @Configurable working with a modern spring-boot and gradle setup with load time weaving for Lombok support. Hopefully it will be useful for someone.

Casey
  • 6,166
  • 3
  • 35
  • 42