Class VersionMixin

java.lang.Object
org.apache.juneau.rest.server.servlet.RestMixin
org.apache.juneau.rest.server.convention.VersionMixin

public class VersionMixin extends RestMixin
Mixin that serves deployment-introspection metadata at /version (configurable).

Sibling of FaviconMixin, SeoMixin, and WellKnownMixin. All four classes live in the org.apache.juneau.rest.server.convention convention-endpoints mixin pack.

Compose into a host resource via @Rest(mixins=VersionMixin.class); the /version URL becomes available alongside the host's own endpoints with no further wiring.

Configurable mount path:

The default mount /version can be overridden via the SVL variable ${juneau.version.path:version} — set via system property (-Djuneau.version.path=build-info), environment variable (JUNEAU_VERSION_PATH=build-info), or Config key (juneau.version.path = build-info) to change the runtime mount without subclassing. Resolution happens once at RestContext construction time.

Override accepts bare token (version), leading slash (/version), or trailing slash (version/) — all resolve to the same mount.

Migration note (10.0.0): Earlier development snapshots of this mixin mounted at three historical aliases — /version, /info, and /about — on a single op. That multi-path default has been collapsed to a single SVL-configurable mount as part of the "single path per op" principle. Deployers who relied on the /info or /about aliases must now either set -Djuneau.version.path=info (or about), compose a second instance with the desired override, or subclass and supply their own @RestGet(path=...) method.

Mixin-only deployment:

This resource is designed for composition via @Rest(mixins=...). The mount path is pinned at the op level by @RestGet(path="/{juneau.version.path:version}") on getInfo(org.apache.juneau.rest.server.RestResponse); a class-level @Rest(paths=...) declaration would be silently ignored under the mixin pattern (see @Rest(paths) Javadoc).

Composition example:

@Rest(path="/api", mixins=VersionMixin.class) public class ApiResource extends RestServlet { } // Default behavior reads MANIFEST.MF + git.properties from the importer's classpath. // Override programmatically via a @Bean factory: @Bean VersionMixin version() { return VersionMixin.create() .entry("name", "my-app") .entry("version", "1.2.3") .build(); }

Default lookup chain:

The default fromManifest() reader walks the VersionMixin classloader for /META-INF/MANIFEST.MF and reads the standard Implementation-Title, Implementation-Version, Implementation-Vendor, and Build-Jdk attributes (lowercased to name, version, vendor, javaVersion). The default fromGitProperties() reader walks the same classloader for /git.properties (the canonical git-commit-id-maven-plugin output) and surfaces git.commit.id, git.branch, and git.build.time as gitCommit, gitBranch, and buildTime. Missing files / missing keys map to "(unknown)" or are simply omitted — never an exception.

Spring Boot fat-jar caveat: Spring Boot rewrites MANIFEST.MF during repackaging. The mixin's no-arg-default reader uses VersionMixin.class.getClassLoader(); users who want the importer's app manifest under a Spring Boot executable jar should register an explicit fromManifest(importerClassLoader) call so the lookup starts from the importer's classloader rather than the framework's.

Output:

The endpoint returns a JSON map — e.g.:

{ "name": "my-app", "version": "1.2.3", "gitCommit": "abc123", "gitBranch": "main", "buildTime": "2026-05-24T18:00:00Z", "javaVersion": "21" }

Endpoints are excluded from generated Swagger / OpenAPI specs via @OpSwagger(ignore=true).

See Also:
Since:
10.0.0
  • Field Details

  • Constructor Details

    • VersionMixin

      public VersionMixin()
      No-arg constructor — delegates to a default VersionProvider worker (reads MANIFEST.MF, git.properties, and the JVM version from the framework classloader).
    • VersionMixin

      protected VersionMixin(VersionProvider worker)
      Worker constructor.
      Parameters:
      worker - The shared VersionProvider worker this flavor delegates to. Must not be null.
    • VersionMixin

      protected VersionMixin(VersionProvider worker, RestBuilder<?> builder)
      Worker + builder constructor.

      Used by VersionMixin.Builder.build() to both delegate to the shared VersionProvider worker and stash the programmatic RestBuilder(carrying any @Rest-level overrides such as path) so those values take precedence over the mixin class's own @Rest annotation.

      Why worker + builder, not the flavor Builder:
      • Takes the already-built worker bean (not the flavor VersionMixin.Builder) so the flavor can be constructed from ANY independently-supplied worker — e.g. a user's own @Bean VersionProvider or BeanStore bean, per the delegate-bean model — not only via this flavor's own builder.
      • Takes the generic RestBuilder(here this from VersionMixin.Builder.build()) so it honors the uniform §2.4 Foo(RestBuilder<?>) injection contract the base class and DI resolution key on; the base knows nothing about the concrete flavor builder or the worker type.
      • Holds the finished worker product (the final VersionProvider field), not a transient builder; the worker is materialized exactly once at VersionMixin.Builder.build() time.
      • Keeps the capability worker and the REST-level config as two distinct inputs.
      Parameters:
      worker - The shared VersionProvider worker this flavor delegates to. Must not be null.
      builder - The programmatic configuration builder. May be null.
  • Method Details