diff --git a/inventory-orders-service/.sdkmanrc b/inventory-orders-service/.sdkmanrc index 74c0edb..81bc6df 100644 --- a/inventory-orders-service/.sdkmanrc +++ b/inventory-orders-service/.sdkmanrc @@ -1 +1,4 @@ -java=17.0.2-open \ No newline at end of file +java=17.0.2-open + +# Optional: uncomment to use a GraalVM distribution when working with native images +# java=17.0.8-graal \ No newline at end of file diff --git a/inventory-orders-service/META-INF/MANIFEST.MF b/inventory-orders-service/META-INF/MANIFEST.MF new file mode 100644 index 0000000..a205b10 --- /dev/null +++ b/inventory-orders-service/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: io.flamingock.examples.inventory.InventoryOrdersApp + diff --git a/inventory-orders-service/README.md b/inventory-orders-service/README.md index ba0b09b..eaa56f3 100644 --- a/inventory-orders-service/README.md +++ b/inventory-orders-service/README.md @@ -67,6 +67,9 @@ This example showcases Flamingock’s ability to: - [Prerequisites](#prerequisites) - [Dependencies](#dependencies) - [How to Run this Example](#how-to-run-this-example) + - [Option 1: Run the Application (Recommended)](#option-1-run-the-application-recommended) + - [Option 2: Run Tests](#option-2-run-tests) + - [Option 3: Run with GraalVM Native Image (Optional)](#option-3-run-with-graalvm-native-image-optional) - [Proven Functionalities](#proven-functionalities) - [Implemented Changes](#implemented-changes) - [Contributing](#contributing) @@ -211,6 +214,97 @@ Run the integration tests with Testcontainers (no Docker Compose needed): ./gradlew test ``` +### Option 3: Run with GraalVM Native Image (Optional) + +If you want to showcase Flamingock running as a GraalVM native image, you can follow these **optional** steps. The regular JVM flow above still works as-is. + +For full details, see the official docs: https://docs.flamingock.io/frameworks/graalvm + +#### 1. Use a GraalVM Java distribution + +Using SDKMAN: + +```bash +sdk env install # uses .sdkmanrc in this folder +sdk use java 22.0.2-graalce # or any installed GraalVM distribution compatible with your setup +``` + +The default `.sdkmanrc` keeps Java 17, but includes a commented example GraalVM version you can enable. + +#### 2. Ensure GraalVM support dependencies are present + +This example already includes the Flamingock GraalVM integration and resource configuration: + +- `build.gradle.kts` contains: + - `implementation("io.flamingock:flamingock-graalvm:$flamingockVersion")` +- `resource-config.json` in the project root includes: + - `META-INF/flamingock/metadata.json` resources required at native-image time + +If you copy this example to your own project, make sure you add the same pieces (or follow the docs linked above). + +#### 3. Build the fat (uber) JAR + +First build the application as usual, which also creates a **fat / uber JAR** bundling all runtime dependencies and a `Main-Class` manifest entry: + +```bash +./gradlew clean build +``` + +The `jar` task in `build.gradle.kts` is configured like this: + +```kotlin +tasks.named("jar") { + manifest { + attributes["Main-Class"] = "io.flamingock.examples.inventory.InventoryOrdersApp" + } + + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + + from(sourceSets.main.get().output) + + from({ + configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) } + }) +} +``` + +This produces an executable uber JAR under `build/libs/` (for example `build/libs/inventory-orders-service-1.0-SNAPSHOT.jar`). + +> **Why this matters for GraalVM** +> +> GraalVM's `native-image -jar` mode expects a JAR that: +> - has a valid `Main-Class` manifest attribute, and +> - contains all the classes and dependencies reachable from that entry point. +> +> The fat/uber JAR configuration above ensures those requirements are met, which is essential for the native-image step to work reliably. + +#### 4. Create the native image + +From the project root, run (adjust the JAR name and output binary name if needed): + +```bash +native-image \ + --no-fallback \ + --features=io.flamingock.graalvm.RegistrationFeature \ + -H:ResourceConfigurationFiles=resource-config.json \ + -H:+ReportExceptionStackTraces \ + --initialize-at-build-time=org.slf4j.simple \ + -jar build/libs/inventory-orders-service-1.0-SNAPSHOT.jar \ + inventory-orders-service +``` + +This uses Flamingock's GraalVM feature to automatically register all required reflection metadata. + +#### 5. Run the native image + +With Docker Compose infrastructure already running (see [Option 1](#option-1-run-the-application-recommended)), start the native binary: + +```bash +./inventory-orders-service +``` + +The application will execute the same Flamingock migrations as when running on the regular JVM, but with GraalVM-native startup and footprint characteristics. + ## Troubleshooting ### Schema Registry Connection Issues diff --git a/inventory-orders-service/build.gradle.kts b/inventory-orders-service/build.gradle.kts index 2861905..5a3e2af 100644 --- a/inventory-orders-service/build.gradle.kts +++ b/inventory-orders-service/build.gradle.kts @@ -26,7 +26,7 @@ repositories { group = "io.flamingock" version = "1.0-SNAPSHOT" -val flamingockVersion = "1.0.0-beta.1" +val flamingockVersion = "1.0.0-beta.4" logger.lifecycle("Building with flamingock version: $flamingockVersion") val mongodbVersion = "5.5.1" @@ -39,6 +39,10 @@ dependencies { // Flamingock Dependencies implementation(platform("io.flamingock:flamingock-community-bom:$flamingockVersion")) implementation("io.flamingock:flamingock-community") + // Optional: enable GraalVM native image support for Flamingock + // See: https://docs.flamingock.io/frameworks/graalvm + // Uncomment + implementation("io.flamingock:flamingock-graalvm:$flamingockVersion") annotationProcessor("io.flamingock:flamingock-processor:$flamingockVersion") // MongoDB dependencies @@ -73,6 +77,20 @@ application { mainClass = "io.flamingock.examples.inventory.InventoryOrdersApp" } +tasks.named("jar") { + manifest { + attributes["Main-Class"] = "io.flamingock.examples.inventory.InventoryOrdersApp" + } + + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + + from(sourceSets.main.get().output) + + from({ + configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) } + }) +} + tasks.withType { options.compilerArgs.add("-parameters") } diff --git a/inventory-orders-service/resource-config.json b/inventory-orders-service/resource-config.json new file mode 100644 index 0000000..599fa54 --- /dev/null +++ b/inventory-orders-service/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources": { + "includes": [ + { "pattern": "META-INF/flamingock/metadata.json" } + ] + } +}