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
| Artifact | Size | Description | Details |
|---|---|---|---|
| juneau-shaded-core | 2.0 MB | Core marshalling and configuration functionality | Learn more → |
| juneau-shaded-rest-client | 3.8 MB | Core + REST client functionality | Learn more → |
| juneau-shaded-rest-server | 3.8 MB | Core + REST server functionality | Learn more → |
| juneau-shaded-rest-server-springboot | 3.8 MB | REST server + Spring Boot integration | Learn more → |
| juneau-shaded-all | 4.0 MB | Complete Juneau framework in one JAR | Learn 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 Artifact | Common External Dependencies |
|---|---|
juneau-shaded-core | None |
juneau-shaded-rest-client | httpclient5, httpcore5 |
juneau-shaded-rest-server | jakarta.servlet-api, jetty-server |
juneau-shaded-rest-server-springboot | spring-boot-starter-web, jakarta.servlet-api |
juneau-shaded-all | All 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
- Start with the smallest shaded artifact that meets your needs
- Always check
dependency-reduced-pom.xmlfor external dependencies - Use
rules_jvm_externalfor production Bazel builds - Pin dependency versions to ensure reproducible builds
- 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
- Juneau Shaded Core - Core marshalling and configuration
- Juneau Shaded REST Client - REST client development
- Juneau Shaded REST Server - REST server development
- Juneau Shaded REST Server Spring Boot - Spring Boot integration
- Juneau Shaded All - Complete framework
Additional Resources
- Shaded Module README - Complete technical documentation
- Juneau Documentation - Official Juneau docs
- Bazel Documentation - Learn more about Bazel
- Apache Juneau Mailing List - Get help from the community
Share feedback or follow-up questions for this page directly through GitHub.