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.
Quarkus REST provides type-safe response construction through the RestResponse<T> class and declarative annotations for status codes and headers. These features offer a more concise and type-safe alternative to Jakarta REST's Response class.
import org.jboss.resteasy.reactive.RestResponse;
import org.jboss.resteasy.reactive.RestResponse.ResponseBuilder;
import org.jboss.resteasy.reactive.ResponseStatus;
import org.jboss.resteasy.reactive.ResponseHeader;
import jakarta.ws.rs.core.Response.Status;Type-safe response wrapper that provides compile-time type checking for response entities.
public class RestResponse<T> {
// Factory methods for common responses
public static <T> RestResponse<T> ok(T entity);
public static <T> RestResponse<T> status(Status status);
public static <T> RestResponse<T> status(Status status, T entity);
public static <T> RestResponse<T> status(int status);
public static <T> RestResponse<T> status(int status, T entity);
public static <T> RestResponse<T> notModified();
public static <T> RestResponse<T> noContent();
public static <T> RestResponse<T> accepted();
public static <T> RestResponse<T> accepted(T entity);
public static <T> RestResponse<T> notFound();
// Access response properties
public int getStatus();
public T getEntity();
public <OtherT> OtherT readEntity(Class<OtherT> type);
public boolean hasEntity();
public MultivaluedMap<String, Object> getHeaders();
public String getHeaderString(String name);
// Convert to Jakarta REST Response
public Response toResponse();
// Additional metadata access (inherited from Response)
public MultivaluedMap<String, Object> getMetadata();
public MultivaluedMap<String, String> getStringHeaders();
public MediaType getMediaType();
public Locale getLanguage();
public int getLength();
}Note: RestResponse<T> extends Jakarta REST's Response class and inherits additional methods including getCookies(), getEntityTag(), getDate(), getLastModified(), getLocation(), getLinks(), hasLink(), getLink(), and getLinkBuilder(). Refer to Jakarta REST documentation for complete Response API.
Fluent builder for constructing complex responses.
public static class ResponseBuilder<T> {
// Start builder chain
public static <T> ResponseBuilder<T> ok();
public static <T> ResponseBuilder<T> ok(T entity);
public static <T> ResponseBuilder<T> status(Status status);
public static <T> ResponseBuilder<T> status(int status);
public static <T> ResponseBuilder<T> created(URI location);
public static <T> ResponseBuilder<T> fromResponse(Response response);
// Configure response
public ResponseBuilder<T> status(int status);
public ResponseBuilder<T> status(Status status);
public ResponseBuilder<T> entity(T entity);
public ResponseBuilder<T> header(String name, Object value);
public ResponseBuilder<T> headers(MultivaluedMap<String, Object> headers);
public ResponseBuilder<T> type(MediaType type);
public ResponseBuilder<T> type(String type);
public ResponseBuilder<T> tag(EntityTag tag);
public ResponseBuilder<T> tag(String tag);
public ResponseBuilder<T> lastModified(Date date);
public ResponseBuilder<T> location(URI location);
public ResponseBuilder<T> contentLocation(URI location);
public ResponseBuilder<T> language(String language);
public ResponseBuilder<T> language(Locale language);
public ResponseBuilder<T> cookie(NewCookie... cookies);
public ResponseBuilder<T> expires(Date expires);
// Build response
public RestResponse<T> build();
}@GET
@Path("/{id}")
public RestResponse<Item> get(@RestPath String id) {
Item item = itemService.findById(id);
if (item == null) {
return RestResponse.notFound();
}
return RestResponse.ok(item);
}
@POST
public RestResponse<Item> create(Item item) {
Item created = itemService.create(item);
return RestResponse.status(Status.CREATED, created);
}
@DELETE
@Path("/{id}")
public RestResponse<Void> delete(@RestPath String id) {
itemService.delete(id);
return RestResponse.noContent();
}
@PUT
@Path("/{id}")
public RestResponse<Item> update(@RestPath String id, Item item) {
Item updated = itemService.update(id, item);
return updated != null
? RestResponse.ok(updated)
: RestResponse.notFound();
}@POST
public RestResponse<Item> create(Item item) {
Item created = itemService.create(item);
URI location = URI.create("/items/" + created.getId());
return RestResponse.ResponseBuilder.created(location)
.entity(created)
.header("X-Item-Version", created.getVersion())
.header("X-Created-By", "system")
.build();
}
@GET
@Path("/{id}")
public RestResponse<Item> get(@RestPath String id, @RestHeader String ifNoneMatch) {
Item item = itemService.findById(id);
if (item == null) {
return RestResponse.notFound();
}
String etag = item.getVersion();
if (etag.equals(ifNoneMatch)) {
return RestResponse.notModified();
}
return RestResponse.ResponseBuilder.ok(item)
.tag(etag)
.lastModified(item.getUpdatedAt())
.build();
}
@GET
@Path("/download/{id}")
public RestResponse<byte[]> download(@RestPath String id) {
FileData file = fileService.getFile(id);
return RestResponse.ResponseBuilder.ok(file.getContent())
.type("application/octet-stream")
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"")
.header("Content-Length", file.getSize())
.build();
}@GET
public RestResponse<List<Item>> list() {
List<Item> items = itemService.findAll();
RestResponse<List<Item>> response = RestResponse.ok(items);
// Access response properties
int status = response.getStatus();
List<Item> entity = response.getEntity();
boolean hasEntity = response.hasEntity();
return response;
}
// Read entity as different type
public void processResponse(RestResponse<?> response) {
if (response.hasEntity()) {
String json = response.readEntity(String.class);
// Process JSON string
}
}Sets the HTTP status code declaratively on the resource method.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ResponseStatus {
int value(); // HTTP status code
}Usage:
@POST
@ResponseStatus(201)
public Item create(Item item) {
return itemService.create(item);
}
@DELETE
@Path("/{id}")
@ResponseStatus(204)
public void delete(@RestPath String id) {
itemService.delete(id);
}
@PUT
@Path("/{id}")
@ResponseStatus(202)
public Item updateAsync(@RestPath String id, Item item) {
asyncService.scheduleUpdate(id, item);
return item;
}Adds response headers declaratively. This annotation is repeatable.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(ResponseHeader.List.class)
public @interface ResponseHeader {
String name(); // Header name
String[] value(); // Header value(s)
}Usage:
@GET
@ResponseHeader(name = "X-Total-Count", value = "100")
public List<Item> list() {
return itemService.findAll();
}
@GET
@Path("/{id}")
@ResponseHeader(name = "Cache-Control", value = "max-age=3600")
@ResponseHeader(name = "X-Custom", value = "value")
public Item get(@RestPath String id) {
return itemService.findById(id);
}
@POST
@ResponseStatus(201)
@ResponseHeader(name = "X-Created-By", value = "system")
@ResponseHeader(name = "X-Request-Id", value = "${requestId}")
public Item create(Item item) {
return itemService.create(item);
}RestResponse<T> provides compile-time type safety:
// Type-safe entity access
@GET
@Path("/{id}")
public RestResponse<Item> get(@RestPath String id) {
Item item = itemService.findById(id);
RestResponse<Item> response = RestResponse.ok(item);
// Compile-time checked - entity is Item
Item entity = response.getEntity();
return response;
}
// Contrast with Jakarta REST Response
@GET
@Path("/{id}/legacy")
public Response getLegacy(@RestPath String id) {
Item item = itemService.findById(id);
Response response = Response.ok(item).build();
// Runtime cast required - no compile-time safety
Item entity = (Item) response.getEntity();
return response;
}RestResponse works seamlessly with reactive types:
@GET
@Path("/{id}")
public Uni<RestResponse<Item>> getAsync(@RestPath String id) {
return itemService.findByIdAsync(id)
.map(item -> item != null
? RestResponse.ok(item)
: RestResponse.notFound()
);
}
@POST
public Uni<RestResponse<Item>> createAsync(Item item) {
return itemService.createAsync(item)
.map(created -> RestResponse.status(Status.CREATED, created));
}| Feature | RestResponse<T> | Response |
|---|---|---|
| Type safety | ✅ Compile-time | ❌ Runtime only |
| Entity access | T getEntity() | Object getEntity() (cast required) |
| Factory methods | ✅ Type-safe | ✅ Available |
| Builder pattern | ✅ Type-safe | ✅ Available |
| JAX-RS compatible | ✅ Fully compatible | ✅ Standard |
Both RestResponse and Response are fully supported. RestResponse is recommended for new code due to its type safety benefits.