"Accidental override: The following declarations have the same JVM signature" when implementing Java interface
Asked Answered
B

5

13

I faced the following error trying to extend RuntimeException and implement GraphQLError interface, defined in Java, from my Kotlin code. This is the error:

Accidental override: The following declarations have the same JVM signature (getMessage()Ljava.lang.string;):

public open fun <get-message>(): String? defined in NegativeCountException public open fun getMessage(): String? defined in NegativeCountException

The following is my code:

class NegativeCountException() : RuntimeException(), GraphQLError {
  override fun getMessage(): String? {
    TODO("not implemented")
  }
  <...>
}

where GraphQLError is an interface, defined in Java as shown bellow:

public interface GraphQLError {
  String getMessage();
  <...>
}

Seems like it clashes with getMessage() defined in Throwable.

I can't change code of the interface, because it comes from a library.

How can I create my own runtime exception, that will implement GraphQLError?


PS: I also tried the following, and received a very similar error:

class NegativeCountException(override val message: String?) : RuntimeException(), GraphQLError {
  <...>
}
Battology answered 9/2, 2018 at 4:22 Comment(4)
Are you sure you don't have val message hidden inside <...>? That's what the error seems to say.Vellavelleity
@AlexeyRomanov Yes, I'm sure - there is no message property defined by me.Battology
Does this answer your question? Accidental override: The following declarations have the same JVM signatureKarmen
This has a solution that worked for me: github.com/graphql-java/graphql-java/issues/1022Ice
S
2

This is a graphql problem. My workaround:

Reimplement GraphQLError, ExceptionWhileDataFetching and DataFetcherErrorHandler.

KGraphQLError is a "fixed" kotlin interface (with val instead of getters) that you use for your custom errors.

in KDataFetcherErrorHandler: Replace ExceptionWhileDataFetching in this line with KExceptionWhileDataFetching:
val error = ExceptionWhileDataFetching(path, exception, sourceLocation)

KExceptionWhileErrorHandling implements GraphQLError. Look through the code and replace all instances of if (exception is GraphQLError) with (exception is KGraphQLError)

Pass the new KDataFetcherErrorHandler to your queryExecutionStrategy and mutationExecutionStrategy.

Your custom errors can now extend Throwable and implement KGraphQLError, and get handled properly.

More info here: http://graphql-java.readthedocs.io/en/latest/execution.html

Shiflett answered 18/5, 2018 at 12:42 Comment(1)
I wouldn't say it's a GraphQL problem. It's definitely a Kotlin problem, namely, that it doesn't allow to easily resolve this ambiguity. 2.5 years later, in Kotlin 1.4, the problem is still there.Hiram
E
1

I think it would work, when message was not a field in the one class (Throwable) and a method in the other. But it seems kotlin can not resolve the ambiguity when message is a field in the class and a method in the interface. If you have control over your GraphQlError you could do this:

class NegativeCountException() : RuntimeException(), GraphQLError {
    override val message: String?
        get() = super.message
}

interface GraphQLError {
    val message: String?
}
Endorse answered 10/2, 2018 at 11:12 Comment(2)
Thanks! But I have no control over the interface.Battology
This is the issue: youtrack.jetbrains.com/issue/KT-6653Hiram
C
0

This is because Kotlin will create getters and setters for your variables when generating Java byte code. For example,

class Foo(val bar)

Foo with have getBar in Java byte code. To avoid name conflict, use @JvmField and @JvmName.

Read more about this here.

Cumquat answered 9/2, 2018 at 5:29 Comment(6)
The problem is that I define no properties. Moreover, I do define nothing. The only thing I do is overriding of getMessage method, which is defined in both: abstract class Throwable and interface GraphQLError.Battology
@VictorDombrovsky Your NegativeCountException constructor has override val message: String?. var and val in constructor is class variables.Cumquat
It was an additional try. Take a look, please, at the main example, where I have no properties defined.Battology
I added a link to sources of GraphQLError. Probably it may help to reproduce the problem.Battology
Actually, in my understanding, since getMessage is implemented in Throwable, it should be considered as implementation for getMessage defined in GraphQLError (signatures are the same), so that I need to override nothing. But it doesn't work this way.Battology
@VictorDombrovsky I understand your problem now. But do you have control on GraphQLError? As far as I know, there isn't a way to work around this. It also happens when there are name conflicts in Java.Cumquat
H
0

There is a quick and dirty workaround, in case your project allows Java alongside Kolin. Write your NegativeCountException in Java :D

Hiram answered 5/10, 2020 at 5:40 Comment(0)
I
0

There's actually a good solution for this (provided here):

class NegativeCountException(@JvmField override val message: String) : RuntimeException(message), GraphQLError {
    override fun getMessage(): String? = super.message
  <...>
}
Ice answered 15/2, 2022 at 17:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.