Search code examples
kotlinclasscastexception

Kotlin - ClassCastException isn't being caught


Consider the following function

fun issueAssetOrThrow(): ResponseEntity<AssetResponseMessage> {
    val response = getOrThrow(controller.issueAsset(ASSET_REQUEST_MESSAGE))

    return try {
        response as ResponseEntity<AssetResponseMessage>
    } catch (classCastException: ClassCastException) {
        val errorResponse = response as ResponseEntity<ErrorResponseMessage>
        fail(errorResponse.body.error)
    }
}

In the event of a successful response, getOrThrow(controller.issueAsset(ASSET_REQUEST_MESSAGE)) will return ResponseEntity<AssetResponseMessage>.

In the event of an unsuccessful response it will return ResponseEntity<ErrorResponseMessage>, unless there is some catastrophic failure, in which case it throws an exception.

Since the generic part of the response is unknown at this point, the function should first try to cast the response to ResponseEntity<AssetResponseMessage>.

If it can't perform this cast, it will throw a ClassCastException and then tries to cast the response to ResponseEntity<ErrorResponseMessage>.

It should then extract the error message and fail with this message, throwing an AssertionError

The problem is that I actually get this output

java.lang.ClassCastException: com.demo.api.messages.ErrorResponseMessage cannot be cast to com.demo.api.messages.AssetResponseMessage

It looks like catch(classCastException: ClassCastException) gets ignored completely! Why is this?


Solution

  • Thanks to lrcover for suggesting as? I have now come up with this as a solution

    private fun <TResult> responseOrFail(response: Any): ResponseEntity<TResult> {
        val errorResponse = response as? ResponseEntity<ErrorResponseMessage>
    
        if (errorResponse != null) {
            fail(errorResponse.body.error)
        }
    
        return response as ResponseEntity<TResult>
    }
    

    Then in my method:

    return responseOrFail(response)

    And now I have the desired result.