2013-06-19 10 views
12

Pracuję nad interfejsem REST API. Otrzymanie komunikatu POST ze złym JSON (np. {Sdfasdfasdf}) powoduje, że Spring zwraca domyślną stronę serwera dla błędu 400 nieprawidłowych żądań. Nie chcę zwrócić strony, chcę zwrócić niestandardowy obiekt błędu JSON.Używanie Spring MVC, akceptowanie żądań POST ze złym JSON prowadzi do domyślnej strony 400 serwera kodów błędu, która jest zwracana

Mogę to zrobić, gdy wystąpi wyjątek zgłoszony przez @ExceptionHandler. Więc jeśli jest to puste zapytanie lub pusty obiekt JSON (np. {}), Wygeneruje on wyjątek NullPointerException i będę mógł go złapać za pomocą mojego wyjątkuHandler i robić, co mi się podoba.

Problem polega na tym, że Spring nie rzuca wyjątku, gdy jest to po prostu nieprawidłowa składnia ... przynajmniej nie to, co widzę. To po prostu zwraca domyślną stronę błędu z serwera, czy to Tomcat, Glassfish, itp.

Moje pytanie brzmi: jak mogę "przechwycić" Spring i zmusić go do użycia mojej procedury obsługi wyjątków lub w inny sposób zapobiec wyświetleniu strony błędu wyświetla i zamiast tego zwraca obiekt błędu JSON?

Oto mój kod:

@RequestMapping(value = "/trackingNumbers", method = RequestMethod.POST, consumes = "application/json") 
@ResponseBody 
public ResponseEntity<String> setTrackingNumber(@RequestBody TrackingNumber trackingNumber) { 

    HttpStatus status = null; 
    ResponseStatus responseStatus = null; 
    String result = null; 
    ObjectMapper mapper = new ObjectMapper(); 

    trackingNumbersService.setTrackingNumber(trackingNumber); 
    status = HttpStatus.CREATED; 
    result = trackingNumber.getCompany(); 


    ResponseEntity<String> response = new ResponseEntity<String>(result, status); 

    return response;  
} 

@ExceptionHandler({NullPointerException.class, EOFException.class}) 
@ResponseBody 
public ResponseEntity<String> resolveException() 
{ 
    HttpStatus status = null; 
    ResponseStatus responseStatus = null; 
    String result = null; 
    ObjectMapper mapper = new ObjectMapper(); 

    responseStatus = new ResponseStatus("400", "That is not a valid form for a TrackingNumber object " + 
      "({\"company\":\"EXAMPLE\",\"pro_bill_id\":\"EXAMPLE123\",\"tracking_num\":\"EXAMPLE123\"})"); 
    status = HttpStatus.BAD_REQUEST; 

    try { 
     result = mapper.writeValueAsString(responseStatus); 
    } catch (IOException e1) { 
     e1.printStackTrace(); 
    } 

    ResponseEntity<String> response = new ResponseEntity<String>(result, status); 

    return response; 
} 
+1

Gwint tutaj wyjaśnia, co jest najprawdopodobniej dzieje: http://stackoverflow.com/questions/3230358/spring-3-create-exceptionhandler-for-nosuchrequesthandlingmethodexception Zasadniczo metoda ExceptionHandler odnosi się tylko do RequestMappings w jego własna klasa. W twoim przypadku żądanie nie osiąga żadnych mapowań w tej klasie, ponieważ json jest nieprawidłowy. Użyj HandlerExceptionResolver lub ControllerAdvice, jeśli jesteś na wiosnę 3.2 – Matt

+1

Sprawdź inne pytanie z odpowiedzią, która może ci pomóc - http://stackoverflow.com/questions/17183102/spring3-doesnt-work-valid-when-json-request -i-got-400-bad-request-error/17185583 # 17185583 –

+0

@PavelHoral Oto moja odpowiedź - użycie 'HttpMessageNotReadableException' ale z całą historią tego, jak została dodana i która wersja Spring może być użyta ! – andyb

Odpowiedz

15

ta została podniesiona jako problem ze sprężyną SPR-7439 - JSON (Jackson) @RequestBody marshalling niezręczną rzuca wyjątek - która została ustalona w Spring 3.1M2 poprzez Wiosna rzucać org.springframework.http.converter.HttpMessageNotReadableException w przypadku brakującej lub nieważnej treści wiadomości.

W swoim kodzie nie można utworzyć ResponseStatus, ponieważ jest abstrakcyjny, ale przetestowałem przechwytywanie tego wyjątku za pomocą prostszej metody lokalnie przy pomocy Spring 3.2.0.RELEASE na Jetty 9.0.3.v20130506.

@ExceptionHandler({org.springframework.http.converter.HttpMessageNotReadableException.class}) 
@ResponseStatus(HttpStatus.BAD_REQUEST) 
@ResponseBody 
public String resolveException() { 
    return "error"; 
} 

i otrzymałem odpowiedź "błąd" o statusie 400 błędów.

Usterka została omówiona na this Wiosennego postu na forum.

Uwaga: zacząłem testowanie z Jetty 9.0.0.M4 ale że miał jakieś inne problemy wewnętrzne zatrzymanie @ExceptionHandler ukończeniu, więc w zależności od kontenera (Jetty, Tomcat, inne) wersja może być konieczne, aby uzyskać nowsze Wersja, która ładnie gra z wersją Spring, której używasz.

+1

Edytowane od @PavelHoral wydawało się obrazić jego "osobisty" charakter – andyb

+0

To jest dokładnie to, czego potrzebowałem. Po prostu nie mogłem wiedzieć, który wyjątek został rzucony ... To rozwiązało problem. Dziękuję bardzo! Pomogły mi też linki powyżej Matt's i PavelHoral, pomogły mi zaprojektować czystszą architekturę kontrolera. – UpAllNight

+0

Dobrze słyszeć, że działa! "@ ControllerAdvice" było miłym dodatkiem do Spring 3.2 – andyb

Powiązane problemy