Skip to main content

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, testing)
  • juneau-rest-common - REST APIs common to client and server
  • juneau-rest-client - Full-featured REST client API
  • juneau-rest-mock - REST testing utilities

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

Maven Dependency

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

Bazel Dependency

maven_jar(
name = "juneau_rest_client",
artifact = "org.apache.juneau:juneau-shaded-rest-client:${juneau.version}",
)

# External dependencies
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",
)

java_binary(
name = "my_client",
srcs = ["MyClient.java"],
deps = [
"@juneau_rest_client//jar",
"@httpclient5//jar",
"@httpcore5//jar",
],
)

External Dependencies

juneau-shaded-rest-client requires:

Required

  • Apache HttpClient 5.2+ - HTTP client implementation
  • Apache HttpCore 5.2+ - HTTP core functionality

Optional

  • Jakarta XML Bind API 3.0+ - For XML serialization
  • Apache Jena - For RDF support

Example Usage

Basic REST Call

import org.apache.juneau.rest.client.*;

public class RestClientExample {
public static void main(String[] args) {
try (RestClient client = RestClient.create().build()) {
// GET request
Person person = client.get("http://api.example.com/person/1")
.run()
.getContent().as(Person.class);

System.out.println(person.getName());
}
}
}

POST with JSON

try (RestClient client = RestClient.create().json().build()) {
Person newPerson = new Person("John Smith", 42);

// POST JSON
Person created = client.post("http://api.example.com/person")
.content(newPerson)
.run()
.getContent().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.create().build()) {
PetStore store = client.getRemote(PetStore.class);

Pet pet = store.getPet(123);
System.out.println(pet.getName());
}

Try-With-Resources Pattern

RestClient client = RestClient.create().build();

try (RestRequest req = client.get("/api/data")) {
String response = req.run().getContent().asString();
System.out.println(response);
} // Request and response are automatically closed

Authentication

// Basic authentication
RestClient client = RestClient.create()
.basicAuth("user", "password")
.build();

// Bearer token
RestClient client = RestClient.create()
.headerData("Authorization", "Bearer " + token)
.build();

// OAuth2
RestClient client = RestClient.create()
.oauth2Bearer(tokenSupplier)
.build();

Interceptors

RestClient client = RestClient.create()
.interceptors(
// Log requests
(req) -> System.out.println("Calling: " + req.getUri()),

// Add custom headers
(req) -> req.header("X-Custom", "value"),

// Retry logic
RetryInterceptor.create().maxAttempts(3).build()
)
.build();

Mock Testing

import org.apache.juneau.rest.mock.*;

@Test
public void testRestClient() throws Exception {
MockRestClient client = MockRestClient.create(MyRestApi.class).build();

// Call the mocked API
String response = client.get("/test")
.run()
.getContent().asString();

assertEquals("expected", response);
}

Features

Content Negotiation

Automatic serialization/deserialization based on Accept and Content-Type headers:

// Request JSON, get POJO
Person person = client.get("/person/1")
.accept("application/json")
.run()
.getContent().as(Person.class);

Error Handling

try (RestClient client = RestClient.create().build()) {
String response = client.get("/api/data")
.run()
.assertStatus().is(200) // Assert successful
.getContent().asString();
} catch (RestCallException e) {
System.err.println("HTTP " + e.getResponseCode());
System.err.println(e.getResponseMessage());
}

Request/Response Assertions

client.get("/api/data")
.run()
.assertStatus().is(200)
.assertHeader("Content-Type").is("application/json")
.assertContent().contains("expected");

Performance Characteristics

  • Connection Pooling: Built-in via Apache HttpClient
  • 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

Discussion

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