2017-02-26 20 views
2

Spring MVCアプリケーションでは、レスポンスによってクライアントに転送された例外を処理しようとしていますが、実際の解決策が見つかりません。クライアントサイドでのREST例外の処理

サーバ側制御装置:

@RestController 
public class MessageProducerController { 

    @Autowired 
    private MessageService service; 

    @RequestMapping(value = "/messageApp-api/getMessage/{id}", produces = "application/json") 
    public Message restGetMessage(@PathVariable long id) { 

     Message message = service.findSingleMessage(id).orElse(EMPTY_MESSAGE); 
     if (EMPTY_MESSAGE.equals(message)) { 
      throw new MessageNotFoundException(id); 
     } 

     return message; 
    } 
} 

例外クラス:

public class MessageNotFoundException extends RuntimeException { 
    public MessageNotFoundException(long id) { 
     super(String.format("Message id=%d not found", id)); 
    } 
} 

ApiError次のクラス:

public class ApiError { 
    private HttpStatus status; 
    private String message; 

    public ApiError(HttpStatus status, String message) { 
     this.status = status; 
     this.message = message; 
    } 

    public HttpStatus getStatus() { 
     return status; 
    } 

    public String getMessage() { 
     return message; 
    } 
} 

RestResponseExceptionクラス:

@Component 
@ControllerAdvice 
public class RestResponseException { 
    @ExceptionHandler(MessageNotFoundException.class) 
    public ResponseEntity<Object> messageNotFound(MessageNotFoundException e) { 
     ApiError apiError = new ApiError(HttpStatus.NOT_FOUND, e.getMessage()); 
     return new ResponseEntity<>(apiError, new HttpHeaders(), apiError.getStatus()); 
    } 
} 

クライアント側コントローラ:

@Controller 
public class MessageClientController { 

    private static final String MESSAGE = "restMessage"; 
    private static final String MESSAGES = "restMessages"; 
    private static final String ERROR = "error"; 

    @RequestMapping(value = "/messageApp-api/getMessage/{id}") 
    public String restGetMessage(@PathVariable long id, Model model) { 

     String view = MESSAGE; 

     try { 
      RestTemplate rest = new RestTemplate(); 
      ResponseEntity<Message> response = 
        rest.getForEntity("http://localhost:80/messageApp-api/getMessage/{id}", Message.class, id); 

      if (HttpStatus.OK == response.getStatusCode()) { 
       model.addAttribute(MESSAGE, response.getBody()); 
      } else if (HttpStatus.NOT_FOUND == response.getStatusCode()) { 
       model.addAttribute(MESSAGE, EMPTY_MESSAGE); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
      view = ERROR; 
     } 

     return view; 
    } 
} 

アイデアは、応答の状態を確認し、それに応じて、モデルに関するさらなるステップを作ることです。しかし、実際には、rest.getForEntity( "http://localhost:80/messageApp-api/getMessage/ {ID}"、Message.class、ID)いくつかのIDを持つメッセージが見つからなかった場合は、次の例外をスロー:だから

org.springframework.web.client.HttpClientErrorException: 404 null 
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) 
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:667) 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:620) 
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580) 
    at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:312) 
    at messageApp.controllers.rest.MessageClientController.restGetMessage(MessageClientController.java:34) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:220) 
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134) 
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) 
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:150) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) 
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783) 
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:789) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) 
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 

、例外を防止する方法レスポンスからhttpStatusを取得する方法を教えてください。..

答えて

3

これは私が遭遇した誤解です。 ResponseEntityのステータスコードをイントロスペクトするだけでエラーが発生したように見えます。しかし、そうではありません。

レスポンスステータスコードが> = 400の場合は必ずスローされるHttpStatusCodeExceptionをキャッチすることができます。次に、例外からステータスコードを取得できます。

try { 
     RestTemplate rest = new RestTemplate(); 
     ResponseEntity<Message> response = 
       rest.getForEntity("http://localhost:80/messageApp-api/getMessage/{id}", Message.class, id); 

     model.addAttribute(MESSAGE, response.getBody()); 
    } catch (HttpStatusCodeException e) { 
     if (HttpStatus.NOT_FOUND == e.getStatusCode()) { 
      model.addAttribute(MESSAGE, EMPTY_MESSAGE); 
     } 
     //handle other errors here 
    } 

HttpStatusCodeExceptionという2つのサブクラスがあります。

HttpClientErrorExceptionクライアントエラー(400 < =ステータスコード< 500)

HttpServerErrorExceptionサーバーエラーをスローされる(ステータスコード> = 500)

ためにスローされます