Skip to main content

Juneau Shaded Artifacts

Juneau provides shaded (uber) JAR artifacts that bundle multiple Juneau modules into single JAR files. These artifacts simplify dependency management and are especially useful for build systems like Bazel that require explicit dependency declarations.

What Are Shaded Artifacts?

Shaded artifacts use the Maven Shade Plugin to:

  • Bundle multiple Juneau modules into a single JAR
  • Merge service provider files automatically
  • Eliminate the need to declare transitive Juneau dependencies
  • Maintain all original functionality without modification

Important: Shaded artifacts only bundle Juneau modules. External dependencies (like Apache HttpClient, Jakarta Servlet API, etc.) must still be declared separately.

Available Shaded Artifacts

ArtifactSizeDescriptionDetails
juneau-shaded-core2.0 MBCore marshalling and configuration functionalityLearn more →
juneau-shaded-rest-client3.8 MBCore + REST client functionalityLearn more →
juneau-shaded-rest-server3.8 MBCore + REST server functionalityLearn more →
juneau-shaded-rest-server-springboot3.8 MBREST server + Spring Boot integrationLearn more →
juneau-shaded-all4.0 MBComplete Juneau framework in one JARLearn more →

When to Use Shaded Artifacts

✅ Use Shaded Artifacts When:

  • Using Bazel or similar build systems - These require explicit dependency declarations; shaded artifacts simplify this significantly
  • Wanting simplified dependency management - One dependency instead of many
  • Building standalone applications - Uber JARs are convenient for deployment
  • Getting started quickly - Fewer decisions about which modules to include

❌ Consider Individual Modules When:

  • Building a library - Other projects may need fine-grained control over dependencies
  • Minimizing JAR size - Individual modules allow excluding unused functionality
  • Avoiding classpath conflicts - In complex applications with many dependencies
  • Needing different module versions - Though this is rarely necessary

Quick Start

Maven

<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-shaded-all</artifactId>
<version>${juneau.version}</version>
</dependency>

Bazel

maven_jar(
name = "juneau_all",
artifact = "org.apache.juneau:juneau-shaded-all:${juneau.version}",
)

Why Shaded Artifacts for Bazel?

Bazel enforces strict dependency management where you must explicitly declare every direct dependency your code uses. Unlike Maven, which automatically resolves transitive dependencies, Bazel requires you to know and declare all dependencies.

The Problem with Regular Juneau in Bazel

When using regular Juneau modules in Bazel:

# This is incomplete and will fail!
maven_jar(
name = "juneau_marshall",
artifact = "org.apache.juneau:juneau-marshall:9.2.0-SNAPSHOT",
)

java_library(
name = "my_lib",
srcs = ["MyCode.java"],
deps = ["@juneau_marshall//jar"], # Missing juneau-common!
)

Problem: Your code can't compile because juneau-marshall depends on juneau-common, but you didn't declare it.

Solution with Shaded Artifacts

Just one dependency declaration!

maven_jar(
name = "juneau_core",
artifact = "org.apache.juneau:juneau-shaded-core:9.2.0-SNAPSHOT",
)

java_library(
name = "my_lib",
srcs = ["MyCode.java"],
deps = ["@juneau_core//jar"], # Everything included!
)

Complete Bazel Examples

Example 1: REST Client

Scenario: Build a REST client application.

WORKSPACE:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

# Add Maven dependencies
maven_jar(
name = "juneau_rest_client",
artifact = "org.apache.juneau:juneau-shaded-rest-client:9.2.0-SNAPSHOT",
repository = "https://repository.apache.org/content/repositories/snapshots/",
)

# External dependencies (still need these)
maven_jar(
name = "httpclient5",
artifact = "org.apache.httpcomponents.client5:httpclient5:5.2.1",
)

maven_jar(
name = "httpcore5",
artifact = "org.apache.httpcomponents.core5:httpcore5:5.2.1",
)

BUILD:

java_binary(
name = "my_rest_client",
srcs = ["MyRestClient.java"],
deps = [
"@juneau_rest_client//jar",
"@httpclient5//jar",
"@httpcore5//jar",
],
main_class = "com.example.MyRestClient",
)

Example 2: REST Server

Scenario: Build a REST server application.

WORKSPACE:

maven_jar(
name = "juneau_rest_server",
artifact = "org.apache.juneau:juneau-shaded-rest-server:9.2.0-SNAPSHOT",
repository = "https://repository.apache.org/content/repositories/snapshots/",
)

maven_jar(
name = "jakarta_servlet_api",
artifact = "jakarta.servlet:jakarta.servlet-api:6.1.0",
)

maven_jar(
name = "jetty_server",
artifact = "org.eclipse.jetty:jetty-server:12.0.5",
)

BUILD:

java_library(
name = "my_rest_server",
srcs = ["MyRestServer.java"],
deps = [
"@juneau_rest_server//jar",
"@jakarta_servlet_api//jar",
"@jetty_server//jar",
],
)

Example 3: Spring Boot Integration

Scenario: Build a Spring Boot + Juneau application.

WORKSPACE:

maven_jar(
name = "juneau_rest_server_springboot",
artifact = "org.apache.juneau:juneau-shaded-rest-server-springboot:9.2.0-SNAPSHOT",
repository = "https://repository.apache.org/content/repositories/snapshots/",
)

maven_jar(
name = "spring_boot_starter_web",
artifact = "org.springframework.boot:spring-boot-starter-web:3.2.0",
)

BUILD:

java_library(
name = "my_spring_app",
srcs = glob(["src/**/*.java"]),
deps = [
"@juneau_rest_server_springboot//jar",
"@spring_boot_starter_web//jar",
],
)

Example 4: Core Marshalling Only

Scenario: Use Juneau for JSON/XML/etc. serialization without REST features.

WORKSPACE:

maven_jar(
name = "juneau_core",
artifact = "org.apache.juneau:juneau-shaded-core:9.2.0-SNAPSHOT",
repository = "https://repository.apache.org/content/repositories/snapshots/",
)

BUILD:

java_library(
name = "my_serialization_lib",
srcs = ["MySerializer.java"],
deps = [
"@juneau_core//jar",
],
)

Example 5: Everything (Complete Framework)

Scenario: You want access to all Juneau features.

WORKSPACE:

maven_jar(
name = "juneau_all",
artifact = "org.apache.juneau:juneau-shaded-all:9.2.0-SNAPSHOT",
repository = "https://repository.apache.org/content/repositories/snapshots/",
)

# Still need external dependencies
maven_jar(
name = "jakarta_servlet_api",
artifact = "jakarta.servlet:jakarta.servlet-api:6.1.0",
)

maven_jar(
name = "httpclient5",
artifact = "org.apache.httpcomponents.client5:httpclient5:5.2.1",
)

BUILD:

java_library(
name = "my_full_app",
srcs = glob(["src/**/*.java"]),
deps = [
"@juneau_all//jar",
"@jakarta_servlet_api//jar",
"@httpclient5//jar",
],
)

Finding External Dependencies

Shaded JARs only bundle Juneau modules. External dependencies (like Apache HttpClient, Jakarta Servlet API, etc.) must still be declared separately.

Method 1: Check the dependency-reduced-pom.xml

After building a shaded module, examine:

cat juneau-shaded/juneau-shaded-rest-client/dependency-reduced-pom.xml

This file lists all external dependencies that the shaded JAR still requires.

Method 2: Use Maven dependency:tree

cd juneau-shaded/juneau-shaded-rest-client
mvn dependency:tree

Method 3: Common External Dependencies

Here's a quick reference:

Juneau Shaded ArtifactCommon External Dependencies
juneau-shaded-coreNone
juneau-shaded-rest-clienthttpclient5, httpcore5
juneau-shaded-rest-serverjakarta.servlet-api, jetty-server
juneau-shaded-rest-server-springbootspring-boot-starter-web, jakarta.servlet-api
juneau-shaded-allAll of the above

Advanced: Using rules_jvm_external

For more sophisticated Bazel builds, use rules_jvm_external:

WORKSPACE:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

RULES_JVM_EXTERNAL_TAG = "5.3"
RULES_JVM_EXTERNAL_SHA = "d31e369b854322ca5098ea12c69d7175ded971435e55c18dd9dd5f29cc5249ac"

http_archive(
name = "rules_jvm_external",
strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
sha256 = RULES_JVM_EXTERNAL_SHA,
url = "https://github.com/bazelbuild/rules_jvm_external/releases/download/%s/rules_jvm_external-%s.tar.gz" % (RULES_JVM_EXTERNAL_TAG, RULES_JVM_EXTERNAL_TAG),
)

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
artifacts = [
"org.apache.juneau:juneau-shaded-rest-client:9.2.0-SNAPSHOT",
"org.apache.httpcomponents.client5:httpclient5:5.2.1",
"org.apache.httpcomponents.core5:httpcore5:5.2.1",
],
repositories = [
"https://repository.apache.org/content/repositories/snapshots/",
"https://repo1.maven.org/maven2",
],
fetch_sources = True,
)

BUILD:

java_binary(
name = "my_app",
srcs = ["MyApp.java"],
deps = [
"@maven//:org_apache_juneau_juneau_shaded_rest_client",
"@maven//:org_apache_httpcomponents_client5_httpclient5",
"@maven//:org_apache_httpcomponents_core5_httpcore5",
],
main_class = "com.example.MyApp",
)

Bazel Troubleshooting

Build fails with "package X does not exist"

Cause: You're missing an external dependency.

Solution: Check the dependency-reduced-pom.xml for the shaded module and add the missing dependency to your WORKSPACE.

Conflicting versions of dependencies

Cause: Multiple artifacts depend on different versions of the same library.

Solution: Use rules_jvm_external with version resolution:

maven_install(
artifacts = [
"org.apache.juneau:juneau-shaded-rest-client:9.2.0-SNAPSHOT",
"org.apache.httpcomponents.client5:httpclient5:5.2.1",
],
version_conflict_policy = "pinned", # Use specific versions
)

Shaded JAR is too large

Cause: You're using juneau-shaded-all when you only need a subset.

Solution: Use a more specific shaded artifact:

  • For client only: juneau-shaded-rest-client
  • For server only: juneau-shaded-rest-server
  • For core only: juneau-shaded-core

Bazel Best Practices

  1. Start with the smallest shaded artifact that meets your needs
  2. Always check dependency-reduced-pom.xml for external dependencies
  3. Use rules_jvm_external for production Bazel builds
  4. Pin dependency versions to ensure reproducible builds
  5. Document external dependencies in your project's README

Performance Considerations

Build Time

  • Shaded JARs: Faster builds due to fewer dependency declarations
  • Individual Modules: More explicit control but slower due to transitive resolution

Runtime

  • No runtime difference between shaded and non-shaded artifacts
  • Same classes, same performance characteristics

JAR Size

  • Shaded JARs are larger but self-contained
  • For microservices, this is usually acceptable
  • For libraries, consider using individual modules

Architecture

The shaded modules form a dependency hierarchy:

juneau-shaded-core (2.1 MB)

├─→ juneau-shaded-rest-client (3.8 MB)

└─→ juneau-shaded-rest-server (3.8 MB)

└─→ juneau-shaded-rest-server-springboot (3.8 MB)

juneau-shaded-all (4.0 MB)
= juneau-shaded-rest-server-springboot
+ juneau-rest-client
+ all bean modules
+ all microservice modules

Distribution

All shaded artifacts are included in the binary distribution under the /shaded directory:

apache-juneau-${version}-bin.zip
└── shaded/
├── juneau-shaded-core-${version}.jar
├── juneau-shaded-rest-client-${version}.jar
├── juneau-shaded-rest-server-${version}.jar
├── juneau-shaded-rest-server-springboot-${version}.jar
└── juneau-shaded-all-${version}.jar

Learn More

Individual Shaded Artifacts

Additional Resources

Discussion

Share feedback or follow-up questions for this page directly through GitHub.