The Gradle Plugin

The net.benelog.spidersilk plugin carries the packaging conventions, so a build states only what is the application’s own: the main class, the image name, and the native binary’s resources. An application that containerizes with Jib, precompiles its templates, and perhaps compiles to a native binary would otherwise restate the same block in every build file.

plugins {
    id 'net.benelog.spidersilk' version '1.1.0'
}

spiderSilk {
    jte()   // precompiled templates; leave out for FreeMarker, Handlebars, or Thymeleaf
}

application {
    mainClass = 'flashcard.FlashcardApp'
}

jib {
    to {
        image = 'ghcr.io/benelog/spider-silk-flashcard'
    }
}

The plugin is published to Maven Central with the jars, not to the Gradle Plugin Portal. Gradle looks up a plugin id in the Plugin Portal alone by default, so settings.gradle adds Central to the plugin repositories:

pluginManagement {
    repositories {
        mavenCentral()
        gradlePluginPortal()
    }
}

What applying it does

Applying the plugin applies application, Jib, and the GraalVM native plugin, and sets the conventions the surrounding chapters walk through:

  • Jib builds on eclipse-temurin:21-jre and exposes port 8080, layered the way Deployment describes.

  • targetCompatibility is derived from options.release, closing the gap where Jib would otherwise read the toolchain’s version and refuse the JRE base.

  • The native binary builds --no-fallback, since a fallback image is a JVM carrying the reflection the framework exists to avoid, and mostly static (--static-nolibc), so the distroless/base container below owes it nothing but glibc. GraalVM’s reachability metadata repository is enabled for libraries like H2.

  • A resolveDependencies task downloads the external runtime jars and nothing else, for a Dockerfile’s dependency-cache layer.

  • -Pnative re-aims jib, jibBuildTar, and jibDockerBuild at the GraalVM binary: a distroless/base image in place of the JRE, :native appended to the configured image name so the JVM image is not overwritten, and the task dependency on nativeCompile wired. The native image chapter shows that switch in action.

Every one of these lands before the build script’s own blocks run, so overriding a convention is a matter of configuring jib, graalvmNative, or java as usual. The diagram shows what the plugin wires between the sources and the two images a build can produce:

The templates become Java classes through generateJte
Figure 1. From the sources to a container image

spiderSilk.jte()

jte() is the one opt-in, since not every application renders with jte. It sets up precompilation exactly as Templates describes: every template under src/main/resources/jte becomes a Java class at build time, so the jar renders without a runtime compiler and a template that does not compile fails the build rather than the request. It also attaches jte’s native-resources extension, which emits the reflection config a native image needs for the generated template classes.

What the plugin pins

The plugin’s version fixes the versions of what it applies: jte 3.2.4, Jib 3.5.4, and the GraalVM build tools 1.1.10. A toolchain bump arrives as a plugin release. Nothing the plugin does is beyond plain Gradle: each convention is a handful of lines in the open, and the chapters linked above show the expanded form for a build that would rather own them directly. A Maven build gets the same conventions by inheritance instead; see The Maven Parent.