[英]How to document internal error with microprofile
Assume following code written with Quarkus.假设以下代码是用 Quarkus 编写的。 But can as well be with micronaut.
但也可以与 micronaut 一起使用。
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@APIResponses(
value = {
@APIResponse(
responseCode = "201",
description = "Customer Created"),
@APIResponse(
responseCode = "400",
description = "Customer already exists for customerId")
}
)
public Response post(@Valid Customer customer) {
final Customer saved = customerService.save(customer);
return Response.status(Response.Status.CREATED).entity(saved).build();
}
The Customer definition includes a field pictureUrl.客户定义包括一个字段 pictureUrl。 CustomerService is responsible to validate the the URL is a valid URL and that the image really exists.
CustomerService 负责验证 URL 是有效的 URL 并且图像确实存在。
This means that following exception will be processed by the service: MalformedURLException and IOException.这意味着服务将处理以下异常:MalformedURLException 和 IOException。 The CustomerService catches these errors and throws an application specific exception to report that the image does not exist or the path is not correct: ApplicationException.
CustomerService 捕获这些错误并抛出应用程序特定异常以报告图像不存在或路径不正确:ApplicationException。
How do you document this error case with microprofile?您如何使用 microprofile 记录此错误案例?
My research suggests that I have to implement an exception mapper of the form:我的研究表明我必须实施以下形式的异常映射器:
public class ApplicationExceptionMapper implements ExceptionMapper<NotFoundException> {
@Override
@APIResponse(responseCode = "404", description = "Image not Found",
content = @Content(
schema = @Schema(implementation = Customer.class)
)
)
public Response toResponse(NotFoundException t) {
return Response.status(404, t.getMessage()).build();
}
}
And once I have a such mapper, the framework would know how to convert my exception into Response.一旦我有了这样的映射器,框架就会知道如何将我的异常转换为 Response。 Is my analysis correct?
我的分析正确吗? What is the best practice?
最佳做法是什么?
You are more or less pointed in the right direction, your question can be divided in two, let me answer separately both:您或多或少指向了正确的方向,您的问题可以分为两个,让我分别回答两个:
A common good strategy for dealing with the scenario you have explained is to have a family of custom exceptions that extend the WebApplicationException where you can specify the response code and message, Or just using the ones provided by jax-rs .处理您所解释的场景的一个常见的好策略是拥有一系列扩展 WebApplicationException 的自定义异常,您可以在其中指定响应代码和消息,或者仅使用jax-rs提供的那些。 And if you need further customization with i18n support or its important to provide a response entity with details associated to the error, then implement the ExceptionMapper.
如果您需要进一步定制 i18n 支持,或者提供一个包含与错误相关的详细信息的响应实体很重要,那么请实现 ExceptionMapper。
For the actual error handling and conversion of exceptions to corresponding HTTP responses you would use the JaxRS exception mapper as you already started.对于实际的错误处理和将异常转换为相应的 HTTP 响应,您将使用已经开始的 JaxRS 异常映射器。 But the exception mapper itself, is not considered at all during the creation of the OpenAPI schema, as the OpenAPI extension has no way of obtaining the information about the actual error responses produced by your exception mapper.
但是异常映射器本身在创建 OpenAPI 模式期间根本不被考虑,因为 OpenAPI 扩展无法获取有关异常映射器产生的实际错误响应的信息。 So you need to declare the possible error cases on the actual endpoint methods -which can be a bit tedious, especially if your endpoint methods can result in multiple error responses (400, 500, 409..).
因此,您需要在实际端点方法上声明可能的错误情况——这可能有点乏味,尤其是当您的端点方法可能导致多个错误响应(400、500、409..)时。 But you can reduce the amount of duplicated code by creating a shared error response definitions.
但是您可以通过创建共享的错误响应定义来减少重复代码的数量。
A common pattern for error handling on API layer is to explicitly define the models for your error responses eg I want all my endpoints to return error responses in a form of json document that looks sth like this: API 层错误处理的常见模式是明确定义错误响应的模型,例如我希望我所有的端点以 json 文档的形式返回错误响应,看起来像这样:
{
"errorCode" : "MY_API_123",
"errorDescription" : "This operation is not allowed"
//anything else, details, links etc
}
So I create a POJO model for the response:所以我为响应创建了一个 POJO model:
@Data
@AllArgsConstructor
public class ErrorResponse {
private String errorCode;
private String errorDescription;
}
And in my exception mapper I can convert my exception to the error response above:在我的异常映射器中,我可以将我的异常转换为上面的错误响应:
public Response toResponse(Exception e) {
// you can define a mapper for a more general type of exception and then create specific error responses based on actual type, or you could define your own application level exception with custom error info, keys, maybe even i18n, that you catch here, you get the idea
if (e instanceOf NotFoundException) {
return Response.status(404, new ErrorResponse("MY_API_400", "Object not found")).build();
}
if (e instanceOf IllegalArgumentException) {
return Response.status(400, new ErrorResponse("MY_API_400", "Invalid request")).build();
}
// fallback if we dont have any better error info
return Response.status(500, new ErrorResponse("MY_API_100", "Internal server error")).build();
}
You can then document the possible error responses using the OpenAPi annotations:然后,您可以使用 OpenAPI 注释记录可能的错误响应:
@APIResponses({
@APIResponse(responseCode = "201", description = "Customer Created"),
@APIResponse(responseCode = "400", description = "Other object exists for customerId", content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@APIResponse(responseCode = "500", description = "Internal error", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
public Response yourMethod()
Or if you have some responses that are repeated often (such as generic internal server error, unathorized/unathenticated) you can document them on your class extending JaxRS Application and then reference them in your endpoints like this:或者,如果您有一些经常重复的响应(例如一般的内部服务器错误、未经授权/未经授权),您可以将它们记录在您的 class 扩展 JaxRS 应用程序中,然后在您的端点中引用它们,如下所示:
@Authenticated
@APIResponses({
@APIResponse(responseCode = "200", description = "Ok"),
@APIResponse(responseCode = "401", ref = "#/components/responses/Unauthorized"),
@APIResponse(responseCode = "500", ref = "#/components/responses/ServerError")
})
public Response someAPIMethod() {
Example JaxRS application class(useful for other common top level openapi schema attributes) JaxRS 应用程序类示例(对其他常见的顶级 openapi 模式属性很有用)
@OpenAPIDefinition(
info = @Info(title = "My cool API", version = "1.0.0"),
components = @Components(
schemas = {@Schema(name = "ErrorResponse", implementation = ErrorResponse.class)},
responses = {
@APIResponse(name = "ServerError", description = "Server side error", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(ref = "#/components/schemas/ErrorResponse")), responseCode = "500"),
@APIResponse(name = "NotFound", description = "Requested object not found", content = @Content(schema = @Schema(ref = "#/components/schemas/ErrorResponse")), responseCode = "404"),
@APIResponse(name = "Forbidden", description = "Authorization error", responseCode = "403"),
@APIResponse(name = "BadRequest", description = "Bad Request", responseCode = "400"),
@APIResponse(name = "Unauthorized", description = "Authorization error", responseCode = "401")})
)
public class RESTApplication extends Application {
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.