Skip to main content

Dependency Management

Apache Juneau ships two packaging aids that make it easy to depend on a coherent, version-aligned slice of the framework without hand-maintaining a long list of <version> tags:

  • A Bill of Materials (BOM) — org.apache.juneau:juneau-bom — for version alignment.
  • A small set of curated dependency bundles — one per deployment shape — that transitively pull a coherent module set.

Both are deliberately dependency-only aids. They register nothing and discover nothing at runtime (see Explicit over magic below).

The BOM​

The ${juneau.version} property is 10.0.0-SNAPSHOT for these docs; the latest release on Maven Central is 9.2.0. See Install Juneau.

The BOM is a 10.0 artifact; it is not published for 9.2.0.

Import juneau-bom (scope import, type pom) in your <dependencyManagement> and then drop the explicit versions from every Juneau dependency — the BOM supplies them:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-bom</artifactId>
<version>${juneau.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<!-- No <version> needed - the BOM aligns it. -->
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-marshall</artifactId>
</dependency>
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-rest-server</artifactId>
</dependency>
</dependencies>

The BOM enumerates the consumer-facing Juneau modules (juneau-core marshalling/config, juneau-rest, juneau-microservice, juneau-bean, juneau-sc), the test-support modules (juneau-bct, juneau-microservice-test, juneau-rest-mock), and the curated *-bundle POMs themselves. It excludes aggregate/non-library artifacts (juneau-shaded/*, juneau-examples, juneau-petstore, juneau-distrib) and the juneau-terminal build tooling.

BOM module catalog​

Every module below is version-managed by juneau-bom. See the Ecosystem Overview for what each one does and what it requires.

AreaManaged artifacts
Corejuneau-commons, juneau-config, juneau-marshall, juneau-marshall-rdf, juneau-beanquery-sql, juneau-beanquery-postgres, juneau-bct
Secretsjuneau-secret-macos-keychain
Beansjuneau-bean-atom, juneau-bean-common, juneau-bean-hal, juneau-bean-html5, juneau-bean-jsonapi, juneau-bean-jsonpatch, juneau-bean-jsonrpc, juneau-bean-jsonschema, juneau-bean-mcp-v20250618, juneau-bean-mcp-v20260728, juneau-bean-openapi-v3, juneau-bean-rfc7807, juneau-bean-swagger-v2
REST common and mockjuneau-rest-common, juneau-rest-common-classic, juneau-rest-mock
REST serverjuneau-rest-server, juneau-rest-server-rdf, juneau-rest-server-springboot, juneau-rest-server-management-logging, juneau-rest-server-reactive, juneau-rest-server-reactive-reactor
REST server: MCPjuneau-rest-server-mcp, juneau-rest-server-mcp-v20250618, juneau-rest-server-mcp-v20260728
REST server: authjuneau-rest-server-auth-jwt, juneau-rest-server-auth-saml, juneau-rest-server-auth-oauth, juneau-rest-server-auth-oidc-rp, juneau-rest-auth-oauth-flow
REST server: observabilityjuneau-rest-server-metrics-micrometer, juneau-rest-server-tracing-otel
REST server: view enginesjuneau-rest-server-view-freemarker, juneau-rest-server-view-jsp, juneau-rest-server-view-mustache, juneau-rest-server-view-thymeleaf
REST server: console UI and viewsjuneau-console, juneau-console-freemarker, juneau-console-datatables, juneau-console-views, juneau-console-views-markdown, juneau-console-widgets, juneau-terminal-report
REST clientjuneau-rest-client, juneau-rest-client-classic, juneau-rest-client-apache-httpclient-45, juneau-rest-client-apache-httpclient-50, juneau-rest-client-okhttp, juneau-rest-client-jetty
REST client: MCPjuneau-rest-client-mcp, juneau-rest-client-mcp-v20250618, juneau-rest-client-mcp-v20260728, juneau-rest-client-mcp-auth
Microservicejuneau-microservice, juneau-microservice-jetty, juneau-microservice-tomcat, juneau-microservice-test
Server configjuneau-sc-server
Bundlesjuneau-microservice-jetty-bundle, juneau-microservice-tomcat-bundle, juneau-springboot-bundle, juneau-observability-otlp-bundle

Beyond Juneau's own modules, the BOM also pins the small set of starter-relevant third-party versions the bundles need to stay coherent — Micrometer (micrometer-core, micrometer-registry-otlp), OpenTelemetry (opentelemetry-api, opentelemetry-sdk, opentelemetry-exporter-otlp, opentelemetry-sdk-extension-autoconfigure), and Jakarta (jakarta.servlet-api, jakarta.validation-api). It is not a whole-world third-party BOM (unlike Spring Boot's), so it won't collide with a third-party BOM you import yourself.

The bundles​

Juneau also publishes bundle artifacts — <packaging>pom</packaging> Maven coordinates that pull a curated, version-aligned set of Juneau modules (and their transitive dependencies) in a single declaration. Each bundle targets one deployment shape: depend on a single bundle and you transitively pull a coherent module set plus the REST client.

Bundles are dependency aggregators only: they contain no code, register no configurations, and perform no classpath auto-discovery. Every bean, server, and resource still needs to be wired explicitly, exactly as if you had listed the individual modules yourself. Because each bundle internally imports juneau-bom, the modules it pulls are already version-aligned.

Bundle vs. starter. These *-bundle POMs are dependency aggregators — add one dependency, get a coherent module set. They are not to be confused with the clone-and-go starter project templates on dedicated apache/juneau branches (microservice-*-starter), which are full runnable project templates.

Bundles vs shaded JARs vs individual modules​

ApproachWhat it isBest for
BundleA POM-type dependency that pulls a curated module set transitivelyApplications where you control the full classpath and want a quick start
Shaded JARA single fat JAR with Juneau modules merged inBazel builds or environments that need a single-artifact classpath; see Juneau Shaded Artifacts
Individual modulesEach Juneau JAR declared explicitlyLibraries and frameworks that want fine-grained transitive dependency control

Available bundles​

ArtifactUse when
juneau-microservice-jetty-bundleBuilding an embedded-Jetty microservice
juneau-microservice-tomcat-bundleBuilding an embedded-Tomcat microservice
juneau-springboot-bundleAdding Juneau REST resources to Spring Boot
juneau-observability-otlp-bundleExporting metrics + traces over OTLP in one dependency

juneau-microservice-jetty-bundle​

<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-microservice-jetty-bundle</artifactId>
<version>${juneau.version}</version>
<type>pom</type>
</dependency>

Pulls the full embedded-Jetty microservice stack for a standalone service process:

Direct dependencyWhat it brings
juneau-microservice-jettyEmbedded-Jetty launcher, juneau-microservice lifecycle, juneau-rest-server, juneau-marshall, juneau-config, juneau-commons, and the Jetty embedded-server JARs at the tested compatible version
juneau-rest-clientREST client for typical service-to-service calls

Use this when starting a new Jetty-based microservice and you want a single dependency to bootstrap the project. Wire your servers explicitly via Microservice.Builder.configurations(...) — the bundle performs no auto-configuration.

See juneau-microservice-jetty for setup instructions.

juneau-microservice-tomcat-bundle​

<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-microservice-tomcat-bundle</artifactId>
<version>${juneau.version}</version>
<type>pom</type>
</dependency>

The Tomcat equivalent of juneau-microservice-jetty-bundle:

Direct dependencyWhat it brings
juneau-microservice-tomcatEmbedded-Tomcat launcher, juneau-microservice lifecycle, juneau-rest-server, juneau-marshall, juneau-config, juneau-commons, and the Tomcat embedded-server JARs at the tested compatible version
juneau-rest-clientREST client for typical service-to-service calls

Wire your servers explicitly via Microservice.Builder.configurations(...).

See juneau-microservice-tomcat for setup instructions.

juneau-springboot-bundle​

<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-springboot-bundle</artifactId>
<version>${juneau.version}</version>
<type>pom</type>
</dependency>

Pulls the Juneau REST server stack for a Spring Boot application:

Direct dependencyWhat it brings
juneau-rest-server-springbootSpring Boot bridge, juneau-rest-server, spring-boot-starter-web, and the shared juneau-rest-common types
juneau-rest-clientREST client for typical service-to-service calls

Wire your @Rest-annotated resources explicitly in your Spring @Configuration classes — the bundle performs no classpath auto-discovery.

See juneau-rest-server-springboot for Spring Boot integration details.

juneau-observability-otlp-bundle​

<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-observability-otlp-bundle</artifactId>
<version>${juneau.version}</version>
<type>pom</type>
</dependency>

Pulls both Juneau observability bridges plus a coherent, version-aligned OTLP exporter stack in one dependency:

Direct dependencyWhat it brings
juneau-rest-server-metrics-micrometerMicrometerMetricsRecorder — the MetricsRecorder SPI implementation
juneau-rest-server-tracing-otelOtelTracerHook — the TracerHook SPI implementation
opentelemetry-exporter-otlpOTLP span exporter
opentelemetry-sdkOpenTelemetry SDK (satisfies the provided OTel API dependency of the tracing bridge)
opentelemetry-sdk-extension-autoconfigureSDK auto-configure extension
micrometer-registry-otlpMicrometer OTLP registry (satisfies the provided Micrometer dependency of the metrics bridge)

The bundle covers metrics and traces; OTLP log export is not included in v1.

Because the bundle is a dependency aggregator only, you still register the beans explicitly:

@Configuration
public class ObservabilityConfig {

@Bean MeterRegistry registry() {
// OtlpMeterRegistry is the Micrometer OTLP registry pulled by the bundle.
return new OtlpMeterRegistry(OtlpConfig.DEFAULT, Clock.SYSTEM);
}

@Bean MetricsRecorder recorder(MeterRegistry r) {
return new MicrometerMetricsRecorder(r);
}

@Bean TracerHook tracer() {
// Uses GlobalOpenTelemetry, typically wired by the OTel Java agent or SDK autoconfigure.
return new OtelTracerHook();
}
}

See Observability — Micrometer + OpenTelemetry for the full configuration guide including per-operation controls, W3C trace-context propagation, and custom MetricsRecorder / TracerHook implementations.

When to use a bundle vs building your own assembly​

Use a bundle when:​

  • Starting a new application — one dependency gets you a working, version-aligned stack.
  • You control the full classpath — no other dependency manager can conflict with the bundle's transitive pulls.
  • You want the versions the Juneau team tested — bundle dependencies are pinned against the juneau-bom so all Juneau sub-modules and their third-party peers are mutually compatible.

Build your own assembly when:​

  • Writing a library — declare only the modules your library's API surface requires; don't force your consumers to pull a full microservice stack.
  • Mixing with an existing framework — if your project already declares Jetty or Spring Boot at a specific version, depend on the individual Juneau modules and let your build tool resolve the container version.
  • Minimizing JAR footprint — a single microservice module is smaller than the full microservice bundle when you know exactly which Juneau features you use.

Explicit over magic (no auto-configuration)​

A bundle gives you the classpath for a deployment shape. It does not wire anything up for you. Juneau keeps configuration registration explicit — you register your configuration classes yourself through Microservice.Builder.configurations(Class<?>...). There is no ServiceLoader / META-INF/services scan and no @ConditionalOnClass-style classpath auto-discovery that decides what to activate based on what happens to be on the classpath.

This is a deliberate design choice, not a missing feature. In the maintainer's words:

"No, we want an explicit classpath-driven solution. I actually see auto-configuration as a weakness in Spring Boot that leads to applications with long startup times and impossible-to-understand architectures. We should make this distinction clear in our docs."

The two costs called out there are exactly what the explicit model avoids:

  • Startup time. No classpath scanning for conditional configuration to evaluate at boot. What you register is what runs.
  • Comprehensibility. The set of active configurations is the literal list you passed to configurations(...) — readable in one place, with no implicit behavior toggled on by a transitive dependency you didn't realize was present.

So the division of labor is clean: the BOM aligns versions, the bundles assemble a coherent classpath, and you stay in explicit control of what gets wired up.

See also​

In This Section​