Http错误消息未从微服务传播到Webapp

时间:2016-03-31 20:11:46

标签: java spring rest spring-mvc

我正在构建一个基于Spring boot微服务的应用程序,我无法将我的错误消息从包含所有业务逻辑的服务传播回webapp。在我的服务中,我抛出的异常如下:

@ResponseStatus(HttpStatus.BAD_REQUEST)
public class Http400ServiceException extends Exception {

    public Http400ServiceException() {
        super("Some error message");
    }
}

一切都按预期运行,按预期发送响应代码。因此,如果我的服务发送了403异常,我将在webapp中获得403。我现在要做的是从我的服务中的例外中获取错误消息。

问题

当我以一种产生403的方式从其他客户端戳我的服务时,响应(用JSON)看起来像这样:

{
    "timestamp": 1459453512220
    "status": 403
    "error": "Forbidden"
    "exception": "com.mysite.mypackage.exceptions.Http403ServiceException"
    "message": "Username Rob must be between 5 and 16 characters long"
    "path": "/createLogin"
}

但是,出于某种原因,我无法从我的webapp访问“消息”字段。我在webapp中有一些通用的错误处理代码,如下所示:

@Override
public RuntimeException handleException(Exception e) {
    ...
    if (e instanceof HttpClientErrorException) {
        HttpClientErrorException httpError = (HttpClientErrorException) e;
        LOGGER.info(httpError.getResponseBodyAsString());
    }
    ...
}

但是当我查看我的日志/在调试中运行我的应用程序时,httpError.getResponseBodyAsString()返回null。它有正确的响应代码,只是没有响应主体。

如果有人对出了什么问题有任何见解,我会非常感激。

1 个答案:

答案 0 :(得分:0)

因此,当我们在应用程序的其他区域工作时,我们将此问题暂停了几个月。但是,如果其他人在尝试解决类似问题时看到这一点,我最终采用的方法是以下

  • 为要实现的所有服务的所有响应创建一个接口,并使用一个异常类型来指示该异常是由于用户错误:

    public interface IModel {
        boolean isError();
        UserException getError();
    }
    
  • 在每个服务的控制器中,捕获任何异常并从中创建某种IModel:

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(UserException.class)
    public IModel handleException(UserException exception) {
        return exception.toModel();
    }
    
  • 在用于调用服务的组件中,如果响应上有UserException,则抛出它,否则返回响应主体:

    public <T extends IModel> T makeCall(Object payload, Endpoint<T> endpoint) throws UserException {
        ...
        ResponseEntity<T> response = restTemplate.postForEntity(endpoint.getEndpointUrl(), payload, endpoint.getReturnType());
        if (response.getBody().isError()) {
            throw response.getBody().getError();
        }
        ...
        return response.getBody();
    }
    
  • 在webapp中,使用适当的@ExceptionHandler处理异常,例如

    @ExceptionHandler(UserException.class)
    public ModelAndView handleUserException(UserException e) {
        ModelAndView modelAndView = new ModelAndView("viewName");
        modelAndView.addObject("errorMessage", e.getMessage());
        return modelAndView;
    }
    

我觉得有一个更清洁的方法,但这是迄今为止我能够提出的最好的方法。如果我找到更好的方法,我会更新这个。