DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Introduce a New API Quickly Using Spring Boot and Gradle
  • Magic of Aspects: How AOP Works in Spring
  • A Guide to Aspect-Based Sentiment Analysis With GPT and BERT
  • Adding Versatility to Java Logging Aspect

Trending

  • Scalable System Design: Core Concepts for Building Reliable Software
  • Unlocking AI Coding Assistants Part 3: Generating Diagrams, Open API Specs, And Test Data
  • Accelerating AI Inference With TensorRT
  • DGS GraphQL and Spring Boot

Working With Gradle, Spring Aspects and Compile-time Weaving

By 
Lieven Doclo user avatar
Lieven Doclo
·
Jul. 22, 13 · Interview
Likes (2)
Comment
Save
Tweet
Share
26.5K Views

Join the DZone community and get the full member experience.

Join For Free

As one of my previous posts already mentioned, I’m in the process of migrating most if not all of my projects to Gradle. I’m very pleased with the fact it’s going a lot smoother than I had anticipated.

However I came across an issue: how to get AspectJ compile-time weaving working with Gradle. My use case is quite simple: I’m using Spring’s @Configurable annotation, which either requires load-time or compile-time weaving to work correctly. Load-time weaving isn’t really an option, so compile time weaving it was. There is a plugin but it’s outdated: it doesn’t work with Gradle 1.6. If this was the case with Maven, I’d be screwed/ I would have to write my own plugin. Luckily with Gradle, it was not that difficult.

The old plugin relied on the old Gradle 0.9 DSL, so I could use that as a starting point. The instructions required me to define some new configurations and add some things to the javaCompile task. So I started out with this:

configurations {
  ajc
  aspects
}

compileJava {
  sourceCompatibility="1.6"
  targetCompatibility="1.6"

  doLast{
      ant.taskdef( resource:"org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath)
      ant.iajc(source:"1.6", target:"1.6", destDir:sourceSets.main.output.classesDir.absolutePath, maxmem:"512m", fork:"true",
          aspectPath:configurations.aspects.asPath,
            sourceRootCopyFilter:"**/.svn/*,**/*.java",classpath:configurations.compile.asPath){
          sourceroots{
              sourceSets.main.java.srcDirs.each{
                  pathelement(location:it.absolutePath)
              }
          }
      }
  }
}

dependencies {
  ajc             "org.aspectj:aspectjtools:1.6.10"
  compile         "org.aspectj:aspectjrt:1.6.10"
  aspects        "org.springframework:spring-aspects:3.2.2.RELEASE"
}

This, however, did not work. I was greeted by the following exception:

can't determine superclass of missing type org.springframework.transaction.interceptor.TransactionAspectSupport

It seems like spring-aspects contains multiple aspects, each requiring some dependencies which are required regardless whether you want to use those aspects. This, by the way, was also required when using the Maven AspectJ plugin. After some POM fishing, I found out I had to add a couple of libraries. So now we have the following dependencies:

dependencies {
  ajc         "org.aspectj:aspectjtools:1.6.10"
  compile         "org.aspectj:aspectjrt:1.6.10"
  aspects        "org.springframework:spring-aspects:3.2.2.RELEASE"
  aspects        "javax.persistence:persistence-api:1.0"
  aspects        "org.springframework:spring-tx:3.2.2.RELEASE"
  aspects        "org.springframework:spring-orm:3.2.2.RELEASE"
}

My code compiled and my aspects were weaved in! Unfortunately, it wasn’t the end of the story. My tests failed. It was missing the aspect library at runtime, as the (now weaved) classes referenced some classes that were contained in spring-aspects and I was subclassing them in my testcode. The quick solution would be to duplicate the spring-aspects dependency in the compile configuration, but that was something I didn’t like. I did however came up with a cleaner solution: I had to make sure the aspect dependencies were added to the compile configuration. A small change in the configurations section was all I needed to do.

configurations {
  ajc
  aspects
  compile {
      extendsFrom aspects
  }
}

Hurrah! I wished. Unfortunately now the dependencies I had to add to the build in order to make the weaving work were now also added to the compile configuration. I didn’t need them or used them, so I had to find a way to exclude them from the compile configuration, but still include them in the aspect weaving. The solution was simple and clean: add a new configuration and include those configuration’s dependencies in the weaving classpath. The new configiration is not added in the compile configuration, so your build is not dependent on those dependencies.

The final product looked like this:

configurations {
  ajc
  aspects
  aspectCompile
  compile {
      extendsFrom aspects
  }
}

compileJava {
  sourceCompatibility="1.6"
  targetCompatibility="1.6"

  doLast{
      ant.taskdef( resource:"org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath)
      ant.iajc(source:"1.6", target:"1.6", destDir:sourceSets.main.output.classesDir.absolutePath, maxmem:"512m", fork:"true",
          aspectPath:configurations.aspects.asPath},  sourceRootCopyFilter:"**/.svn/*,**/*.java",classpath:"${configurations.compile.asPath};${configurations.aspectCompile.asPath}"){
          sourceroots{
              sourceSets.main.java.srcDirs.each{
                  pathelement(location:it.absolutePath)
              }
          }
      }
  }
}

dependencies {
  ajc             "org.aspectj:aspectjtools:1.6.10"
  compile         "org.aspectj:aspectjrt:1.6.10"
  aspects        "org.springframework:spring-aspects:3.2.2.RELEASE"
  aspectCompile  "javax.persistence:persistence-api:1.0"
  aspectCompile  "org.springframework:spring-tx:3.2.2.RELEASE"
  aspectCompile  "org.springframework:spring-orm:3.2.2.RELEASE"
}

The entire process took me about an hour, although most of it was looking up stuff in the Gradle documentation. I’m also really impressed with the error notification of Gradle. If something goes wrong, it’s quite accurate in pinpointing the problem.

This was one of the more complex things in the builds I have, so anything else should be a breeze. One thing I really, really like about Gradle is that you can merge all build configuration of a multi-module project into a single build.gradle file. For a build with 10 modules this meant going from maintaining 11 Maven POM files to only one gradle build script. Even better: the single build.gradle file is 3 times smaller than the projects root POM! If that’s not nice, I don’t know what is.

Gradle Aspect (computer programming)

Published at DZone with permission of Lieven Doclo, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Introduce a New API Quickly Using Spring Boot and Gradle
  • Magic of Aspects: How AOP Works in Spring
  • A Guide to Aspect-Based Sentiment Analysis With GPT and BERT
  • Adding Versatility to Java Logging Aspect

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: