Skip to content

Commit 754fe3e

Browse files
authored
Issue 148 forward fixes JDK 25 build stage distroless WORKDIR and jdt2jar helper (#151)
* Issue #148 bump Docker build stage from JDK 24 to JDK 25 LTS * Issue #148 fix WORKDIR in distroless stage, document docker cp fallback for macOS/Colima * chore: remove accidental tmp test artifacts * Issue #148 add helper script for restricted volume mount environments, clean up README
1 parent 49c6f51 commit 754fe3e

4 files changed

Lines changed: 60 additions & 30 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ jobs:
1313
- name: Checkout
1414
uses: actions/checkout@v4
1515

16-
- name: Set up JDK 24
16+
- name: Set up JDK 25
1717
uses: actions/setup-java@v4
1818
with:
1919
distribution: oracle
20-
java-version: '24'
20+
java-version: '25'
2121
cache: 'maven'
2222

2323
- name: Build and verify

jdt2jar/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# syntax=docker/dockerfile:1
22

3-
FROM eclipse-temurin:24-jdk AS build
3+
FROM eclipse-temurin:25-jdk AS build
44
WORKDIR /build
55
COPY . .
66
RUN ["./mvnw", "-pl", "jdt2jar", "-am", "package", "-DskipTests", "-Dsurefire.failIfNoSpecifiedTests=false"]
@@ -10,6 +10,7 @@ RUN ["mkdir", "-p", "/empty-work/tmp", "/empty-app"]
1010
FROM gcr.io/distroless/base-debian13:nonroot
1111
COPY --from=build --chown=65532:65532 /empty-work /work
1212
COPY --from=build --chown=65532:65532 /empty-app /app
13+
WORKDIR /work
1314
ENV JAVA_TOOL_OPTIONS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -Djava.io.tmpdir=/work/tmp -XX:+ExitOnOutOfMemoryError"
1415
COPY --from=build /opt/jre /jre
1516
COPY --from=build /build/jdt2jar/target/jdt2jar.jar /app/jdt2jar.jar

jdt2jar/README.md

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# jdt2jar
22

3-
`jdt2jar` compiles a JTD schema into a standalone validator JAR at build time. The generated JAR runs on JDK 21+ with no JDK 24+ runtime dependency.
3+
`jdt2jar` compiles a JTD schema into a standalone validator JAR at build time. The generated JAR runs on JDK 21+ with no JDK 25+ runtime dependency.
44

55
## Use Case
66

77
This tool bridges the gap between the interpreter and codegen paths:
88

99
- **Interpreter** ([`json-java21-jtd`](../json-java21-jtd/README.md)): ideal for infrequent config parsing — simple, no build step, runs on JDK 21+.
10-
- **Codegen** ([`json-java21-jtd-codegen`](../json-java21-jtd-codegen/README.md)): ideal for repeated hot-path validation — ~9x faster, but requires JDK 24+ at runtime.
11-
- **jdt2jar**: pre-compiles schemas into validator JARs at build time (using JDK 24+), then deploys them to any JDK 21+ runtime. Best for CI/CD pipelines, distroless containers, or environments where you want JIT-optimised validators without shipping a JDK 24+ runtime.
10+
- **Codegen** ([`json-java21-jtd-codegen`](../json-java21-jtd-codegen/README.md)): ideal for repeated hot-path validation — ~9x faster, but requires JDK 25+ at runtime.
11+
- **jdt2jar**: pre-compiles schemas into validator JARs at build time (using JDK 25+), then deploys them to any JDK 21+ runtime. Best for CI/CD pipelines, distroless containers, or environments where you want JIT-optimised validators without shipping a JDK 25+ runtime.
1212

1313
> **Future note**: `java.util.json` has entered the JDK incubator (`jdk.incubator.json`). Once the API stabilises in the JDK itself, generated bytecode validators can depend directly on future JDK classes rather than this backport, making them even more efficient with zero library overhead.
1414
@@ -35,48 +35,52 @@ A minimal distroless container image is available for offline schema compilation
3535
### Pre-built Image (GitHub Container Registry)
3636

3737
```bash
38-
# Pull the latest image
3938
docker pull ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest
40-
41-
# Pull a specific release version
42-
docker pull ghcr.io/simbo1905/java.util.json.java21/jdt2jar:2026.02.05
39+
docker pull ghcr.io/simbo1905/java.util.json.java21/jdt2jar:2026.05.20
4340
```
4441

4542
### Build Locally
4643

47-
Requires Docker and JDK 24+ (for the build stage). Build from the repository root:
44+
Requires Docker and JDK 25+ (for the build stage). Build from the repository root:
4845

4946
```bash
5047
docker build -t jdt2jar -f jdt2jar/Dockerfile .
5148
```
5249

5350
### Usage
5451

52+
The container's working directory is `/work`. Mount your project directory there:
53+
54+
```bash
55+
docker run --rm -v "$(pwd):/work" jdt2jar:latest schema.jtd.json --output schema-validator.jar --main
56+
```
57+
58+
Validate a payload with the generated JAR:
59+
60+
```bash
61+
java -jar schema-validator.jar --validate payload.json
62+
```
63+
64+
Or validate inside a container:
65+
66+
```bash
67+
docker run --rm -v "$(pwd):/work" --entrypoint /jre/bin/java jdt2jar:latest -jar /work/schema-validator.jar --validate /work/payload.json
68+
```
69+
70+
### Helper Script
71+
72+
For environments where volume mounts are restricted (e.g., Colima on macOS with projects outside `~/`), use the helper script:
73+
5574
```bash
56-
# Show help
57-
docker run --rm ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest --help
58-
59-
# Compile a schema to a validator JAR (using docker cp for file I/O)
60-
cid=$(docker create --name jdt2jar-build ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest /work/person.jtd.json --output /work/person-validator.jar --main)
61-
docker cp person.jtd.json jdt2jar-build:/work/person.jtd.json
62-
docker start -a jdt2jar-build
63-
docker cp jdt2jar-build:/work/person-validator.jar .
64-
docker rm jdt2jar-build
65-
66-
# Validate a payload with the generated JAR
67-
java -jar person-validator.jar --validate payload.json
68-
# Or validate inside a container
69-
cid=$(docker create --name jdt2jar-validate --entrypoint /jre/bin/java ghcr.io/simbo1905/java.util.json.java21/jdt2jar:latest -jar /work/person-validator.jar --validate /work/payload.json)
70-
docker cp person-validator.jar jdt2jar-validate:/work/person-validator.jar
71-
docker cp payload.json jdt2jar-validate:/work/payload.json
72-
docker start -a jdt2jar-validate
73-
docker rm jdt2jar-validate
75+
./scripts/jdt2jar.sh schema.jtd.json --output schema-validator.jar --main
7476
```
7577

78+
The script syncs source to `~/tmp/jdt2jar-work`, runs the container, and syncs output back.
79+
7680
### Image Properties
7781

7882
- **Base**: `gcr.io/distroless/base-debian13:nonroot`
79-
- **Runtime**: jlink-minimized JDK 24 (~40 MB)
83+
- **Runtime**: jlink-minimized JDK 25 LTS (~40 MB)
8084
- **Total size**: ~111 MB disk / ~31 MB content
8185
- **User**: `nonroot` (uid 65532)
8286
- **Shell**: none (distroless)

scripts/jdt2jar.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
# jdt2jar helper script for environments where volume mounts are restricted
3+
# (e.g., Colima on macOS with projects outside ~/).
4+
#
5+
# Usage:
6+
# ./scripts/jdt2jar.sh <schema.jtd.json> [options...]
7+
#
8+
# Example:
9+
# ./scripts/jdt2jar.sh .tmp/test.jtd.json --output .tmp/test.jar --main
10+
11+
set -euo pipefail
12+
13+
WORK_DIR="$HOME/tmp/jdt2jar-work"
14+
IMAGE="${JDT2JAR_IMAGE:-jdt2jar:latest}"
15+
16+
mkdir -p "$WORK_DIR"
17+
18+
# Sync source (respecting .gitignore)
19+
rsync -a --filter=':- .gitignore' --exclude='.git/' . "$WORK_DIR/"
20+
21+
# Run jdt2jar in container
22+
docker run --rm -v "$WORK_DIR:/work" "$IMAGE" "$@"
23+
24+
# Sync output back (any new .jar or .java files in the work dir)
25+
rsync -a --include='*.jar' --include='*.java' --exclude='*' "$WORK_DIR/" ./

0 commit comments

Comments
 (0)