OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.77k stars 6.57k forks source link

[REQ] [Java] [Native] Allow exception customization without templating #8759

Open MosheElisha opened 3 years ago

MosheElisha commented 3 years ago

Is your feature request related to a problem? Please describe.

When an exception is thrown from the xxxApi classes, the response body is stored in the exception but is not part of the message. In many cases, the body is important and contains the reason of the error. The current implementation requires us to wrap every API call with try-catch that thrown a wrapping exception with the body in the message.

Describe the solution you'd like

Create an ExceptionHandler interface to allow user to replace the exceptions thrown and add a default ExceptionHandlerImpl that keeps the current behavior. Something like:

public interface ExceptionHandler {

  ApiException createUnsuccessfulResponseException(String msg, HttpResponse<InputStream> response);

  ApiException createException(Exception e);

  ApiException createInvalidRequestException(int statusCode, String msg);
}

The user will be able to replace the exception handler implementation by setting the exception handler on the ApiClient. Similar to how it works with the request and response interceptors.

Describe alternatives you've considered

  1. A simpler alternative which is also fine by me is to simple concatenate the body to the message when creating the exception but I'm not sure everyone would like that behavior (especially if it changes past behavior).

  2. Create a custom template but than you need to make sure to keep your template up-to-date when upgrading OpenAPI.

Additional context

ApiClient:

public class ApiClient {
  ...
  private ExceptionHandler exceptionHandler;
  ...

PostsApi:

public IncidentsApi(ApiClient apiClient) {
  ...
  private final ExceptionHandler exceptionHandler;
  ...
  public IncidentsApi(ApiClient apiClient) {
    ...
    memberVarExceptionHandler = apiClient.getExceptionHandler();
  }
  ...  
}

Default implementation:

public class DefaultExceptionHandler implements ExceptionHandler {

  @Override
  public ApiException createUnsuccessfulResponseException(String msg, HttpResponse<InputStream> response) {
    String bodyStr = null;
    try {
      bodyStr = new String(response.body().readAllBytes());
    } catch (Exception e) {
      bodyStr = "<Failed to read response body: " + e + ">";
    }

    return new ApiException(response.statusCode(), msg, response.headers(), bodyStr);
  }

  @Override
  public ApiException createException(Exception e) {
    return new ApiException(e);
  }

  @Override
  public ApiException createInvalidRequestException(int statusCode, String msg) {
    return  new ApiException(statusCode, msg);
  }
}

Usage example:

      if (localVarResponse.statusCode()/ 100 != 2) {
        throw exceptionHandler.createUnsuccessfulResponseException(
            "createPost call received non-success response",
            localVarResponse
        );
      }
MosheElisha commented 3 years ago

Hi @wing328 ,

Can you please review the feature request or add relevant reviewers?

Thanks.

wing328 commented 3 years ago

As discussed I prefer something simple so revising the exception message with additional information such as HTTP response body is fine with me.