在rest api中返回json中的任何异常

时间:2016-07-22 07:13:00

标签: java json api rest exception

有没有简单的方法可以使用Rest api在JSON中返回异常?
 我已经用Google搜索了这个问题,但我看到的所有解决方案都是关于在某些计算过程中抛出异常。但如果收入参数错误呢?我的意思是如果有sone字符串而不是int输入参数?

我为输入数据创建了一些DTO类:

@XmlRootElement
public class RequestDTO implements Serializable{

private static final long serialVersionUID = 1L;

@XmlElement(name = "request_id")
private String requestId;

@XmlElement(name = "site")
private List<String> sitesIds;

@XmlElement(name = "date_begin")
@JsonSerialize(using = DateSerializer.class)
@JsonDeserialize(using = DateDeserializer.class)
private Date dateBegin;

@XmlElement(name = "date_end")
@JsonSerialize(using = JsonDateSerializer.class)
@JsonDeserialize(using = JsonDateDeserializer.class)
private Date dateEnd;


@XmlElement(name = "volume")
private double volume;

// there is getters and setters
}

如果我在我的json请求中发送类似'qwerty'而不是'volume'字段的内容,我会看到像运行时一样的错误消息。有可能以某种方式处理它吗?我的意思是用这种结构在json中返回错误?

public class ExceptionDTO {

private String shortExceptionMessage;
private String stackTrace;

public ExceptionDTO(String shotExceptionMessage, String stackTrace){
    this.shortExceptionMessage = shotExceptionMessage;
    this.stackTrace = stackTrace;
}

public String getShortExceptionMessage() {
    return shortExceptionMessage;
}

public String getStackTrace() {
    return stackTrace;
}
}

UPD1:

@Provider
@Singleton
public class ExceptionMapperProvider implements ExceptionMapper<Exception>{

    @Override
    public Response toResponse(final Exception e) {

        StringBuilder trace = new StringBuilder();
        IntStream.range(0, e.getStackTrace().length)
            .forEach(i -> trace.append(e.getStackTrace()[i]).append('\n'));


        ExceptionDTO exceptionMessage = new ExceptionDTO(
                e.toString(),
                trace.toString()
         );

        return Response.status(500).entity(exceptionMessage).build();
    }
}

3 个答案:

答案 0 :(得分:4)

由于您是否对检查有效负载的字段或值是否正确感兴趣尚不清楚,以下是一些可以同时使用这两种方法的方法。

如果要检查字段的value是否正确(即,字段字段值应大于零等),请查看bean validationThis在您要验证的字段上使用注释。

// for example
@Min(value = 0, message = "invalid message")
private double range;

要在其中一个验证失败时将ExceptionDTO用作错误响应,您可以通过创建ExceptionMapper<ConstraintViolationException>来执行此操作。检查here了解更多详情。

如果要检查无效字段(即客户端发送ragne字段而不是范围),请查看正在抛出异常的堆栈跟踪。然后注册一个以ExceptionDTO为主体的异常映射器。

例如,如果抛出UnrecognizedPropertyException,则可以添加:

@Provider
public class UnrecognizedPropertyExceptionMapper implements ExceptionMapper<UnrecognizedPropertyException> {

   @Override
   public Response toResponse(UnrecognizedPropertyException e) {
      ExceptionDTO myDTO = // build response
      return Response.status(BAD_REQUEST).entity(myDTO).build();
   }
}

答案 1 :(得分:0)

如果要验证请求中的输入参数,则应返回状态码400(错误请求)以及错误详细信息。你可以简单地发送json { "error": { "message": "string received for parameter x, where as int expected" },响应状态代码为400。

`

答案 2 :(得分:0)

我做了一些研究,并确定在JSON中编码Java异常的最佳方法是使用Oasis开发的约定,如下所示:

{
   "error": {
      "code": "400",
      "message": "main error message here",
      "target": "approx what the error came from",
      "details": [
         {
            "code": "23-098a",
            "message": "Disk drive has frozen up again.  It needs to be replaced",
            "target": "not sure what the target is"
         }
      ],
      "innererror": {
         "trace": [ ... ],
         "context": [ ... ]
      }
   }
}

details是一个列表,应该为链中的每个嵌套的原因异常都有一个条目。

如果您愿意,

innererror.trace应该包含堆栈跟踪,作为字符串值列表。

响应状态代码应该是400,除非你有充分的理由让它成为别的东西,并且结构中的代码应该匹配你发送的任何内容。

编写一个方法将Java异常转换为此格式,您就完成了。一致地使用它,您的JS代码将能够处理和显示异常值。

JSON REST API - 异常处理的博文中介绍了评估和解除其他方法的更多细节。 https://agiletribe.wordpress.com/2015/09/16/json-rest-api-exception-handling/

以下是将异常转换为此格式的java方法:

public static JSONObject convertToJSON(Exception e, String context) throws Exception {
    JSONObject responseBody = new JSONObject();
    JSONObject errorTag = new JSONObject();
    responseBody.put("error", errorTag);

    errorTag.put("code", 400);
    errorTag.put("target", context);

    JSONArray detailList = new JSONArray();
    errorTag.put("details", detailList);

    String lastMessage = "";
    Throwable runner = e;
    while (runner!=null) {
        String className =  runner.getClass().getName();
        String msg =  runner.toString();

        runner = runner.getCause();

        JSONObject detailObj = new JSONObject();
        detailObj.put("message",msg);
        int dotPos = className.lastIndexOf(".");
        if (dotPos>0) {
            className = className.substring(dotPos+1);
        }
        detailObj.put("code",className);
        System.out.println("          ERR: "+msg);
        detailList.put(detailObj);
    }

    JSONObject innerError = new JSONObject();
    errorTag.put("innerError", innerError);

    JSONArray stackList = new JSONArray();
    runner = e;
    while (runner != null) {
        for (StackTraceElement ste : runner.getStackTrace()) {
            String line = ste.getFileName() + ":" + ste.getMethodName() + ":" + ste.getLineNumber();
            stackList.put(line);
        }
        stackList.put("----------------");
        runner = runner.getCause();
    }
    errorTag.put("stack", stackList);
    return responseBody;
}