The Jersey Client API is the reference implementation of the JAX-RS 2.x/3.x client specification. It provides a fluent, type-safe way to consume REST endpoints from any Java application — no framework required beyond Jersey itself. In this guide you will learn how to perform every HTTP method, pass headers and query parameters, consume and produce JSON, add Basic and Bearer token authentication, and handle errors gracefully.
Maven Dependencies
<!-- Jersey client + Jackson JSON provider -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>3.1.5</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>3.1.5</version>
</dependency>
<!-- Required HK2 injection bridge -->
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>3.1.5</version>
</dependency>
Creating a Client Instance
A Client instance is expensive to create — create it once and reuse it across requests, just like a connection pool:
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.MediaType;
// Create once, reuse everywhere
Client client = ClientBuilder.newClient();
// Register Jackson for JSON
Client jsonClient = ClientBuilder.newBuilder()
.register(org.glassfish.jersey.jackson.JacksonFeature.class)
.build();
// Remember to close when done (e.g. app shutdown)
// client.close();
GET Request — Retrieve a Resource
import jakarta.ws.rs.client.*;
import jakarta.ws.rs.core.*;
public class GetExample {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
// Simple GET — returns plain String
String body = client
.target("https://jsonplaceholder.typicode.com")
.path("/posts/{id}")
.resolveTemplate("id", 1) // replaces {id} with 1
.request(MediaType.APPLICATION_JSON)
.get(String.class);
System.out.println(body);
// GET with query parameters
Response response = client
.target("https://jsonplaceholder.typicode.com/posts")
.queryParam("userId", 1)
.queryParam("_limit", 5)
.request(MediaType.APPLICATION_JSON)
.get();
System.out.println("Status : " + response.getStatus());
System.out.println("Body : " + response.readEntity(String.class));
response.close();
client.close();
}
}
POST Request — Create a Resource
import jakarta.ws.rs.client.*;
import jakarta.ws.rs.core.*;
public class PostExample {
record Post(int userId, String title, String body) {}
public static void main(String[] args) {
Client client = ClientBuilder.newBuilder()
.register(org.glassfish.jersey.jackson.JacksonFeature.class)
.build();
Post newPost = new Post(1, "Jersey Client Tutorial", "Learn Jersey client step by step.");
Response response = client
.target("https://jsonplaceholder.typicode.com/posts")
.request(MediaType.APPLICATION_JSON)
.post(Entity.json(newPost)); // serialises record to JSON
System.out.println("Created: HTTP " + response.getStatus()); // 201
System.out.println(response.readEntity(String.class));
response.close();
client.close();
}
}
PUT and DELETE Requests
// PUT — full update
Response putResp = client
.target("https://jsonplaceholder.typicode.com/posts/1")
.request(MediaType.APPLICATION_JSON)
.put(Entity.json(new Post(1, "Updated Title", "Updated body.")));
System.out.println("PUT: HTTP " + putResp.getStatus()); // 200
putResp.close();
// PATCH — partial update
Response patchResp = client
.target("https://jsonplaceholder.typicode.com/posts/1")
.request(MediaType.APPLICATION_JSON)
.method("PATCH", Entity.json("{"title":"Patched title"}"));
System.out.println("PATCH: HTTP " + patchResp.getStatus());
patchResp.close();
// DELETE
Response deleteResp = client
.target("https://jsonplaceholder.typicode.com/posts/1")
.request()
.delete();
System.out.println("DELETE: HTTP " + deleteResp.getStatus()); // 200
deleteResp.close();
Adding Request Headers
Response resp = client
.target("https://api.example.com/data")
.request(MediaType.APPLICATION_JSON)
.header("X-Request-ID", "abc-123") // custom header
.header("Accept-Language", "en-US") // locale hint
.header("Authorization", "Bearer eyJ...")
.get();
Authentication
import java.nio.charset.StandardCharsets;
import java.util.Base64;
// HTTP Basic Auth
String credentials = Base64.getEncoder()
.encodeToString("alice:s3cr3t".getBytes(StandardCharsets.UTF_8));
Response basicResp = client
.target("https://api.example.com/secure")
.request()
.header("Authorization", "Basic " + credentials)
.get();
// Bearer Token (JWT)
String jwt = "eyJhbGciOiJIUzI1NiJ9...";
Response jwtResp = client
.target("https://api.example.com/secure")
.request()
.header("Authorization", "Bearer " + jwt)
.get();
Error Handling
import jakarta.ws.rs.core.Response.Status.Family;
public static void safeGet(Client client, String url) {
Response response = client
.target(url)
.request(MediaType.APPLICATION_JSON)
.get();
try {
if (response.getStatusInfo().getFamily() == Family.SUCCESSFUL) {
System.out.println("OK: " + response.readEntity(String.class));
} else if (response.getStatus() == 404) {
System.out.println("Resource not found: " + url);
} else if (response.getStatus() == 401) {
System.out.println("Unauthorized — check credentials");
} else {
System.out.println("Error HTTP " + response.getStatus() +
": " + response.readEntity(String.class));
}
} finally {
response.close(); // always close to return connection to pool
}
}
Configuring Timeouts
import java.util.concurrent.TimeUnit;
import org.glassfish.jersey.client.ClientProperties;
Client client = ClientBuilder.newBuilder()
.connectTimeout(5, TimeUnit.SECONDS) // fail-fast if server unreachable
.readTimeout(30, TimeUnit.SECONDS) // max wait for response body
.build();
Method Quick Reference
| Method | Jersey Call | Typical Status |
|---|---|---|
| GET | .get() / .get(Type.class) | 200 |
| POST | .post(Entity.json(obj)) | 201 |
| PUT | .put(Entity.json(obj)) | 200 |
| PATCH | .method("PATCH", Entity.json(obj)) | 200 |
| DELETE | .delete() | 200 / 204 |
| HEAD | .head() | 200 (no body) |
| OPTIONS | .options() | 200 |
See Also
- Secure Your Jersey REST APIs – Authentication & Authorization Guide
- Jersey REST API – Complete File Upload Example
- Handling Exceptions in JAX-RS Jersey
- Building a REST API with Spring Boot
Conclusion
The Jersey Client API’s fluent builder pattern makes consuming REST services clean and readable. Create one Client instance per application, configure connect and read timeouts upfront, always close Response objects in a finally block or try-with-resources, and register JacksonFeature once for automatic JSON serialisation. These habits keep your REST client performant and leak-free in production.