docs
reference
tessl install tessl/maven-io-quarkus--quarkus-resteasy-reactive@3.15.0A Jakarta REST implementation utilizing build time processing and Vert.x for high-performance REST endpoints with reactive capabilities in cloud-native environments.
Learn how to build type-safe, declarative REST clients with Quarkus.
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-reactive</artifactId>
</dependency>import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
@Path("/api/users")
@RegisterRestClient(configKey = "user-api")
public interface UserClient {
@GET
@Path("/{id}")
Uni<User> getUser(@PathParam("id") Long id);
@GET
Uni<List<User>> listUsers();
@POST
Uni<User> createUser(User user);
@DELETE
@Path("/{id}")
Uni<Void> deleteUser(@PathParam("id") Long id);
}# Base URL
quarkus.rest-client.user-api.url=https://api.example.com
# Timeouts
quarkus.rest-client.user-api.connect-timeout=5000
quarkus.rest-client.user-api.read-timeout=30000@Inject
@RestClient
UserClient userClient;
@GET
@Path("/users/{id}")
public Uni<User> getUser(@RestPath Long id) {
return userClient.getUser(id);
}UserClient client = QuarkusRestClientBuilder.newBuilder()
.baseUri(URI.create("https://api.example.com"))
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build(UserClient.class);
Uni<User> user = client.getUser(123L);@GET
@Path("/search")
@ClientQueryParam(name = "api_key", value = "${api.key}")
@ClientQueryParam(name = "version", value = "2")
Uni<List<Result>> search(@QueryParam("q") String query);@GET
@Path("/search")
Uni<List<Result>> search(
@QueryParam("q") String query,
@QueryParam("page") int page,
@QueryParam("size") int size
);@GET
@Path("/data")
@ClientHeaderParam(name = "X-API-Key", value = "${api.key}")
@ClientHeaderParam(name = "User-Agent", value = "MyApp/1.0")
Uni<Data> getData();@GET
@Path("/data")
Uni<Data> getData(@HeaderParam("Authorization") String token);@ApplicationScoped
public class AuthHeaderFactory extends ReactiveClientHeadersFactory {
@Inject
TokenService tokenService;
@Override
public Uni<MultivaluedMap<String, String>> getHeaders(
MultivaluedMap<String, String> incomingHeaders,
MultivaluedMap<String, String> clientOutgoingHeaders
) {
return tokenService.getTokenAsync()
.map(token -> {
MultivaluedMap<String, String> headers = new MultivaluedHashMap<>();
headers.add("Authorization", "Bearer " + token);
return headers;
});
}
}
@RegisterRestClient
@RegisterProvider(AuthHeaderFactory.class)
public interface SecureApiClient {
@GET
@Path("/data")
Uni<Data> getData();
}@RegisterRestClient
@ClientBasicAuth(username = "${api.username}", password = "${api.password}")
public interface SecureClient {
@GET
@Path("/data")
Uni<Data> getData();
}@GET
@Path("/data")
Uni<Data> getData(@HeaderParam("Authorization") String bearerToken);
// Usage
String token = "Bearer " + tokenService.getToken();
client.getData(token);@RegisterRestClient
public interface ApiClient {
@GET
@Path("/users/{id}")
Uni<User> getUser(@PathParam("id") Long id);
@ClientExceptionMapper
static RuntimeException toException(Response response) {
if (response.getStatus() == 404) {
return new UserNotFoundException();
}
if (response.getStatus() == 401) {
return new UnauthorizedException();
}
return new ApiException("HTTP " + response.getStatus());
}
}@GET
@Path("/users/{id}")
public Uni<RestResponse<User>> getUser(@RestPath Long id) {
return userClient.getUser(id)
.onItem().transform(user -> RestResponse.ok(user))
.onFailure(UserNotFoundException.class)
.recoverWithItem(RestResponse.status(404, "User not found"));
}@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
Uni<UploadResponse> upload(ClientMultipartForm form);
// Usage
ClientMultipartForm form = ClientMultipartForm.create()
.attribute("description", "My file", null)
.binaryFileUpload("file", "document.pdf",
"/path/to/file.pdf", "application/pdf");
Uni<UploadResponse> response = client.upload(form);quarkus.rest-client.user-api.trust-store=/path/to/truststore.jks
quarkus.rest-client.user-api.trust-store-password=password
quarkus.rest-client.user-api.verify-host=trueKeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("truststore.jks"),
"password".toCharArray());
ApiClient client = QuarkusRestClientBuilder.newBuilder()
.baseUri(URI.create("https://secure-api.example.com"))
.trustStore(trustStore, "password")
.verifyHost(true)
.build(ApiClient.class);quarkus.rest-client.user-api.proxy-address=proxy.corp.com:8080
quarkus.rest-client.user-api.proxy-user=proxyuser
quarkus.rest-client.user-api.proxy-password=proxypass
quarkus.rest-client.user-api.non-proxy-hosts=localhost@GET
@Path("/{id}")
public Uni<User> getUser(@RestPath Long id) {
return userClient.getUser(id)
.onFailure().retry().atMost(3)
.onFailure().retry().withBackOff(Duration.ofSeconds(1));
}@GET
@Path("/{id}")
public Uni<User> getUser(@RestPath Long id) {
return userClient.getUser(id)
.ifNoItem().after(Duration.ofSeconds(5))
.fail();
}@QuarkusTest
@QuarkusTestResource(WireMockTestResource.class)
class UserClientTest {
@Inject
@RestClient
UserClient userClient;
@Test
void testGetUser() {
// Setup WireMock stub
stubFor(get(urlEqualTo("/api/users/1"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{\"id\":1,\"name\":\"John\"}")));
// Test
User user = userClient.getUser(1L).await().indefinitely();
assertEquals("John", user.name);
}
}Uni or Multi