0
votes

I try to develop a REST API with GraphQL and Kotlin and I'm facing the following problem: I try to create a custom Exception that extends RuntimeException and implements GraphQLError and in Kotlin I can not do this because I'm receiveing this: Accidental override when using third party Java interface and extending RuntimeException in kotlin.

I resolve this problem with an workaround by creating a Java class for my CustomException.

But I don't know why, when I create a kotlin class that extends RuntimeException and implements GraphQLError, I need to override the getMessage() method from GraphQLError, but when I create a java class that extends RuntimeException and implements GraphQLError I don't need to override the getMessage() method from GraphQLError.

Thank you!

2
I am not into Kotlin, but as I read it, this is a known problem in Kotlin that is not solved yet: KT-24822 (and others) - Arnold Schrijver
Yeah, I understand that problem, but my question was about another fact: why I need to override the getMessage() method in Kotlin, but not in Java. - Dina Bogdan

2 Answers

3
votes

Annotate message with @JvmField like:

class MyError(@JvmField override val message: String?, private val invalidField: String? = null) : RuntimeException(message), GraphQLError {

    override fun getMessage(): String = super.message ?: "no error message set"

    override fun getLocations(): List<SourceLocation> = emptyList()

    override fun getErrorType(): ErrorType = ErrorType.DataFetchingException

    override fun getExtensions(): Map<String, Any> = if(invalidField!=null)
        Collections.singletonMap<String, Any>("invalidField", invalidField)
    else
        Collections.emptyMap()
}
1
votes

It seems overriding a property accessor with a function is not yet seemlessly supported. It is currently a bug as per your link. This can be easily verified by a simple example like this one:

class Sample(val message : String) {
    fun getMessage() :String = "MyString"
}

This happens because the property message (in your case, the message from Throwable) and the getMessage function (in your case, the getMessage from GraphQL) converts to the same JVM signature. It seems to me that the current status quo is that property accessors are not treated as individual members so they cannot be overriden by member functions or even implement abstract functions. I am not sure why that is the case though.