Dieses Blog durchsuchen

Freitag, 6. Januar 2017

REST Service Exception Handling


Bei der Implementierung von REST-Services stellt sich der Entwickler früher oder später die Frage, wie eigentlich mit Exceptions umgegangen werden soll. Denn anders als bei der Implementierung von SOAP Services muss sich der Entwickler hier eine eigene Strategie überlegen, wie aufgetretene Fehler dem nutzenden System übermittelt werden sollen.

An dieser Stelle möchte ich eine Variante aus der Praxis vorstellen, die sich bewährt hat. Und zwar wird dazu die Klasse javax.ws.rs.ext.ExceptionMapper implementiert und mit der @Provider Annotation versehen. Eine weitergehende Konfiguration oder Aktivierung des Mappers ist nicht notwendig. Indem nun die Methode toResponse überschrieben wird, kann definiert werden, wie die Antwort des Servers im Falle einer Exception konkret aussehen soll.

Das Beispiel zeigt den Aufbau einer Nachricht bestehend aus einleitendem Text "An Error occured!", dem aktuellen Datum, dem Namen der Exception-Klasse und der Nachricht. Falls die Exception einen root cause hat, wird auch dieser noch mit ausgegeben.
Zusätzlich ist es sinnvoll, einen passenden HTTP-Status-Code mitzugeben, in diesem Fall Status Code 500 für "Internal Server Error", denn viele Clients fragen diesen Status-Code ab, um entsprechend reagieren zu können.

@Provider
public class RestThrowableExceptionMapper implements ExceptionMapper<Throwable> {

    @Context
    private HttpHeaders headers;

    @Override
    public Response toResponse(Throwable throwable) {
        int status = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); //defaults to internal server error 500;
        StringBuilder messageBuilder = new StringBuilder();
        messageBuilder.append("An Error occured! ");
        messageBuilder.append(new Date());
        messageBuilder.append(": ");
        messageBuilder.append("Cause -> ");
        messageBuilder.append(throwable.getClass().getName());
        messageBuilder.append(": ");
        messageBuilder.append(throwable.getMessage());
        // also append root cause of exception if present
        Throwable rootCause = ExceptionUtils.getRootCause(throwable);
        if (rootCause != null) {
            messageBuilder.append("; Root Cause -> ");
            messageBuilder.append(rootCause.getClass().getName());
            messageBuilder.append(": ");
            messageBuilder.append(rootCause.getMessage());
        }
        return Response.status(status).
               entity(messageBuilder.toString()).
               type(headers.getMediaType()).build();
    }
}

Keine Kommentare:

Kommentar posten