Verwenden von Spring Boot für Restful Web Services.Spring Boot - Globaler benutzerdefinierter Ausnahmebehandlungsmechanismus mit RestControllerAdvice
Es wird versucht, einen globalen benutzerdefinierten Ausnahmebehandlungsmechanismus einzurichten, der auf @RestControllerAdvice basiert, der bekannte, aber auch unbekannte Ausnahmen behandeln kann.
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<repositories>
<repository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
GlobalControllerExceptionHandler:
@RestControllerAdvice
public class GlobalControllerExceptionHandler {
private static final Logger LOG = Logger.getLogger(GlobalControllerExceptionHandler.class);
@ExceptionHandler(value = { ConstraintViolationException.class })
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ApiErrorResponse constraintViolationException(ConstraintViolationException ex) {
LOG.error(ex.getCause().toString());
return new ApiErrorResponse(400, "Bad Request");
}
@ExceptionHandler(value = { NoHandlerFoundException.class })
@ResponseStatus(HttpStatus.NOT_FOUND)
public ApiErrorResponse noHandlerFoundException(Exception ex) {
LOG.error(ex.getCause().toString());
return new ApiErrorResponse(404, "Resource Not Found");
}
@ExceptionHandler(value = { Exception.class })
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ApiErrorResponse unknownException(Exception ex) {
LOG.error(ex.getCause().toString());
return new ApiErrorResponse(500, "Internal Server Error");
}
}
ApiErrorResponse:
public class ApiErrorResponse {
private int status;
private String message;
public ApiErrorResponse(int status, String message) {
this.status = status;
this.message = message;
}
public int getStatus() {
return status;
}
public String getMessage() {
return message;
}
@Override
public String toString() {
return new ToStringBuilder(this).append(status)
.append(message)
.toString();
}
}
Das Problem dabei ist, wenn ich eine 3rd-Party-Bibliothek verwenden, um etwas zu tun, die Eine unbekannte Ausnahme könnte ein 404 sein, wird aber als 500 zurückgegeben!
z.B. Mit Elasticsearch mit einem unbekannten Index (absichtlich Art von Ausnahme zu sehen):
{
"timestamp": 15,
"status": 500,
"error": "Internal Server Error",
"exception": "org.elasticsearch.client.ResponseException",
"message": "POST http://localhost:9200/fn3r4343/_search?pretty=true: HTTP/1.1 404 Not Found"
{
"error": {
"root_cause": [
{
"type": "index_not_found_exception",
"reason": "no such index",
"resource.type": "index_or_alias",
"resource.id": "fn3r4343",
"index_uuid": "_na_",
"index": "fn3r4343"
}
],
"type": "index_not_found_exception",
"reason": "nosuchindex",
"resource.type": "index_or_alias",
"resource.id": "fn3r4343",
"index_uuid": "_na_",
"index": "fn3r4343"
}
{ "root_cause" :
[
{
"type" :"index_not_found_exception",
"reason" : no such index", "resource.type" : "index_or_alias",
"resource.id" : "fn3r4343",
"index_uuid" : "_na_",
"index" : "fn3r4343"
}
],
[
{
"type" : "index_not_found_exception",
"reason" : "no such index",
"resource.type" : "index_or_alias",
"resource.id" : "fn3r4343",
"index_uuid" : "_na_",
"index" : "fn3r4343"
},
"status": 404
]
}
"path": "/myapp/search"
}
Wie man sehen kann, gibt diese als HTTP 500-Status, aber in der Nutzlast sein wirklich HTTP 404!
Was ich suche zurückzukehren, ist dies:
{
"message" : "Index Not Found Exception",
"status" : "HTTP 404"
}
Und für bekannte HTTP 404 Ausnahmen:
Gibt es eine gute Praxis/Mechanismus RestControllerAdvice zu verwenden, jede Art zu fangen von Ausnahme und Anpassung der Antwort in ein JSON-Format, das für einen Client, der die REST-API verwendet, lesbar/nützlich ist?
Dieser Beitrag zu Elasticsearch nicht wirklich spezifisch ist, sondern sucht, wie durch den Versuch @RestControllerAdvice zu verwenden, jede Art von Ausnahme zu behandeln für eine Client-Anwendung die richtige Antwort setzen ...
Danke @Val ... Ich verwende den Low-Level-REST-Client. Ihre Lösung hat mir sehr geholfen, aber wie kann ich die eigentliche Exception-Nachricht erhalten? Übrigens, wir kennen uns von der Java Ranch, Prost! –