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
Please enter at least three characters to search
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

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

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

  • The Future of Java and AI: Coding in 2025
  • Navigating and Modernizing Legacy Codebases: A Developer's Guide to AI-Assisted Code Understanding
  • The Role of AI in Identity and Access Management for Organizations
  • Navigating Change Management: A Guide for Engineers

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
Oops! Something Went Wrong

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:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!