Saveendra Ekanayake
He escrito una aplicación REST simple en Spring Boot
(Spring
Estructura).
Vuelve ResponseEntity<Success>
como Éxito respuesta en el nivel del controlador. Pero quiero volver de una manera completamente diferente. Error respuesta ResponseEntity<Error>
si hay un error (error de validación, error de lógica, error de tiempo de ejecución) en la API.
Éxito & Error las respuestas son completamente diferentes para la aplicación.
Success
& Error
son las 2 clases java que la aplicación utiliza para representar Éxito & Error respuestas
¿Cuál es la mejor manera de devolver diferentes tipos de ResponseEntity
en Spring-Boot
(La mejor manera de manejar los errores para REST con Spring
)?
marco normando
Recomiendo usar Spring’s @ControllerAdvice
para manejar errores. Leer esta guía para una buena introducción, comenzando en la sección denominada “Manejo de errores de Spring Boot”. Para una discusión en profundidad, hay un artículo en el blog Spring.io que se actualizó en abril de 2018.
Un breve resumen de cómo funciona esto:
- Su método de controlador solo debe devolver
ResponseEntity<Success>
. No será responsable de devolver respuestas de error o excepción. - Implementará una clase que maneje excepciones para todos los controladores. Esta clase se anotará con
@ControllerAdvice
- Esta clase de consejos de controlador contendrá métodos anotados con
@ExceptionHandler
- Cada método de manejo de excepciones se configurará para manejar uno o más tipos de excepciones. Estos métodos son donde especifica el tipo de respuesta para los errores.
- Para su ejemplo, declararía (en la clase de consejos del controlador) un método de manejo de excepciones para el error de validación. El tipo de devolución sería
ResponseEntity<Error>
Con este enfoque, solo necesita implementar el manejo de excepciones de su controlador en un solo lugar para todos los puntos finales en su API. También facilita que su API tenga una estructura de respuesta de excepción uniforme en todos los puntos finales. Esto simplifica el manejo de excepciones para sus clientes.
-
Este es el estándar y debería ser la respuesta aceptada de la OMI.
– Honza Zidek
14/09/2018 a las 15:15
-
¿Qué pasa con el hecho de que no se recomienda manejar el flujo de aplicación esperado a través de Excepciones en Java? Por ejemplo, getCustomerForIBAN devuelve un Opcional expuesto a través de una API REST
GET /api/customer/{iban}
que devuelve 200 ok o 404 no encontrado? ¿Aconsejaría lanzar una excepción y manejarla de la misma manera?– LucasSolar
18/07/2019 a las 20:55
-
Si desea evitar el uso de excepciones en Java, puede diseñar su método de controlador para que devuelva un
ResponseEntity
.ResponseEntity
le permite controlar el código de estado HTTP que se devuelve, y es un tipo genérico para que pueda devolver cualquier estructura de objeto. Aquí hay una explicación sobre cómo usarlo: baeldung.com/spring-response-entity– Marcos normando
19 de julio de 2019 a las 14:46
-
¿Es este realmente el estándar para manejar “errores de validación”? Los errores de validación están destinados a ser un flujo controlado en su capa de servicio (presumiblemente). ¿Por qué dejaríamos que una Excepción subiera al nivel del Controlador sin manejar? Entiendo las excepciones inesperadas (es decir, los códigos de error 5xx), pero no las de validación (4xx). ¿Me estoy perdiendo de algo?
– taylorcressy
7 julio 2020 a las 22:17
-
Este es el estándar para manejar errores que otras capas de la aplicación permiten propagar o lanzar explícitamente. RE: errores de validación, la capa de servicio aún puede detectar y manejar. Fui demasiado restrictivo cuando dije “manejar errores de validación” en la primera oración. Eliminé “validación” para indicar que esto es para errores en general. Gracias por señalar eso.
– Marcos normando
7 julio 2020 a las 23:49
Saravana
Puede devolver un comodín genérico <?>
regresar Success
y Error
en un mismo método de asignación de solicitudes
public ResponseEntity<?> method() {
boolean b = // some logic
if (b)
return new ResponseEntity<Success>(HttpStatus.OK);
else
return new ResponseEntity<Error>(HttpStatus.CONFLICT); //appropriate error code
}
@Mark Norman respuesta es el enfoque correcto
-
Su único caso es que las herramientas de calidad de código (como Sonar Lint) marcan esta práctica de codificación con Los tipos de comodines genéricos no deben usarse en los parámetros de retorno (squid:S1452)
– Sabir Kan
12 de octubre de 2017 a las 4:05
-
Esto es más bien un cortar a tajos cómo eludir el mecanismo (imperfecto) de los genéricos de Java. La respuesta de @ MarkNorman es la estándar y debería ser la aceptada.
– Honza Zidek
14 de septiembre de 2018 a las 15:19
-
Acabo de encontrarme con el mismo problema y estoy buscando crear algo que funcione con VAVR
Either
para que yo pudiera tener unpublic ResponseEntity<Either<Error, Success>> method()
o mejor unpublic Either<ResponseEntity<Error>, ResponseEntity<Success>> method()
. Creo que la forma de hacerlo sería crear unHttpMessageConverter
eso sabría cómo manejar eso y simplemente convertiría el lado izquierdo/derecho y dejaría que suceda el procesamiento normal… de esa manera podría señalar mis estados válidos sin usar excepciones… ¿alguna idea sobre esto?–Dominik Dorn
3 de febrero de 2019 a las 16:58
-
¿Hay alguna forma de convertir un genérico comodín en un genérico específico?
– Daniel Pablo
31 de mayo de 2022 a las 7:44
Sathiamoorthy
primavera 2 introducido ResponseStatusExceptionResponseStatusException usando esto puedes devolver Cadena, código de estado HTTP diferente, DTO en el Mismo tiempo.
@PostMapping("/save")
public ResponseEntity<UserDto> saveUser(@RequestBody UserDto userDto) {
if(userDto.getId() != null) {
throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE,"A new user cannot already have an ID");
}
return ResponseEntity.ok(userService.saveUser(userDto));
}
Maulik Patel
no estoy seguro, pero creo que puedes usar @ResponseEntity
y @ResponseBody
y enviar 2 diferentes uno es Éxito y el segundo es un mensaje de error como:
@RequestMapping(value ="/book2", produces =MediaType.APPLICATION_JSON_VALUE )
@ResponseBody
Book bookInfo2() {
Book book = new Book();
book.setBookName("Ramcharitmanas");
book.setWriter("TulasiDas");
return book;
}
@RequestMapping(value ="/book3", produces =MediaType.APPLICATION_JSON_VALUE )
public ResponseEntity<Book> bookInfo3() {
Book book = new Book();
book.setBookName("Ramayan");
book.setWriter("Valmiki");
return ResponseEntity.accepted().body(book);
}
Para más detalles, consulte esto:
http://www.concretepage.com/spring-4/spring-4-mvc-jsonp-example-with-rest-responsebody-responseentity
Puede usar un mapa con su objeto o cadena como a continuación:
@RequestMapping(value = "/path",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<Map<String,String>> getData(){
Map<String,String> response = new HashMap<String, String>();
boolean isValid = // some logic
if (isValid){
response.put("ok", "success saving data");
return ResponseEntity.accepted().body(response);
}
else{
response.put("error", "an error expected on processing file");
return ResponseEntity.badRequest().body(response);
}
}
María Inés Parnisari
Aquí hay una manera en que lo haría:
public ResponseEntity < ? extends BaseResponse > message(@PathVariable String player) { //REST Endpoint.
try {
Integer.parseInt(player);
return new ResponseEntity < ErrorResponse > (new ErrorResponse("111", "player is not found"), HttpStatus.BAD_REQUEST);
} catch (Exception e) {
}
Message msg = new Message(player, "Hello " + player);
return new ResponseEntity < Message > (msg, HttpStatus.OK);
}
@RequestMapping(value = "/getAll/{player}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity < List < ? extends BaseResponse >> messageAll(@PathVariable String player) { //REST Endpoint.
try {
Integer.parseInt(player);
List < ErrorResponse > errs = new ArrayList < ErrorResponse > ();
errs.add(new ErrorResponse("111", "player is not found"));
return new ResponseEntity < List < ? extends BaseResponse >> (errs, HttpStatus.BAD_REQUEST);
} catch (Exception e) {
}
Message msg = new Message(player, "Hello " + player);
List < Message > msgList = new ArrayList < Message > ();
msgList.add(msg);
return new ResponseEntity < List < ? extends BaseResponse >> (msgList, HttpStatus.OK);
}
KARTHIKEYAN.A
También puede implementar de esta manera para devolver el éxito y el error en un mismo método de asignación de solicitud, use la clase de objeto (clase principal de cada clase en Java): –
public ResponseEntity< Object> method() {
boolean b = // logic here
if (b)
return new ResponseEntity< Object>(HttpStatus.OK);
else
return new ResponseEntity< Object>(HttpStatus.CONFLICT); //appropriate error code
}
Una solución es usar
ResponseEntity<Object>
. Otra es usar una BaseClass o Interface para los tipos Success y Error.– Jens
30 de junio de 2016 a las 8:28
¿No podrías simplemente regresar?
ResponseEntity
en tu definición de método? ` public ResponseEntity myControllerMethod(…) y devuelve unResponseEntity<Success>
o unResponseEntity<Error>
– J. Mengelle
30 de junio de 2016 a las 8:40
ResponseEntity<Either<Error, Success>>
sería bueno, si pudiera implementar la estructura de datos en java– Ali Dehgani
30 de junio de 2016 a las 13:08