DEV Community

Cover image for How We Engineered a Zero-Boilerplate Composite Build Architecture for Enterprise Gradle Plugins
Yannick Ebongue
Yannick Ebongue

Posted on

How We Engineered a Zero-Boilerplate Composite Build Architecture for Enterprise Gradle Plugins

The Monolithic Plugin Trap

When building enterprise Gradle plugins that handle deep bytecode tasks (like our JPA linter suite, JPersist), developers often fall into the classpath contamination trap. They bundle the core Java logic, framework dependencies (like Hibernate 5/6, EclipseLink, ANTLR4), and the Gradle API into a single monolithic project.

This creates massive friction for teams trying to scale:

  1. IDE Slowdowns: The integrated development environment struggles to separate compiler scopes, leading to indexing fatigue.
  2. Testing Nightmares: Gradle TestKit functional tests can leak runner classloaders and cause file-locking anomalies.
  3. Barriers to Entry: Outside contributors get intimidated by a complex, tightly-coupled dependency tree.

To solve this permanently, we recently underwent a massive structural migration for our v1.6.0 release track, transforming JPersist into a fully decoupled Symmetric Composite Build.


The Blueprint: Dual Isolated includeBuild Structures

Instead of using standard nested subprojects that leak compilation classpaths, we split the repository into two entirely independent execution containers right at the root directory level:

jpersist/persistence
├── settings.gradle        <-- The Conductor (Combines everything)
├── libraries/             <-- Isolated Build (Pure Java SPI Engines)
│   ├── build.gradle
│   └── lint-persistence-api/
└── plugins/               <-- Isolated Build (Gradle Plugin Wrappers)
    ├── build.gradle
    └── jakarta-persistence-gradle-plugin/
Enter fullscreen mode Exit fullscreen mode

In the root settings.gradle, we treat them as standalone environments using Gradle's includeBuild directive. This connects them as a unified ecosystem without letting their classpaths collide:

rootProject.name = 'jpersist'

// Include the decoupled core Java logic libraries
includeBuild('libraries')

// Include the isolated Gradle plugin definitions 
includeBuild('plugins')
Enter fullscreen mode Exit fullscreen mode

Why This Composite Setup is a Developer Superpower

1. Absolute Compile-Time Classpath Separation

Our Java libraries inside libraries/ compile against native Hibernate 6 strings natively without knowing anything about Gradle or plugin lifecycles. Conversely, the plugin wrappers inside plugins/ pull those libraries down via standard coordinate notation strings:

dependencies {
    implementation 'io.github.jpersist.lint:lint-persistence-api:2.0.0'
}
Enter fullscreen mode Exit fullscreen mode

During local testing, Gradle's composite build engine automatically intercepts these string coordinates and substitutes them with local project references seamlessly, eliminating manual local maven publishing steps completely.

2. Flawless Gradle TestKit Sandbox Testing

When running functional integration tests via TestKit, Gradle forks a separate JVM daemon. In standard layouts, this daemon can lock file paths or leak dependencies. With the composite build layout, plugins/ runs tests in an isolated sandbox, pulling pristine library binaries on-the-fly without colliding with the root build caching variables.


🌟 We're Open for Contributors! (Come Hack with Us)

With this pristine infrastructure locked down, we are officially opening JPersist to public contributions as we kick off the v1.7.0 - Performance & Multi-Tenancy tracks!

Thanks to the composite build separation, onboarding is incredibly easy. You just need JDK 17, and you can compile and verify the whole project immediately:

./gradlew -p plugins functionalTest
Enter fullscreen mode Exit fullscreen mode

We have just logged our very first good first issue tickets on our public roadmap project board:

  • Ticket #68: [FEAT] Global modelgenProcessor Configuration.
  • Ticket #69: [FEAT] Isolated weavingClasspath Pipeline.

If you love advanced build systems engineering, bytecode scanning via ASM, or messing with ANTLR4 parsers, we would love to review your Pull Requests!

⭐ Explore the Roadmap & Grab an Issue: https://github.com/orgs/jpersist/projects

Top comments (0)