diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 469f418..0594f82 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -40,12 +40,22 @@ jobs:
java-version: ${{ matrix.java }}
cache: maven
+ - name: Set up Gradle
+ if: matrix.java == '17'
+ uses: gradle/actions/setup-gradle@v6
+ with:
+ gradle-version: "9.5.1"
+
- run: ./mvnw --batch-mode --no-transfer-progress verify
- name: Verify clean BOM consumers
if: matrix.java == '17'
run: ./scripts/verify-consumer.sh
+ - name: Verify clean Gradle BOM consumers
+ if: matrix.java == '17'
+ run: ./scripts/verify-gradle-consumer.sh
+
- name: Verify Spring Framework 7 compatibility
if: matrix.java == '17'
run: ./mvnw --batch-mode --no-transfer-progress -pl aep-spring-webmvc -am -Pspring7 verify
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..a14d811
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,199 @@
+name: Release
+
+on:
+ workflow_dispatch:
+
+concurrency:
+ group: aep-java-release
+ cancel-in-progress: false
+
+permissions:
+ attestations: write
+ contents: write
+ id-token: write
+
+jobs:
+ release:
+ if: github.repository == 'aep-foundation/aep-java'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v7
+ with:
+ fetch-depth: 0
+
+ - name: Validate release
+ id: release
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then
+ echo "Releases must run from main." >&2
+ exit 1
+ fi
+ version=$(./mvnw --batch-mode --no-transfer-progress help:evaluate -Dexpression=project.version -DforceStdout -q)
+ if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+ echo "The project version must be a stable semantic version such as 0.1.0." >&2
+ exit 1
+ fi
+ tag="v$version"
+ if gh release view "$tag" >/dev/null 2>&1; then
+ echo "Release $tag already exists." >&2
+ exit 1
+ fi
+ if git ls-remote --exit-code --tags origin "refs/tags/$tag" >/dev/null 2>&1; then
+ tag_commit=$(git rev-list -n 1 "$tag")
+ if [[ "$tag_commit" != "$GITHUB_SHA" ]]; then
+ echo "Tag $tag does not identify the selected main commit." >&2
+ exit 1
+ fi
+ fi
+ echo "tag=$tag" >> "$GITHUB_OUTPUT"
+ echo "version=$version" >> "$GITHUB_OUTPUT"
+ artifact="https://repo1.maven.org/maven2/foundation/aep/aep-core/$version/aep-core-$version.pom"
+ if curl --fail --silent --show-error --head "$artifact" >/dev/null; then
+ echo "published=true" >> "$GITHUB_OUTPUT"
+ else
+ echo "published=false" >> "$GITHUB_OUTPUT"
+ fi
+
+ - name: Check out AEP specifications
+ uses: actions/checkout@v7
+ with:
+ repository: aep-foundation/aep-specs
+ path: .conformance/aep-specs
+
+ - name: Check out Node.js reference implementation
+ uses: actions/checkout@v7
+ with:
+ repository: aep-foundation/aep-node
+ path: .conformance/aep-node
+
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: "3.3"
+ bundler-cache: true
+ working-directory: .conformance/aep-specs/ietf
+
+ - uses: actions/setup-java@v6
+ with:
+ distribution: temurin
+ java-version: "17"
+ cache: maven
+ server-id: central
+ server-username-env-var: CENTRAL_USERNAME
+ server-password-env-var: CENTRAL_PASSWORD
+
+ - name: Set up Gradle
+ uses: gradle/actions/setup-gradle@v6
+ with:
+ gradle-version: "9.5.1"
+
+ - name: Set up pnpm
+ uses: pnpm/action-setup@v6
+ with:
+ version: 11.1.3
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v7
+ with:
+ node-version: 24
+
+ - name: Install Node.js reference implementation
+ run: pnpm --dir .conformance/aep-node install --frozen-lockfile
+
+ - name: Verify release
+ run: ./mvnw --batch-mode --no-transfer-progress verify
+
+ - name: Verify Spring Framework 7 compatibility
+ run: ./mvnw --batch-mode --no-transfer-progress -pl aep-spring-webmvc -am -Pspring7 verify
+
+ - name: Run shared conformance harness
+ run: ./scripts/run-conformance.sh
+ env:
+ AEP_SPECS_DIR: .conformance/aep-specs
+
+ - name: Run Node.js interoperability
+ run: ./scripts/run-node-interoperability.sh
+ env:
+ AEP_NODE_DIR: .conformance/aep-node
+
+ - name: Verify clean Maven BOM consumers
+ run: ./scripts/verify-consumer.sh
+
+ - name: Verify clean Gradle BOM consumers
+ run: ./scripts/verify-gradle-consumer.sh
+
+ - name: Inspect release artifacts
+ run: ./scripts/verify-release-artifacts.sh
+
+ - name: Publish Maven artifacts
+ if: steps.release.outputs.published != 'true'
+ run: ./mvnw --batch-mode --no-transfer-progress -Prelease -Dgpg.signer=bc deploy
+ env:
+ CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }}
+ CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
+ MAVEN_GPG_KEY: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
+ MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
+
+ - name: Attest Maven artifacts
+ uses: actions/attest-build-provenance@v4
+ with:
+ subject-path: |
+ aep-core/target/aep-core-${{ steps.release.outputs.version }}*.jar
+ aep-json-jackson2/target/aep-json-jackson2-${{ steps.release.outputs.version }}*.jar
+ aep-json-jackson3/target/aep-json-jackson3-${{ steps.release.outputs.version }}*.jar
+ aep-agent/target/aep-agent-${{ steps.release.outputs.version }}*.jar
+ aep-service/target/aep-service-${{ steps.release.outputs.version }}*.jar
+ aep-httpserver/target/aep-httpserver-${{ steps.release.outputs.version }}*.jar
+ aep-servlet/target/aep-servlet-${{ steps.release.outputs.version }}*.jar
+ aep-spring-webmvc/target/aep-spring-webmvc-${{ steps.release.outputs.version }}*.jar
+ aep-platform/target/aep-platform-${{ steps.release.outputs.version }}*.jar
+
+ - name: Wait for Maven Central availability
+ env:
+ VERSION: ${{ steps.release.outputs.version }}
+ run: |
+ artifact="https://repo1.maven.org/maven2/foundation/aep/aep-core/$VERSION/aep-core-$VERSION.pom"
+ for attempt in {1..60}; do
+ if curl --fail --silent --show-error --head "$artifact" >/dev/null; then
+ exit 0
+ fi
+ sleep 10
+ done
+ echo "Maven Central did not expose $artifact within 10 minutes." >&2
+ exit 1
+
+ - name: Verify Maven Central consumer
+ run: ./scripts/verify-consumer.sh
+ env:
+ AEP_CONSUMER_SOURCE: central
+
+ - name: Verify Maven Central Gradle consumer
+ run: ./scripts/verify-gradle-consumer.sh
+ env:
+ AEP_CONSUMER_SOURCE: central
+
+ - name: Create release tag
+ env:
+ TAG: ${{ steps.release.outputs.tag }}
+ run: |
+ if git rev-parse --verify "refs/tags/$TAG" >/dev/null 2>&1; then
+ exit 0
+ fi
+ git config user.name "github-actions[bot]"
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
+ git tag --annotate "$TAG" --message "AEP Java $TAG" "$GITHUB_SHA"
+ git push origin "$TAG"
+
+ - name: Publish GitHub release
+ run: >-
+ gh release create "${{ steps.release.outputs.tag }}"
+ .conformance/reports/agent.json#aep-java-agent-conformance.json
+ .conformance/reports/service.json#aep-java-service-conformance.json
+ .conformance/reports/platform.json#aep-java-platform-conformance.json
+ .interop/reports/aep-java-node-interoperability.json#aep-java-node-interoperability.json
+ --generate-notes
+ --title "AEP Java ${{ steps.release.outputs.tag }}"
+ --verify-tag
+ env:
+ GH_TOKEN: ${{ github.token }}
diff --git a/.gitignore b/.gitignore
index 330b829..2cd5b9a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
.DS_Store
+.gradle/
.conformance/
.interop/
.idea/
@@ -8,4 +9,5 @@
.vscode/
target/
**/target/
+build/
*.iml
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index 934be9f..f336ba0 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -3,6 +3,7 @@
## Requirements
- Java 17 or newer.
+- Gradle 9.5.1 for the Gradle BOM consumer check.
- No system Maven installation; use the checked-in Maven Wrapper.
## Verification
@@ -12,13 +13,15 @@ Run the complete repository gate before merging:
```sh
./mvnw verify
./scripts/verify-consumer.sh
+./scripts/verify-gradle-consumer.sh
```
The Maven gate compiles all modules, runs tests, enforces dependency convergence and formatting,
and runs Checkstyle, PMD, copy-paste detection, SpotBugs, and JaCoCo reporting. The consumer check
installs the reactor into an isolated temporary repository and proves that a project can import
`aep-bom`, omit versions from its AEP module dependencies, and execute the public JSON API with
-either Jackson 2 or Jackson 3.
+either Jackson 2 or Jackson 3. The Gradle check proves the same combinations through Gradle's
+platform support.
Format Java sources with:
@@ -54,3 +57,32 @@ the other official SDKs as implementation evidence after confirming the specific
All public modules use one lockstep semantic version. `aep-bom` exposes those compatible module
versions to Maven and Gradle consumers without requiring them to inherit the reactor parent.
Examples and conformance tooling remain repository-only modules.
+
+## Releases
+
+The manual `Release` workflow publishes these artifacts to Maven Central:
+
+- `aep-java` parent POM and `aep-bom`;
+- `aep-core`, `aep-json-jackson2`, and `aep-json-jackson3`;
+- `aep-agent`, `aep-service`, and `aep-platform`;
+- `aep-httpserver`, `aep-servlet`, and `aep-spring-webmvc`.
+
+The `examples` and `aep-conformance` modules are excluded from publication. A release requires a
+stable semantic version on `main` and these repository Actions secrets:
+
+- `CENTRAL_USERNAME`
+- `CENTRAL_PASSWORD`
+- `MAVEN_GPG_PRIVATE_KEY`
+- `MAVEN_GPG_PASSPHRASE`
+
+Before publishing, the workflow runs the repository gates, Spring Framework 7 verification, shared
+conformance, Node.js interoperability, Maven and Gradle BOM consumers, and release artifact
+inspection. It publishes and attests the signed artifacts, waits for Maven Central, verifies fresh
+Maven and Gradle consumers against Central, creates the matching `vX.Y.Z` tag, and publishes the
+GitHub release with its conformance and interoperability reports.
+
+Inspect the release profile locally without uploading anything:
+
+```sh
+./scripts/verify-release-artifacts.sh
+```
diff --git a/README.md b/README.md
index 8d1e3a4..fd62de2 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
# Agent Enrollment Protocol for Java
[](https://github.com/aep-foundation/aep-java/actions/workflows/ci.yml)
+[](https://central.sonatype.com/namespace/foundation.aep)
[](https://openjdk.org/)
[](./LICENSE)
diff --git a/aep-agent/pom.xml b/aep-agent/pom.xml
index 43b09ae..e148d13 100644
--- a/aep-agent/pom.xml
+++ b/aep-agent/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
aep-agent
diff --git a/aep-bom/pom.xml b/aep-bom/pom.xml
index 762ba70..cfc5867 100644
--- a/aep-bom/pom.xml
+++ b/aep-bom/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
aep-bom
diff --git a/aep-core/pom.xml b/aep-core/pom.xml
index f5a3d98..0e2e33f 100644
--- a/aep-core/pom.xml
+++ b/aep-core/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
aep-core
diff --git a/aep-httpserver/pom.xml b/aep-httpserver/pom.xml
index b3221ad..406548f 100644
--- a/aep-httpserver/pom.xml
+++ b/aep-httpserver/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
aep-httpserver
diff --git a/aep-json-jackson2/pom.xml b/aep-json-jackson2/pom.xml
index 3b62f3c..183195d 100644
--- a/aep-json-jackson2/pom.xml
+++ b/aep-json-jackson2/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
aep-json-jackson2
diff --git a/aep-json-jackson3/pom.xml b/aep-json-jackson3/pom.xml
index 906e8e0..2fc7208 100644
--- a/aep-json-jackson3/pom.xml
+++ b/aep-json-jackson3/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
aep-json-jackson3
diff --git a/aep-platform/pom.xml b/aep-platform/pom.xml
index 19d61ab..ac58f40 100644
--- a/aep-platform/pom.xml
+++ b/aep-platform/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
aep-platform
diff --git a/aep-service/pom.xml b/aep-service/pom.xml
index 09c64fa..e6f8eb2 100644
--- a/aep-service/pom.xml
+++ b/aep-service/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
aep-service
diff --git a/aep-servlet/pom.xml b/aep-servlet/pom.xml
index e965fc2..3f83f37 100644
--- a/aep-servlet/pom.xml
+++ b/aep-servlet/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
aep-servlet
diff --git a/aep-spring-webmvc/pom.xml b/aep-spring-webmvc/pom.xml
index e92f1db..6e3f75c 100644
--- a/aep-spring-webmvc/pom.xml
+++ b/aep-spring-webmvc/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
aep-spring-webmvc
diff --git a/examples/pom.xml b/examples/pom.xml
index b313ef3..7cebe0e 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
aep-examples
diff --git a/pom.xml b/pom.xml
index 081e93f..b95a277 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
pom
Agent Enrollment Protocol for Java
@@ -56,6 +56,7 @@
17
UTF-8
UTF-8
+ false
6.1.3
3.0
@@ -73,11 +74,15 @@
3.6.3
2.97.0
+ 0.11.0
3.6.0
3.15.0
3.6.3
+ 3.2.8
3.5.1
+ 3.12.0
3.28.0
+ 3.4.0
3.5.6
4.10.4.0
3.10.1
@@ -258,4 +263,68 @@
+
+
+
+ release
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ ${maven-source-plugin.version}
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ ${maven-javadoc-plugin.version}
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ ${maven-gpg-plugin.version}
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+ org.sonatype.central
+ central-publishing-maven-plugin
+ ${central-publishing-maven-plugin.version}
+ true
+
+ true
+ AEP Java ${project.version}
+ aep-conformance,aep-examples
+ central
+ ${central.skipPublishing}
+ published
+
+
+
+
+
+
diff --git a/scripts/install-consumer-artifacts.sh b/scripts/install-consumer-artifacts.sh
new file mode 100755
index 0000000..299e1fd
--- /dev/null
+++ b/scripts/install-consumer-artifacts.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+set -eu
+
+if [ "$#" -ne 2 ]; then
+ echo "Usage: $0 REPOSITORY VERSION" >&2
+ exit 2
+fi
+
+root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
+repository=$1
+version=$2
+
+"$root/mvnw" --batch-mode --no-transfer-progress \
+ --file "$root/pom.xml" \
+ -DskipTests \
+ package
+
+install_artifact() {
+ file=$1
+ pom=$2
+ "$root/mvnw" --batch-mode --no-transfer-progress \
+ org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file \
+ -Dfile="$file" \
+ -DpomFile="$pom" \
+ -DlocalRepositoryPath="$repository"
+}
+
+install_artifact "$root/pom.xml" "$root/pom.xml"
+install_artifact "$root/aep-bom/pom.xml" "$root/aep-bom/pom.xml"
+for artifact in aep-core aep-json-jackson2 aep-json-jackson3 aep-agent aep-service aep-httpserver aep-servlet aep-spring-webmvc aep-platform; do
+ install_artifact \
+ "$root/$artifact/target/$artifact-$version.jar" \
+ "$root/$artifact/pom.xml"
+done
diff --git a/scripts/verify-consumer.sh b/scripts/verify-consumer.sh
index 8c3782d..bf8b93a 100755
--- a/scripts/verify-consumer.sh
+++ b/scripts/verify-consumer.sh
@@ -14,30 +14,16 @@ version=$(
-q
)
-if [ "${AEP_CONSUMER_SOURCE:-local}" = "local" ]; then
- "$root/mvnw" --batch-mode --no-transfer-progress \
- --file "$root/pom.xml" \
- -DskipTests \
- package
-
- install_artifact() {
- file=$1
- pom=$2
- "$root/mvnw" --batch-mode --no-transfer-progress \
- org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file \
- -Dfile="$file" \
- -DpomFile="$pom" \
- -DlocalRepositoryPath="$repository"
- }
-
- install_artifact "$root/pom.xml" "$root/pom.xml"
- install_artifact "$root/aep-bom/pom.xml" "$root/aep-bom/pom.xml"
- for artifact in aep-core aep-json-jackson2 aep-json-jackson3 aep-agent aep-service aep-httpserver aep-servlet aep-spring-webmvc aep-platform; do
- install_artifact \
- "$root/$artifact/target/$artifact-$version.jar" \
- "$root/$artifact/pom.xml"
- done
-fi
+case "${AEP_CONSUMER_SOURCE:-local}" in
+ local)
+ "$root/scripts/install-consumer-artifacts.sh" "$repository" "$version"
+ ;;
+ central) ;;
+ *)
+ echo "AEP_CONSUMER_SOURCE must be local or central." >&2
+ exit 2
+ ;;
+esac
verify_consumer() {
"$root/mvnw" --batch-mode --no-transfer-progress \
diff --git a/scripts/verify-gradle-consumer.sh b/scripts/verify-gradle-consumer.sh
new file mode 100755
index 0000000..0111c46
--- /dev/null
+++ b/scripts/verify-gradle-consumer.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+set -eu
+
+root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
+repository=$(mktemp -d)
+gradle_home=$(mktemp -d)
+trap 'rm -rf "$repository" "$gradle_home"' EXIT INT TERM
+
+version=$(
+ "$root/mvnw" --batch-mode --no-transfer-progress \
+ --file "$root/pom.xml" \
+ help:evaluate \
+ -Dexpression=project.version \
+ -DforceStdout \
+ -q
+)
+
+case "${AEP_CONSUMER_SOURCE:-local}" in
+ local)
+ "$root/scripts/install-consumer-artifacts.sh" "$repository" "$version"
+ ;;
+ central) ;;
+ *)
+ echo "AEP_CONSUMER_SOURCE must be local or central." >&2
+ exit 2
+ ;;
+esac
+
+verify_consumer() {
+ if [ "${AEP_CONSUMER_SOURCE:-local}" = "local" ]; then
+ GRADLE_USER_HOME="$gradle_home" gradle \
+ --no-daemon \
+ --console=plain \
+ --project-dir "$root/testdata/consumer-gradle" \
+ -PaepVersion="$version" \
+ -PaepRepository="$repository" \
+ "$@" \
+ verifyConsumer
+ else
+ GRADLE_USER_HOME="$gradle_home" gradle \
+ --no-daemon \
+ --console=plain \
+ --project-dir "$root/testdata/consumer-gradle" \
+ -PaepVersion="$version" \
+ "$@" \
+ verifyConsumer
+ fi
+}
+
+verify_consumer
+verify_consumer -PspringGeneration=7
diff --git a/scripts/verify-release-artifacts.sh b/scripts/verify-release-artifacts.sh
new file mode 100755
index 0000000..df240ca
--- /dev/null
+++ b/scripts/verify-release-artifacts.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+set -eu
+
+root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
+settings=$(mktemp)
+trap 'rm -f "$settings"' EXIT INT TERM
+printf '%s\n' \
+ '' \
+ ' ' \
+ ' ' \
+ ' central' \
+ ' dry-run' \
+ ' dry-run' \
+ ' ' \
+ ' ' \
+ '' \
+ > "$settings"
+version=$(
+ "$root/mvnw" --batch-mode --no-transfer-progress \
+ --file "$root/pom.xml" \
+ help:evaluate \
+ -Dexpression=project.version \
+ -DforceStdout \
+ -q
+)
+
+case "$version" in
+ *-SNAPSHOT)
+ echo "Release verification requires a stable project version." >&2
+ exit 1
+ ;;
+esac
+
+"$root/mvnw" --batch-mode --no-transfer-progress \
+ --file "$root/pom.xml" \
+ --settings "$settings" \
+ -Prelease \
+ -Dgpg.skip=true \
+ -Dcentral.skipPublishing=true \
+ clean deploy
+
+for artifact in aep-core aep-json-jackson2 aep-json-jackson3 aep-agent aep-service aep-httpserver aep-servlet aep-spring-webmvc aep-platform; do
+ for classifier in "" -sources -javadoc; do
+ file="$root/$artifact/target/$artifact-$version$classifier.jar"
+ if [ ! -s "$file" ]; then
+ echo "Missing release artifact: $file" >&2
+ exit 1
+ fi
+ done
+done
+
+if [ ! -s "$root/aep-bom/pom.xml" ]; then
+ echo "Missing aep-bom POM." >&2
+ exit 1
+fi
+
+for artifact in aep-core aep-json-jackson2 aep-json-jackson3 aep-agent aep-service aep-httpserver aep-servlet aep-spring-webmvc aep-platform; do
+ if ! grep -q "$artifact" "$root/aep-bom/pom.xml"; then
+ echo "aep-bom does not manage $artifact." >&2
+ exit 1
+ fi
+done
diff --git a/testdata/consumer-gradle/build.gradle.kts b/testdata/consumer-gradle/build.gradle.kts
new file mode 100644
index 0000000..e0750a8
--- /dev/null
+++ b/testdata/consumer-gradle/build.gradle.kts
@@ -0,0 +1,54 @@
+plugins {
+ java
+}
+
+val aepVersion = providers.gradleProperty("aepVersion").getOrElse("0.1.0")
+val springGeneration = providers.gradleProperty("springGeneration").getOrElse("6")
+
+repositories {
+ providers.gradleProperty("aepRepository").orNull?.let {
+ maven {
+ url = uri(it)
+ }
+ }
+ mavenCentral()
+}
+
+dependencies {
+ implementation(platform("foundation.aep:aep-bom:$aepVersion"))
+ implementation("foundation.aep:aep-agent")
+ implementation("foundation.aep:aep-service")
+ implementation("foundation.aep:aep-platform")
+ implementation("foundation.aep:aep-httpserver")
+ implementation("foundation.aep:aep-servlet")
+ implementation("foundation.aep:aep-spring-webmvc")
+
+ if (springGeneration == "7") {
+ implementation("foundation.aep:aep-json-jackson3")
+ implementation("jakarta.servlet:jakarta.servlet-api:6.1.0")
+ implementation("org.springframework:spring-webmvc:7.0.9")
+ } else {
+ implementation("foundation.aep:aep-json-jackson2")
+ implementation("jakarta.servlet:jakarta.servlet-api:6.0.0")
+ implementation("org.springframework:spring-webmvc:6.2.19")
+ }
+}
+
+java {
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(17)
+ }
+}
+
+sourceSets {
+ main {
+ java {
+ srcDir("../consumer/src/main/java")
+ }
+ }
+}
+
+tasks.register("verifyConsumer") {
+ classpath = sourceSets.main.get().runtimeClasspath
+ mainClass = "foundation.aep.example.Consumer"
+}
diff --git a/testdata/consumer-gradle/settings.gradle.kts b/testdata/consumer-gradle/settings.gradle.kts
new file mode 100644
index 0000000..7f967ca
--- /dev/null
+++ b/testdata/consumer-gradle/settings.gradle.kts
@@ -0,0 +1 @@
+rootProject.name = "aep-java-consumer"
diff --git a/testdata/consumer/pom.xml b/testdata/consumer/pom.xml
index b5a2e4a..7d7a9d0 100644
--- a/testdata/consumer/pom.xml
+++ b/testdata/consumer/pom.xml
@@ -9,7 +9,7 @@
1.0.0
- 0.1.0-SNAPSHOT
+ 0.1.0
17
UTF-8
6.0.0
diff --git a/tools/aep-conformance/pom.xml b/tools/aep-conformance/pom.xml
index ca646d7..76fa539 100644
--- a/tools/aep-conformance/pom.xml
+++ b/tools/aep-conformance/pom.xml
@@ -7,7 +7,7 @@
foundation.aep
aep-java
- 0.1.0-SNAPSHOT
+ 0.1.0
../../pom.xml