2016-04-25 12 views
3

In einer mit JHipster generierten REST-API möchte ich einige 404-Ausnahmen auslösen. Dies wird normalerweise mitHinzufügen einer Nachricht zu einer 404 Not Found-Ausnahme

return new ResponseEntity<>(HttpStatus.NOT_FOUND); 

durchgeführt, was tatsächlich zu einer 404-Antwort auf die xhr-Anforderung führt. Das Problem ist, dass in der Vorderseite, die Antwort mit JHipster

angular.fromJson(result) 
parst

und ein solches Ergebnis ist leer, wenn die tatsächliche Antwort 404 die ist, die der Parse macht auszufallen.

Wenn ich zu einem nicht zugeordneten URI zeigen, lässt /api/user sagen, während mein Controller Karten /api/users (die plurar beachten) die 404 I von der API bekam einen Körper drin:

{ 
    "timestamp": "2016-04-25T18:33:19.947+0000", 
    "status": 404, 
    "error": "Not Found", 
    "message": "No message available", 
    "path": "/api/user/myuser/contact" 
} 

, die korrekt ist parsen in eckigen.

Wie kann ich einen Körper so erstellen? Wird diese Ausnahme vom Frühling geworfen oder ist Tomcat wer wirft es?

Ich versuchte dies: Trigger 404 in Spring-MVC controller?, aber ich kann die Parameter der Antwort nicht einstellen.

Antwort

6

Grundidee


Erste Option ist Fehlerobjekte zu definieren und sie als 404 Not Found Körper zurückzukehren. So etwas wie folgt vor:

Map<String, String> errors = ....; 
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errors); 

Statt einen typischen ResponseEntity zurückzukehren, können Sie einen Exception werfen, die zu einem 404 Not Found gelöst werden. Angenommen, Sie haben ein NotFoundException wie:

@ResponseStatus(code = HttpStatus.NOT_FOUND) 
public class NotFoundException extends RuntimeException {} 

Dann, wenn Sie diese Ausnahme in Ihre Controller werfen, würden Sie so etwas wie sehen:

{ 
    "timestamp":1461621047967, 
    "status":404, 
    "error":"Not Found", 
    "exception":"NotFoundException", 
    "message":"No message available", 
    "path":"/greet" 
} 

Wenn Sie anpassen möchten die Nachricht und andere Teile des Körpers, Sie sollten einen ExceptionHandler für NotFoundException definieren.

Einführung in Ausnahmehierarchien


Wenn Sie eine RESTful-API erstellen möchten und verschiedene Fehlercodes haben und Fehlermeldungen für verschiedene Ausnahmefällen können Sie eine Hierarchie von Ausnahmen erstellen die Vertreter Fälle und extrahieren Sie Nachricht und Code von jedem.

Zum Beispiel können Sie eine Ausnahme einführen, sagen wir APIException, die Superklasse aller anderen Ausnahmen ist, die von Ihren Controllern ausgelöst werden. Diese Klasse definiert einen Code/Nachrichtenpaar wie:

public class APIException extends RuntimeException { 
    private final int code; 
    private final String message; 

    APIException(int code, String message) { 
     this.code = code; 
     this.message = message; 
    } 

    public int code() { 
     return code; 
    } 

    public String message() { 
     return message; 
    } 
} 

Jede Unterklasse von der Art seiner Ausnahme je können einige sinnvolle Werte für dieses Paar liefern.

@ResponseStatus(code = HttpStatus.BAD_REQUEST) 
public class InvalidStateException extends APIException { 
    public InvalidStateException() { 
     super(1, "Application is in invalid state"); 
    } 
} 

Oder dass berüchtigt nicht gefunden diejenigen: Zum Beispiel könnten wir eine InvalidStateException haben

@ResponseStatus(code = HttpStatus.NOT_FOUND) 
public class SomethingNotFoundException extends APIException { 
    public SomethingNotFoundException() { 
     super(2, "Couldn't find something!"); 
    } 
} 

Dann sollten wir eine ErrorController definieren, die diese Ausnahmen und machen sie zu sinnvollen JSON Darstellungen fängt. Dieser Fehler Controller aussehen kann wie folgt vor:

@RestController 
public class APIExceptionHandler extends AbstractErrorController { 
    private static final String ERROR_PATH = "/error"; 
    private final ErrorAttributes errorAttributes; 

    @Autowired 
    public APIExceptionHandler(ErrorAttributes errorAttributes) { 
     super(errorAttributes); 
     this.errorAttributes = errorAttributes; 
    } 

    @RequestMapping(path = ERROR_PATH) 
    public ResponseEntity<?> handleError(HttpServletRequest request) { 
     HttpStatus status = getStatus(request); 

     Map<String, Object> errors = getErrorAttributes(request, false); 
     getApiException(request).ifPresent(apiError -> { 
      errors.put("message" , apiError.message()); 
      errors.put("code", apiError.code()); 
     }); 
     // If you don't want to expose exception! 
     errors.remove("exception"); 


     return ResponseEntity.status(status).body(errors); 
    } 

    @Override 
    public String getErrorPath() { 
     return ERROR_PATH; 
    } 

    private Optional<APIException> getApiException(HttpServletRequest request) { 
     RequestAttributes attributes = new ServletRequestAttributes(request); 
     Throwable throwable = errorAttributes.getError(attributes); 
     if (throwable instanceof APIException) { 
      APIException exception = (APIException) throwable; 
      return Optional.of(exception); 
     } 

     return Optional.empty(); 
    } 
} 

Also, wenn Sie einen SomethingNotFoundException werfen, würde die zurück JSON wie:

{ 
    "timestamp":1461621047967, 
    "status":404, 
    "error":"Not Found", 
    "message":"Couldn't find something!", 
    "code": 2, 
    "path":"/greet" 
} 
+0

Vielen Dank Ali, aber auf diese Weise kann ich die Nachricht nicht definieren. Ich habe versucht, die Ursache Eigenschaft wie in @ResponseStatus (Wert = HttpStatus.NOT_FOUND, Grund = "Ressource nicht gefunden") hinzufügen, aber dann ist die Antwort so etwas wie {"Nachricht": "error.404", "Beschreibung": "Ressource nicht gefunden“, "fieldErrors": null} – luso

+0

Durch die Art, wie ich es auf diese Weise werfen Rückkehr Optional.ofNullable (entity) .map (Ergebnis -> neues ResponseEntity <> ( Ergebnis HttpStatus.OK)) .orElseThrow (HTTPNotFoundException :: new); – luso

+0

Vielleicht hilft update ... –

0

Ich denke, Sie können dies tun, wenn Sie eine Nachricht zurückkehren möchten oder testen Sie mit Ihrem Fehlercode

@ResponseBody 
public ResponseEntity somthing() { 
HttpHeaders headers = new HttpHeaders(); 
headers.add("Content-Type", "application/json; charset=utf-8"); 
return new ResponseEntity<>(new Gson().toJson("hello this is my message"), headers, HttpStatus.NOT_FOUND); 
}