Convenciones de la capa web
La capa web del arquetipo fija decisiones que todos los endpoints comparten: prefijo de versión, headers obligatorios, forma de la respuesta paginada, contrato de validación y forma de los errores. Esta página documenta cada una con el código exacto del arquetipo.
Path y versionado
El prefijo global es API_PATH_PREFIX, definido en utils/constants/ApiConstants:
public static final String API_PATH_PREFIX = "/{apiBasePath}";
{apiBasePath} es una propiedad del arquetipo definida al generar el proyecto.
Los controladores declaran solo la parte versionada del recurso:
@RequestMapping("/v1/tasks")
WebConfig.configurePathMatch antepone el prefijo a todos los controladores del paquete base:
configurer.addPathPrefix(API_PATH_PREFIX, HandlerTypePredicate.forBasePackage("..."));
URL resultante: /{apiBasePath}/v1/{recurso}. Las bumps mayores de contrato suben a /v2, /v3 y conviven con la versión previa hasta deprecación.
Headers globales
Cada operación REST exige los siguientes headers. Las constantes viven en utils/constants/HeaderConstants; OpenAPIConfig.globalHeaderCustomizer los inyecta en cada Operation del documento OpenAPI, así que los controladores no los declaran individualmente.
| Header | Obligatorio | Pattern | Propósito |
|---|---|---|---|
|
Sí |
UUID v4 |
Resuelve el tenant del request. |
|
No |
|
Identifica el dispositivo origen. |
|
No |
|
Plataforma cliente. |
|
No |
|
Aplicación cliente. |
|
Sin |
Paginación
Las queries paginadas reciben un Pageable como último parámetro y devuelven PageResponse<T> (commons/adapter/in/web/PageResponse):
@GetMapping
ResponseEntity<PageResponse<TaskResponse>> list(Pageable pageable) {
Page<Task> page = taskRetrievalPort.findAll(pageable);
return ResponseEntity.ok(PageResponse.of(page.map(TaskResponse::of)));
}
PageResponse.of(Page<T>) aplana metadata y contenido a una forma JSON estable:
{
"page": {
"number": 0,
"size": 20,
"totalElements": 137,
"totalPages": 7,
"empty": false
},
"items": [ /* ... */ ]
}
Los parámetros estándar de Spring (page, size, sort) se aceptan como query params sin configuración adicional.
Validación
El binding usa Bean Validation (jakarta.validation.constraints.*) sobre los DTOs de request, activado por @Valid en el handler:
@PostMapping
ResponseEntity<String> create(@RequestBody @Valid CreateTaskRequest request) { /* ... */ }
Una violación de constraints dispara MethodArgumentNotValidException. GlobalExceptionHandler.handleMethodArgumentNotValid la traduce a HTTP 400 con ProblemDetail y la lista violations:
{
"type": "about:blank",
"title": "Bad Request",
"status": 400,
"detail": "Request validation failed.",
"violations": [
{ "field": "title", "message": "must not be blank" }
]
}
IllegalArgumentException lanzada manualmente (validación que no encaja en una anotación) también mapea a 400 — sin violations, con detail igual al mensaje de la excepción.
Errores
Todas las respuestas de error siguen RFC 7807 (ProblemDetail). El mapeo está en web/advice/GlobalExceptionHandler:
| Origen | Forma |
|---|---|
|
|
|
HTTP 400. |
|
HTTP 400. |
|
HTTP 400. |
|
HTTP 400. |
|
HTTP 409. |
|
HTTP 404. |
|
HTTP 500. |
Para errores de negocio (invariante violada, recurso no encontrado) el patrón es lanzar ApplicationException con un ApplicationError enum específico del aggregate. No subclasear Exception.
Ver también
-
Como crear un endpoint REST — paso a paso de un endpoint nuevo.
-
Como definir un puerto de salida — del otro lado del controller: cómo accede a datos.