0

I'm writing an API in Kotlin with the Ratpack framework, using Jackson to deserialize JSON request bodies. When I send an invalid request body, my application throws a 500 internal server error exception:

import com.google.inject.Inject
import com.mycompany.mynamespace.MyComponent
import ratpack.func.Action
import ratpack.handling.Chain
import java.util.UUID

class MyTestEndpoint @Inject constructor(
    private val myComponent: MyComponent) : Action<Chain> {

  override fun execute(chain: Chain) {
    chain
        .post { ctx ->
          ctx.parse(MyParams::class.java)
              .map { parsedObject -> myComponent.process(parsedObject) }
              .then { ctx.response.send() }
        }
  }
}

data class MyParams(val borrowingId: UUID)

The exception when this endpoint is hit with an invalid request body is:

com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class com.mycompany.mynamespace.MyParams] value failed for JSON property borrowingId due to missing (therefore NULL) value for creator parameter borrowingId which is a non-nullable type

I have a generic error handler which checks the type of Exception thrown, and returns an appropriate status. But in this case, checking for a MissingKotlinParameterException and returning 400 bad request does not make sense, because this exception may be thrown in other circumstances.

Additionally, I could add onError after the ctx.parse line, but this is going to be a large API, and implementing that in every handler doesn't follow the pattern of having a generic error handler to keep the API consistent. Is there a way to get Ratpack to throw a specific exception (something like ParseFailedException) when the parse fails, so that I can catch it and return a 400 bad request?

1 Answers1

0

As a workaround I've written an extension method:

fun <T: Any> Context.tryParse(type: Class<T>): Promise<T> {
    return parse(type)
        .onError { ex -> throw BadRequestException(ex) }
}

Where my generic error handler catches the BadRequestException, and sets the response status to 400