Micronaut ExceptionHandler: создать HttpResponse с кодом состояния и телом

В моем приложении Micronaut я определил ExceptionHandler, который должен ловить WorkflowException и возвращать HttpResponse с кодом состояния 412 и с WorkflowExceptionVM в качестве тела.

Вот моя текущая реализация:

@Produces
@Singleton
@Requires(classes = [WorkflowException::class, ExceptionHandler::class])
class WorkflowExceptionHandler : ExceptionHandler<WorkflowException, HttpResponse<WorkflowExceptionVM>> {

    override fun handle(request: HttpRequest<Any>, exception: WorkflowException): HttpResponse<WorkflowExceptionVM> {
        return HttpResponse.status<WorkflowExceptionVM>(HttpStatus.PRECONDITION_FAILED)
                .body(WorkflowExceptionVM(exception.code))
    }
}

Он дает ответ с правильным кодом, но не включает тело.

Вот мой тест:

@Test
fun `Should handle WorkflowException`() {
    val request = POST(THE_URL, THE_BODY).basicAuth("user", "password")
    val exception = shouldThrow<HttpClientResponseException>
        {client.toBlocking().exchange(request, MyEntity::class.java) }

    exception.response.code() shouldBe 412 // This works
    exception.response.body() // ERROR: this is null
}


Как добавить тело в ответ?


person Eerik Sven Puudist    schedule 05.08.2019    source источник


Ответы (1)


Чтобы получить тело ошибки, вам нужно использовать метод с 3 параметрами exchange, в котором третий - тип ошибки: https://docs.micronaut.io/1.2.x/api/io/micronaut/http/client/DefaultHttpClient.html#exchange-io.micronaut.http.HttpRequest-io.micronaut.core.type.Argument-io.micronaut.core.type.Argument-

Итак, ваш код должен быть:

val exception = shouldThrow<HttpClientResponseException>
        {client.toBlocking().exchange(request, MyEntity::class.java, WorkflowExceptionVM::class.java) }

Я не уверен на 100%, будет ли это работать в Kotlin или нет, потому что в Java вам нужно обернуть bodyType и errorType внутри Argument. Если это не сработает, попробуйте:

val exception = shouldThrow<HttpClientResponseException>
        {client.toBlocking().exchange(request, Argument.of(MyEntity::class.java), Argument.of(WorkflowExceptionVM::class.java)) }

ОБНОВЛЕНИЕ: извлечение тела из исключения использует exception.getResponse().getBody(WorkflowExceptionVM::class.java). Это возвращает Optional, поэтому вы можете проверить наличие тела, получить его и проверить любое свойство на WorkflowExceptionVM.

person Iván López    schedule 05.08.2019
comment
Спасибо! Вы правы, что проблема в тестовом коде (я проверил с помощью Postman, что тело ошибки действительно присутствует, как и ожидалось). Ваш первый пример кода не компилируется. Добавление только ожидаемого типа тела без его обертывания в Argument.of() работает нормально, но если тип ошибки также присутствует, оба должны быть обернуты. Второй образец компилируется, но тело по-прежнему остается нулевым. - person Eerik Sven Puudist; 07.08.2019
comment
Я обновил свой ответчик о том, как извлечь в тело. Опять же, имейте в виду, что он может не компилироваться непосредственно в Kotlin, я просто перевожу эквивалентный код Java (на самом деле Groovy, потому что я использую Spock для тестов) - person Iván López; 08.08.2019