juneau-shaded-rest-client
The juneau-shaded-rest-client artifact bundles all core Juneau modules plus REST client functionality. At 3.8 MB, it provides everything needed for building REST client applications.
What's Included
This artifact includes:
- All modules from juneau-shaded-core (marshalling, config)
- juneau-rest-common - REST APIs common to client and server
- juneau-rest-common-classic - REST APIs common to the classic (Apache HttpClient 4.5) client and server
- juneau-rest-client - Transport-agnostic REST client (no Apache HttpClient dependency)
- juneau-rest-client-classic - Legacy REST client built on Apache HttpClient 4.5
Use Cases
Use juneau-shaded-rest-client when you need:
- REST API consumption - Call external REST services
- Type-safe clients - Use remote interfaces and proxies
- Advanced HTTP features - Interceptors, authentication, retries
- Serialization flexibility - Automatic content negotiation
- Testing REST endpoints - Use the mock REST framework (add
juneau-rest-mockas a test dependency — it is not bundled here)
| Maven | |
|---|---|
| Bazel | |
| Jar | juneau-shaded-rest-client-10.0.0.jar |
| Links | Maven Central · Javadocs · Source |
External Dependencies
juneau-shaded-rest-client requires:
HTTP Transport
- None for the canonical client - the canonical
juneau-rest-clienthas no Apache HttpClient dependency; it ships with a built-inJavaHttpTransportbacked by the JDK'sjava.net.http.HttpClientand works out of the box on Java 11+. - Apache HttpClient 4.5.x - required only if you use the classic
juneau-rest-client-classicclient, which is built on Apache HttpClient 4.5.
Optional
- Apache HttpClient 4.5.x / Apache HttpClient 5.x / OkHttp / Jetty client - to swap the default JDK-
HttpClient-based transport for a different native HTTP client, pull in one of thejuneau-rest-client-apache-httpclient-45/juneau-rest-client-apache-httpclient-50/juneau-rest-client-okhttp/juneau-rest-client-jettytransport modules. Each registers a higher-priorityHttpTransportProviderviaServiceLoaderand is picked up automatically. - Jakarta XML Bind API 3.0+ - For XML serialization
- Apache Jena - For RDF support
The code samples below target the canonical next-generation (NG) org.apache.juneau.rest.client.* client bundled in this shaded artifact — the headline module per What's Included above. The NG client is the recommended, generally available client in 10.0.0 and has a deliberately smaller surface than the classic client: no .json()/.basicAuth()/.oauth2Bearer() shortcuts, no RetryInterceptor. If you need those, use the bundled juneau-rest-client-classic (org.apache.juneau.rest.client.classic.*) instead — see REST Client Basics.
Example Usage
Basic REST Call
import org.apache.juneau.marshall.json.*;
import org.apache.juneau.rest.client.*;
public class RestClientExample {
public static void main(String[] args) throws Exception {
try (RestClient client = RestClient.builder()
.parser(JsonParser.DEFAULT)
.build()) {
// GET request
Person person = client.get("http://api.example.com/person/1")
.run()
.body().as(Person.class);
System.out.println(person.getName());
}
}
}
POST with JSON
try (RestClient client = RestClient.builder()
.serializer(JsonSerializer.DEFAULT)
.parser(JsonParser.DEFAULT)
.build()) {
Person newPerson = new Person("John Smith", 42);
// POST JSON
Person created = client.post("http://api.example.com/person")
.body(newPerson)
.run()
.body().as(Person.class);
System.out.println("Created: " + created.getId());
}
Remote Proxies
// Define interface
@Remote(path="/petstore")
public interface PetStore {
@RemoteGet("/pet/{petId}")
Pet getPet(@Path("petId") long id);
@RemotePost("/pet")
Pet createPet(@Content Pet pet);
}
// Use it
try (RestClient client = RestClient.builder()
.serializer(JsonSerializer.DEFAULT)
.parser(JsonParser.DEFAULT)
.build()) {
PetStore store = client.remote(PetStore.class);
Pet pet = store.getPet(123);
System.out.println(pet.getName());
}
Try-With-Resources Pattern
try (RestClient client = RestClient.builder().parser(JsonParser.DEFAULT).build()) {
String response = client.get("/api/data").run().body().asString();
System.out.println(response);
} // Client (and its underlying transport) is automatically closed
Authentication
The NG client has no built-in auth shortcuts (classic-only, per the note above); wire credentials in as plain headers:
// Basic authentication (manual, since there's no NG .basicAuth() shortcut)
String creds = Base64.getEncoder().encodeToString("user:password".getBytes(StandardCharsets.UTF_8));
RestClient client = RestClient.builder()
.header("Authorization", "Basic " + creds)
.build();
// Bearer token — a Supplier re-evaluates the header on every request (e.g. for token refresh)
RestClient client2 = RestClient.builder()
.header("Authorization", () -> "Bearer " + tokenSupplier.get())
.build();
Interceptors
RestCallInterceptor is a lifecycle callback interface (onInit/onConnect/onClose), not a per-request lambda — and there is no built-in RetryInterceptor on either client stack:
RestClient client = RestClient.builder()
.interceptors(new RestCallInterceptor() {
@Override
public void onInit(RestRequest req) {
System.out.println("Calling: " + req.getUri());
}
@Override
public void onConnect(RestRequest req, RestResponse res) {
System.out.println("Status: " + res.getStatusCode());
}
})
.build();
Mock Testing
The mock framework lives in juneau-rest-mock, which is not bundled in this shaded artifact. Add it as a separate test-scoped dependency to use MockRestClient:
import org.apache.juneau.rest.mock.*;
@Test
public void testRestClient() throws Exception {
MockRestClient client = MockRestClient.create(MyRestApi.class);
// Call the mocked API
String response = client.get("/test")
.run()
.body().asString();
assertEquals("expected", response);
}
Features
Content Negotiation
Automatic serialization/deserialization based on Accept and Content-Type headers (there is no dedicated .accept(String) shortcut on the NG client — set the header directly):
// Request JSON, get POJO
Person person = client.get("/person/1")
.header("Accept", "application/json")
.run()
.body().as(Person.class);
Error Handling
try (RestClient client = RestClient.builder().build()) {
String response = client.get("/api/data")
.run()
.assertOk() // Throws RestCallException if status is not 2xx
.body().asString();
} catch (RestCallException e) {
System.err.println("HTTP " + e.getStatusCode());
}
Request/Response Assertions
try (RestResponse resp = client.get("/api/data").run()) {
resp.assertThat()
.statusCode(200)
.header("Content-Type").contains("application/json")
.body().contains("expected");
}
Performance Characteristics
- Connection Pooling: Provided by the underlying HTTP transport (JDK
HttpClientby default, or the transport module you plug in) - Keep-Alive: Automatic connection reuse
- Streaming: Efficient memory usage for large responses
- Async Support: Non-blocking operations available
Migration from Individual Modules
Before:
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-marshall</artifactId>
<version>${juneau.version}</version>
</dependency>
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-rest-client</artifactId>
<version>${juneau.version}</version>
</dependency>
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-rest-common</artifactId>
<version>${juneau.version}</version>
</dependency>
After:
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-shaded-rest-client</artifactId>
<version>${juneau.version}</version>
</dependency>
Next Steps
- Need server functionality too? Use juneau-shaded-all
- Learn about REST client: See REST Client Basics
- Learn about remote proxies: See Remote Proxies
- Learn about marshalling: See Marshalling Basics