2015-08-20 19 views
10

Ho una classe annotato con @ControllerAdvice e questo metodo in essa:primavera @ExceptionHandler e HttpMediaTypeNotAcceptableException

@ExceptionHandler(ResourceNotFoundException.class) 
@ResponseStatus(HttpStatus.NOT_FOUND) 
@ResponseBody 
public ExceptionInfo resourceNotFoundHandler(ResourceNotFoundException ex) { 
    List<ErrorContent> errors = new ArrayList<>(); 
    errors.add(new ErrorContent(ExceptionsCodes.NOT_FOUND_CODE, null, 
      "test")); 
    return fillExceptionInfo(HttpStatus.NOT_FOUND, errors, ex); 
} 

Ecco fillExceptionInfo:

public ExceptionInfo fillExceptionInfo(HttpStatus status, List<ErrorContent> errors, 
     Exception ex) { 
    String msg = ex.getMessage(); 

    return new ExceptionInfo(status.toString(), errors, (msg != null && !msg.equals("")) 
      ? ex.getMessage() 
      : ExceptionUtils.getFullStackTrace(ex)); 
} 

Quando un web-client invia una richiesta per alcuni JSON dati, che non possono essere trovati, questo metodo funziona bene. Ma quando il server riceve una richiesta di immagine, invece della mia eccezione viene lanciata una HttpMediaTypeNotAcceptableException. Capisco che ciò avvenga a causa del tipo di contenuto sbagliato, ma come posso risolvere questo problema?

Aggiornamento

Il mio obiettivo è quello di gettare ResourceNotFoundException in entrambi i casi per i dati JSON e per il file.

Eccezione che ottengo (quindi è gettato dal AbstractMessageConverterMethodProcessor):

ERROR o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - doResolveHandlerMethodException - Failed to invoke @ExceptionHandler method: public com.lia.utils.GlobalExceptionHandler$ExceptionInfo com.lia.utils.GlobalExceptionHandler.resourceNotFoundHandler(com.lia.app.controllers.exceptions.ResourceNotFoundException) 
    org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation 
     at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:168) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:101) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:198) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) ~[spring-web-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:362) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:60) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:138) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1167) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1004) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:955) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) [javax.servlet-api-3.1.0.jar:3.1.0] 
     at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [javax.servlet-api-3.1.0.jar:3.1.0] 
     at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:717) [jetty-servlet-9.1.1.v20140108.jar:9.1.1.v20140108] 
     at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1644) [jetty-servlet-9.1.1.v20140108.jar:9.1.1.v20140108] 
.... 
+0

Qual è il tuo obiettivo? Gestire 'HttpMediaTypeNotAcceptableException's o far sì che il metodo lanci un' ResourceNotFoundException' in entrambi i casi? Inoltre, si prega di inviare il metodo che genera l'eccezione. – hzpz

+0

@hzpz Ho aggiornato la mia domanda di conseguenza al tuo commento, per favore guarda le mie modifiche – Lia

risposta

7

Il problema sta nel incompatibilità del tipo di contenuto richiesto e l'oggetto che viene restituito. Vedere my response su come configurare ContentNegotiationConfigurer in modo che Spring determini il tipo di contenuto richiesto in base alle proprie esigenze (guardando l'estensione del percorso, il parametro URL o l'intestazione Accept).

A seconda di come il tipo di contenuto richiesto è determinato, avete seguenti opzioni quando un'immagine è richiesto dal cliente:

  • se il tipo di contenuto richiesto è determinato dalla intestazione Accept, e se il cliente può/desidera gestire una risposta JSON invece dei dati dell'immagine, quindi il client deve inviare la richiesta con Accept: image/*, application/json. In questo modo, Spring sa che può tranquillamente restituire i dati del byte dell'immagine o il messaggio JSON di errore.
  • in ogni altro caso la soluzione migliore è semplicemente restituire un codice di errore HTTP, senza alcun messaggio di errore. È possibile farlo in un paio di modi in vostro controller:

Impostare il codice di errore sulla risposta direttamente

public byte[] getImage(HttpServletResponse resp) { 
    try { 
     // return your image 
    } catch (Exception e) { 
     resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 
    } 
} 

Usa ResponseEntity

public ResponseEntity<?> getImage(HttpServletResponse resp) { 
    try { 
     byte[] img = // your image 
     return ReponseEntity.ok(img); 
    } catch (Exception e) { 
     return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR); 
    } 
} 

Utilizzare un @ExceptionHandler metodo separato in quel controller, che sostituirà la gestione predefinita delle eccezioni Spring. Ciò presuppone che tu abbia o un tipo di eccezione dedicato per le richieste di immagini o un controller separato solo per servire le immagini. In caso contrario, il gestore delle eccezioni gestirà anche le eccezioni da altri endpoint in quel controller.

1

Che aspetto ha la tua classe ExceptionInfo? Mi imbatto in un problema abbastanza simile dopo aver definito alcuni gestori di eccezioni nella classe con annotazione @ControllerAdvice. Quando si è verificata un'eccezione, è stata rilevata, anche se la risposta non è stata restituita e è stato generato org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation.

Ho capito che il problema era causato dal fatto che mi mancava aggiungere metodi getter alla mia classe ErrorResponse.Dopo aver aggiunto metodi getter (questa classe era immutabile, quindi non c'erano metodi setter) tutto funzionava come un incantesimo.

+0

grazie, ma ho getter nel mio ExceptionInfo – Lia

Problemi correlati