Skip to content

Annotation‑driven ServiceLoader automation for JVM projects

License

Notifications You must be signed in to change notification settings

EventHorizonLab/SPI-Tooling

SPI‑Tooling

Annotation‑driven ServiceLoader automation for JVM projects

Annotations Maven Central Processor Maven Central Build
License: MIT


📖 Overview

spi-tooling eliminates the boilerplate of Java’s Service Provider Interface (SPI) by generating META-INF/services entries at compile time.
Instead of manually maintaining service registration files, you annotate your implementations and let the processor handle the rest — deterministically, reproducibly, and contributor‑friendly.

This is designed for:

  • Library authors who want zero‑friction SPI onboarding for consumers.
  • Multi‑module projects where manual service file management is error‑prone.
  • Teams that value reproducible builds and automated contributor workflows.

✨ Features

  • Annotation‑driven: Mark your contracts with @ServiceContract and service implementations with @ServiceProvider(Contract:class)
  • Automatic META-INF/services generation at compile time.
  • Multi‑module aware: Handles aggregation across modules without collisions.
  • Deterministic output: Stable ordering for reproducible builds.
  • Error validation: Compile‑time checks for missing interfaces, duplicates, or misconfigurations.
  • Kotlin & Java friendly: Works seamlessly with both.
  • Gradle‑ready: Zero manual wiring for most setups.

🚀 Quick Start

1. Add the dependency

Groovy DSL:

dependencies {
    implementation "com.github.eventhorizonlab:spi-tooling-annotations:<version>"
    
    // --- BELOW ONLY REQUIRED FOR PROJECTS USING @ServiceProvider ---
    // Kotlin projects:
    kapt "com.github.eventhorizonlab:spi-tooling-processor:<version>"
    
    // Java projects:
    annotationProcessor("com.github.eventhorizonlab:spi-tooling:<version>")
}

Gradle kts:

dependencies {
    implementation("com.github.eventhorizonlab:spi-tooling-annotations:<version>")
    
    // --- BELOW ONLY REQUIRED FOR PROJECTS USING @ServiceProvider ---
    // Kotlin projects:
    kapt("com.github.eventhorizonlab:spi-tooling-processor:<version>")
    // Java projects:
    annotationProcessor("com.github.eventhorizonlab:spi-tooling-processor:<version>")
}

➡️ See Kapt for more information

2. Annotate your contract & implementation

Contract:

package com.example.myproject.spi.api
import com.github.eventhorizonlab.spi.ServiceContract

@ServiceContract
interface MyContract {
    fun doSomething()
}

Implementation:

package com.example.myproject.spi
import com.github.eventhorizonlab.spi.ServiceProvider
import com.example.myproject.spi.api.MyContract

@ServiceProvider(MyContract::class)
class MyImpl : MyContract {
    override fun doSomething() {
        println("Hello World!")
    }
}

3. Build your project

The processor generates:

META-INF/services/com.example.myproject.spi.api.MyContract

containing:

com.example.myproject.spi.MyImpl

4. Use ServiceLoader

package com.example.myproject.spi.api
import com.github.eventhorizonlab.spi.ServiceContract
import java.util.*

@ServiceContract
interface MyContract {
    fun doSomething()
}

val myContract = ServiceLoader.load(MyContract::class.java).first()
myContract.doSomething()

Architecture Diagram

 ┌─────────────────────────┐
 │  Source Code (.kt/.java)│
 │  with annotations       │
 └───────────┬─────────────┘
             │
             ▼
 ┌──────────────────────────┐
 │  SPI-Tooling Annotation  │
 │  Processor (compile-time)│
 └───────────┬──────────────┘
             │
             ▼
 ┌───────────────────────────────┐
 │  Generates META-INF/services/ │
 │  <FullyQualifiedInterfaceName>│
 └───────────────────────────────┘


Testing & Validation

spi-tooling is tested with:

  • kotest for expressive, readable test cases
  • kotlin-compile-testing for compile-time validation Run tests locally:
./gradlew kotest

Development

Clone & Build

git clone https://github.com/EventHorizonLab/SPI-Tooling.git
cd SPI-Tooling
./gradlew build

Contributing

We welcome contributions!

  • Keep builds reproducible -- no manual steps
  • Add tests for new features
  • Follow the existing Gradle/Kotlin DSL style See CONTRIBUTING.md for more details.

Publishing

This project is published to Maven Central and GitHub Packages under:

groupId: io.github.eventhorizonlab
artifactIds:
- spi-tooling-annotations
- spi-tooling-processor

Releases are automated via GitHub Actions:

  • On push/merge to main & gradle.properties updated with new version
  • Pushes a new version tag -> Publishes to Maven Central & GitHub Packages -> Creates a GitHub Release GPG signing and Sonatype credentials are securely handled in CI

License

MIT License


Why SPI-Tooling?

Manual SPI file management is:

  • Error-prone (typos, missing entries)
  • Hard to maintain in multi-module setups
  • A barrier for new contributors spi-tooling makes it automatic, safe, and reproducible -- so you can focus on building features, not maintaing service files.

About

Annotation‑driven ServiceLoader automation for JVM projects

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors 2

  •  
  •  

Languages