Embedded packaging configuration in JAR (META-INF)
- Dominant language
- Rust
- Stars
- 181
- Forks
- 11
- PR merge metrics
- No merged PRs in 30d
Description
## Problem
Libraries that require specific Java modules at runtime have no way to declare this requirement. When a user packages an application that depends on such a library, jdeps may fail to detect the needed modules (due to reflection/dynamic loading), causing runtime failures. The burden falls entirely on the end user to discover and configure the correct modules.
## Inspiration
GraalVM's native-image supports [build configuration embedded in JAR files](https://www.graalvm.org/latest/reference-manual/native-image/overview/BuildConfiguration/) via `META-INF/native-image/`. Libraries ship their reflection/resource/JNI configuration inside the JAR, and the native-image builder automatically discovers and merges all configurations from the classpath.
This means library authors solve the configuration problem once, and all users benefit automatically. Example:
```
my-library.jar
└── META-INF/
└── native-image/
└── com.example/my-library/
├── native-image.properties
├── reflect-config.json
└── resource-config.json
```
## Expected Outcome
jbundle should support a `META-INF/jbundle/` directory convention inside JARs:
### Library-Side Configuration
A library author adds to their JAR:
```
META-INF/jbundle/{group-id}/{artifact-id}/jbundle.edn
```
Example content:
```edn
{:required-modules ["java.sql" "java.naming"]
:min-java-version 17
:resources-needed ["db/migrations/*.sql"]
:shrink-exclude ["com/example/generated/**"]}
```
### jbundle Behavior
1. During the build, scan all JARs on the classpath (inside the uberjar) for `META-INF/jbundle/` entries
2. Merge all discovered configurations:
- Union of `:required-modules` → feeds into jlink
- Maximum of `:min-java-version` → validates JDK selection
- Union of `:resources-needed` → protects from shrink removal
- Union of `:shrink-exclude` → protects from aggressive shrink
3. User's `.jbundle.edn` and CLI flags override/extend merged config
### Precedence (lowest to highest)
1. `META-INF/jbundle/` from dependencies (auto-discovered)
2. `.jbundle.edn` in project root (#9)
3. CLI flags
### Benefits
- **Library authors** declare requirements once, saving every user from debugging
- **Application developers** get correct module detection without manual configuration
- **Ecosystem**: as adoption grows, the "jdeps misses reflection" problem diminishes
- **Backwards compatible**: JARs with `META-INF/jbundle/` work fine with other tools (extra files are ignored)
## Real-World Examples
Libraries that would benefit from declaring their requirements:
- **next.jdbc / clojure.java.jdbc**: needs `java.sql`, `java.naming`
- **ring-jetty / http-kit**: needs `jdk.crypto.ec` for HTTPS
- **clojure.data.xml**: needs `java.xml`
- **buddy-sign (JWT)**: needs `java.security.jgss`, `jdk.crypto.ec`
- **amazonica / cognitect.aws**: needs `java.xml`, `java.naming`, `java.management`
## Ecosystem Adoption Path
1. jbundle documents the `META-INF/jbundle/` convention
2. jbundle ships a built-in "known modules" database for popular libraries (temporary bridge)
3. Library maintainers add the metadata to their JARs over time
4. Built-in database becomes less necessary as ecosystem adopts the convention
Contributor guide
Research direction
Start by reading the proposed META-INF/jbundle/{group-id}/{artifact-id}/jbundle.edn format alongside the project-root .jbundle.edn and CLI precedence described here. Trace the build step that feeds jlink, then define how dependency JAR entries are discovered and merged. Done means all four configuration categories are merged with the stated precedence and the JDK version is validated.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, rust
- Domain
- build-system, devtools
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100