feat: add new generic response

This commit is contained in:
2026-09-15 21:39:24 +07:00
parent a8a1dca641
commit beed75a9bf
5 changed files with 89 additions and 27 deletions
@@ -1,17 +0,0 @@
package aplp.backend.core.common.response;
import java.time.Instant;
public record ApiError(
Instant timestamp,
int status,
String error,
String code,
String message,
String traceId
) {
public static ApiError of(int status, String error, String code, String message, String traceId) {
return new ApiError(Instant.now(), status, error, code, message, traceId);
}
}
@@ -0,0 +1,28 @@
package aplp.backend.core.common.response;
import java.time.Instant;
public record ApiResponse<T>(
boolean success,
String code,
String message,
T data,
Instant timestamp,
String traceId
) {
public static <T> ApiResponse<T> ok(T data) {
return new ApiResponse<>(true, "OK", "Success", data, Instant.now(), null);
}
public static <T> ApiResponse<T> ok(String message, T data) {
return new ApiResponse<>(true, "OK", message, data, Instant.now(), null);
}
public static <T> ApiResponse<T> error(String code, String message) {
return new ApiResponse<>(false, code, message, null, Instant.now(), null);
}
public static <T> ApiResponse<T> error(String code, String message, String traceId) {
return new ApiResponse<>(false, code, message, null, Instant.now(), traceId);
}
}
@@ -1,10 +0,0 @@
package aplp.backend.core.common.response;
import java.time.LocalDateTime;
public record ErrorResponse(
int status,
String message,
LocalDateTime timestamp
) {
}
@@ -0,0 +1,16 @@
package aplp.backend.core.common.response;
import java.util.List;
public record PagedResponse<T>(
List<T> content,
int page,
int size,
long totalElements,
int totalPages
) {
public static <T> PagedResponse<T> of(List<T> content, int page, int size, long totalElements) {
int totalPages = size <= 0 ? 0 : (int) Math.ceil((double) totalElements / size);
return new PagedResponse<>(content == null ? List.of() : List.copyOf(content), page, size, totalElements, totalPages);
}
}
@@ -0,0 +1,45 @@
package aplp.backend.core.common.response;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class ApiResponseTest {
@Test
void ok_wrapsDataWithSuccessTrue() {
ApiResponse<String> res = ApiResponse.ok("hello");
assertTrue(res.success());
assertEquals("OK", res.code());
assertNotNull(res.message());
assertEquals("hello", res.data());
assertNotNull(res.timestamp());
assertNull(res.traceId());
}
@Test
void error_wrapsCodeWithoutData() {
ApiResponse<String> res = ApiResponse.error("USER_NOT_FOUND", "User not found");
assertFalse(res.success());
assertEquals("USER_NOT_FOUND", res.code());
assertEquals("User not found", res.message());
assertNull(res.data());
assertNotNull(res.timestamp());
}
@Test
void pagedResponse_computesTotalPages() {
PagedResponse<String> page = PagedResponse.of(List.of("a", "b"), 0, 10, 25);
assertEquals(3, page.totalPages());
assertEquals(2, page.content().size());
ApiResponse<PagedResponse<String>> res = ApiResponse.ok(page);
assertTrue(res.success());
assertEquals(3, res.data().totalPages());
}
}