使用Sitebricks发送一致的JSON响应以报告异常

时间:2012-11-15 17:17:27

标签: java json exception-handling sitebricks

我正在开发一个webapp,它提供了许多带有Google Sitebricks的REST端点。为了最小化重复/类似的代码,我希望每次在REST端点中执行的代码抛出异常时,我都希望将sitebricks配置为使用一致的Reply对象进行响应。

不是在每个端点处理异常并创建自定义JSON响应,而是希望sitebricks本身捕获异常并返回如下内容:

{
  statusCode: 123,
  message: "this could contain Exception.getMessage()",
  stacktrace: "this could contain the full stacktrace"
}

Sitebricks将负责创建上述结构并填写状态代码和其他字段,例如基于注释。

  • 我是否必须自己构建或者其他人已经这样做了吗?也许有一种方法可以用Sitebricks本身做到这一点?
  • 是否相当于Jersey's ExceptionMapper interface

2 个答案:

答案 0 :(得分:0)

不完全回答您的问题,但我在管理错误方面所采取的措施如下:

在我所有REST端点的父类中,我已声明了以下方法:

protected Reply<?> error(String errorCode) {
    logger.error(errorCode);
    return Reply.with(new ErrorJSONReply(errorCode)).as(Json.class).headers(headers()).type("application/json; charset=utf-8");
}

然后在我的所有端点中,我正在捕获异常并使用此方法来回复一般错误。

希望有所帮助。

此致

答案 1 :(得分:0)

您可以使用Guice的AOP goodness绑定方法拦截器来捕获和序列化JSON的异常...

public class ReplyInterceptor implements MethodInterceptor {

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    @BindingAnnotation
    public @interface HandleExceptionsAndReply {
    }


    public ReplyInterceptor() {
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        try {
            return methodInvocation.proceed();
        } catch (Throwable e) {
            return handleException(e);
        }
    }

    private Object handleException(Throwable e) {
        Throwable cause = getCause(e);
        return Reply.with(cause).as(Json.class);
    }


    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
    private Throwable getCause(Throwable e) {
        // org.apache.commons.lang3.exception.ExceptionUtils
        Throwable rootCause = ExceptionUtils.getRootCause(e);
        return rootCause == null ? e : rootCause;
    }
}

绑定它......

bindInterceptor(
        Matchers.any(),
        Matchers.annotatedWith(ReplyInterceptor.HandleExceptionsAndReply.class),
        new ReplyInterceptor(getProvider(ResponseBuilder.class))
);

// OR bind to request method annotations...

bindInterceptor(
        Matchers.any(),
        Matchers.annotatedWith(Get.class),
        new ReplyInterceptor(getProvider(ResponseBuilder.class))
);

使用它......

@At("/foo/:id")
@Get
@ReplyInterceptor.HandleExceptionsAndReply
public Reply<ApiResponse<Foo>> readFoo(@Named("id") String id) {
     // fetch foo and maybe throw an exception
     // ...        
}

参考:https://code.google.com/p/google-guice/wiki/AOP