diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index d8cbfc6..ca36b67 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -11,7 +11,7 @@ jobs: strategy: matrix: - java-version: [ 17 ] + java-version: [ 17, 19 ] steps: - name: Checkout source repository @@ -20,7 +20,7 @@ jobs: fetch-depth: 0 - name: Set up JDK ${{ matrix.java-version }} - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: ${{ matrix.java-version }} @@ -28,20 +28,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Cache Gradle packages - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ matrix.java-version }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle-${{ matrix.java-version }}- - - name: Test with Gradle - run: ./gradlew build check --stacktrace - - - name: Cleanup Gradle Cache - run: | - rm -f ~/.gradle/caches/modules-2/modules-2.lock - rm -f ~/.gradle/caches/modules-2/gc.properties \ No newline at end of file + uses: gradle/gradle-build-action@v2 + with: + arguments: build check --stacktrace \ No newline at end of file diff --git a/README.md b/README.md index bbe260e..bb2039a 100644 --- a/README.md +++ b/README.md @@ -92,18 +92,23 @@ GraalVM supports creating a single Ahead-Of-Time [native executable](https://www.graalvm.org/native-image/) from your java bytecode. -Once you have at least GraalVM 22.3.1 Java 19 installed, you can generate the -UberJar as above, then create your native binary as such: +Once you have at least GraalVM 22.3.1 Java 17 installed, you can generate the native binary with: ```bash -native-image --no-fallback --enable-preview -jar app/build/libs/hello-uber-1.0.jar +./gradlew nativeCompile ``` -You'll end up with a `hello-uber-1.0` file that can be executed directly without +You'll end up with a `hello-1.0` file that can be executed directly without the need of a JVM: ```bash -./hello-uber-1.0 +./app/build/native/nativeCompile/hello-1.0 +``` + +Alternatively, you can run the native executable directly with: + +```bash +./gradlew nativeRun ``` > **NOTE:** RIFE2 support for GraalVM native-image is still in preliminary diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ad32a36..0e50f00 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,13 +1,32 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestLogEvent +import com.uwyn.rife2.gradle.TemplateType.* plugins { - java + application + id("com.uwyn.rife2") version "1.0.6" + `maven-publish` + id("org.graalvm.buildtools.native") version "0.9.20" +} + +version = 1.0 +group = "com.example" + +rife2 { + version.set("1.4.0") + uberMainClass.set("hello.AppUber") + useAgent.set(true) + precompiledTemplateTypes.add(HTML) } base { archivesName.set("hello") - version = 1.0 +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } } repositories { @@ -16,90 +35,40 @@ repositories { maven { url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots") } // only needed for SNAPSHOT } -sourceSets { - main { - runtimeClasspath = files(file("src/main/resources"), runtimeClasspath); - } -} - -sourceSets.main { - resources.exclude("templates/**") -} - dependencies { - implementation("com.uwyn.rife2:rife2:1.3.0") - runtimeOnly("com.uwyn.rife2:rife2:1.3.0:agent") - runtimeOnly("org.eclipse.jetty:jetty-server:11.0.13") - runtimeOnly("org.eclipse.jetty:jetty-servlet:11.0.13") - runtimeOnly("org.slf4j:slf4j-simple:2.0.5") - testImplementation("org.jsoup:jsoup:1.15.3") testImplementation("org.junit.jupiter:junit-jupiter:5.9.1") } -tasks { - val dependencies = configurations - .runtimeClasspath.get().files; - val rifeAgentJar = dependencies - .filter { it.toString().contains("rife2") } - .filter { it.toString().endsWith("-agent.jar") }[0] +application { + mainClass.set("hello.App") +} +tasks { test { - jvmArgs = listOf("-javaagent:$rifeAgentJar") useJUnitPlatform() testLogging { exceptionFormat = TestExceptionFormat.FULL events = setOf(TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED) } } +} - // Pre-compile the RIFE2 templates to bytecode for deployment - register("precompileHtmlTemplates") { - classpath = sourceSets["main"].runtimeClasspath - mainClass.set("rife.template.TemplateDeployer") - args = listOf( - "-verbose", - "-t", "html", - "-d", "${projectDir}/build/classes/java/main", - "-encoding", "UTF-8", "${projectDir}/src/main/resources/templates" - ) - } - - register("precompileTemplates") { - dependsOn("precompileHtmlTemplates") - } - - // Ensure that the templates are pre-compiled before building the jar - jar { - dependsOn("precompileTemplates") - } - - // Replace the run task with one that uses the RIFE2 agent - register("run") { - classpath = sourceSets["main"].runtimeClasspath - mainClass.set("hello.App") - jvmArgs = listOf("-javaagent:$rifeAgentJar") - } - - // These two tasks create a self-container UberJar - register("copyWebapp") { - from("src/main/") - include("webapp/**") - into("$buildDir/webapp") - } - - register("uberJar") { - dependsOn("jar") - dependsOn("copyWebapp") - archiveBaseName.set("hello-uber") - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - manifest { - attributes["Main-Class"] = "hello.AppUber" +publishing { + repositories { + maven { + name = "Build" + url = uri(rootProject.layout.buildDirectory.dir("repo")) } - val uberDependencies = dependencies - .filter { !it.toString().matches("rife2-.*agent\\.jar".toRegex()) } - .map(::zipTree) - from(uberDependencies, "$buildDir/webapp") - with(jar.get()) } -} \ No newline at end of file + publications { + create("maven") { + from(components["java"]) + } + } +} + +graalvmNative.binaries.all { + buildArgs.add("--enable-preview") // support for Jetty virtual threads with JDK 19 + imageName.set("hello-$version") +} diff --git a/app/src/main/java/hello/App.java b/app/src/main/java/hello/App.java index a7bed73..43a1870 100644 --- a/app/src/main/java/hello/App.java +++ b/app/src/main/java/hello/App.java @@ -13,4 +13,4 @@ public class App extends Site { .staticResourceBase("src/main/webapp") .start(new App()); } -} \ No newline at end of file +} diff --git a/app/src/main/resources/META-INF/native-image/reflect-config.json b/app/src/main/resources/META-INF/native-image/reflect-config.json index 9b0c3be..3f485d5 100644 --- a/app/src/main/resources/META-INF/native-image/reflect-config.json +++ b/app/src/main/resources/META-INF/native-image/reflect-config.json @@ -1,6 +1,6 @@ [ -{ - "name":"rife.template.html.hello", - "methods":[{"name":"","parameterTypes":[] }] -} + { + "name":"rife.template.html.hello", + "methods":[{"name":"","parameterTypes":[] }] + } ] diff --git a/app/src/main/resources/META-INF/native-image/resource-config.json b/app/src/main/resources/META-INF/native-image/resource-config.json deleted file mode 100644 index ad0b0a3..0000000 --- a/app/src/main/resources/META-INF/native-image/resource-config.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "resources":{ - "includes":[ - {"pattern":"^webapp/.*$"} - ] - }, - "bundles":[] -} diff --git a/app/src/main/resources/templates/hello.html b/app/src/main/resources/templates/hello.html index f7ffe8b..59ff81b 100644 --- a/app/src/main/resources/templates/hello.html +++ b/app/src/main/resources/templates/hello.html @@ -8,4 +8,4 @@

Hello World

- \ No newline at end of file + diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..4f996f1 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.parallel=true +org.gradle.caching=true diff --git a/settings.gradle.kts b/settings.gradle.kts index 29842fd..ba4e9a5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,11 +1,9 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * The settings file is used to specify which projects to include in your build. - * - * Detailed information about configuring a multi-project build in Gradle can be found - * in the user manual at https://docs.gradle.org/7.6/userguide/multi_project_builds.html - */ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} rootProject.name = "hello" include("app","war") diff --git a/war/build.gradle.kts b/war/build.gradle.kts index 206f003..c15092b 100644 --- a/war/build.gradle.kts +++ b/war/build.gradle.kts @@ -2,9 +2,10 @@ plugins { war } +version = 1.0 + base { archivesName.set("hello") - version = 1.0 } repositories { @@ -19,5 +20,4 @@ dependencies { tasks.war { webAppDirectory.set(file("../app/src/main/webapp")) webXml = file("src/web.xml") - rootSpec.exclude("**/jetty*.jar", "**/slf4j*.jar", "**/rife2*-agent.jar") } \ No newline at end of file