question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Boolean properties with "is" prefix are misinterpreted during reflective DataFetcher generation

See original GitHub issue

Library Version 1.4.2

Describe the bug Declaring a Kotlin Boolean property with a prefix of “is” causes the default KotlinDataFetcherFactoryProvider to return a graphql-java PropertyDataFetcher with a name that does not resolve as expected.

Kotlin Boolean properties with an “is” prefix generate get methods without an additional prefix, e.g: val isFancy: Boolean yields a generated method of boolean isFancy() but PropertyDataFetcher’s reflective method lookup only considers methods with an additional “is” or “get” prefix. This causes data fetching to fail at query time.

This results in additional unexpected behavior if Boolean properties isFancy and fancy are exposed on the same object (though this is admittedly a contrived scenario). PropertyDataFetcher will resolve fancy to point at the isFancy property when queried, and attempting to fetch isFancy will produce an error.

To Reproduce Steps to reproduce the behavior.

  • Schema Configuration Default
  • Kotlin code used to generate the schema
class Test {
    val isFancy: Boolean get() = true
    val fancy: Boolean get() = false
}

// Pass TopLevelObject(Query()) to toSchema()
class Query {
    fun test() = Test()
}

Queries to reproduce:

# Cannot fetch the isFancy property
query LookupError {
  test {
    isFancy
  }
}

# Fetches the isFancy property, not fancy (returns true rather than false)
query WrongProperty {
  test {
    fancy
  }
}

Expected behavior The generated data fetchers fetch the Kotlin object properties with names matching the generated schema.

Workaround Solving the issue completely may involve either upstream changes for graphql-java’s PropertyDataFetcher or reimplementing it with Kotlin-aware behavior in graphql-kotlin to resolve the ambiguity between is-prefixed and unprefixed Boolean properties. The first issue illustrated can be worked around by replacing the KotlinDataFetcherFactoryProvider as follows:

class FixedDataFetcherFactoryProvider(
    hooks: SchemaGeneratorHooks = NoopSchemaGeneratorHooks
) : KotlinDataFetcherFactoryProvider(hooks) {
    @ExperimentalStdlibApi // for typeOf
    override fun propertyDataFetcherFactory(
        kClass: KClass<*>,
        kProperty: KProperty<*>
    ) = DataFetcherFactory<Any> {
        if (kProperty.name.startsWith("is")
            && kProperty.returnType == typeOf<Boolean>()
            && kProperty.name.length > 2
        ) {
            // Omit "is" prefix that PropertyDataFetcher will add back
            PropertyDataFetcher(kProperty.name.substring(2))
        } else PropertyDataFetcher(kProperty.name)
    }
}

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:5

github_iconTop GitHub Comments

2reactions
dariuszkuccommented, Jan 16, 2021

While looking into this I’ve noticed that we actually don’t need to invoke the default PropertyDataFetcher from graphql-java at all. While it is pretty well optimized and works great for retrieving fields from arbitrary POJO, it does so by using reflections to locate the target getter function. Since we are generating the schema using reflections, when we process the target property we already know which field on a class we have to access and can reference the target getter function directly. As a bonus, this also removes the ambiguity in resolving the field prefixed with is as well.

See https://github.com/ExpediaGroup/graphql-kotlin/pull/1018 for details

0reactions
andimarekcommented, Jan 4, 2021

GraphQL Java maintainer here: in general we want to provide good interop with kotlin as long as it comes with reasonable costs. If this fix here would mean a bit tweaking of the PropertyDataFetcher I would recommend you open a PR and we can go from there.

In general I would recommend not to duplicated/copy the PropertyDataFetcher: it is quite optimized at this stage and I can imagine it will evolve further in the future.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Questions about boolean class properties naming convention ...
is prefix can be used for boolean variables and methods. isSet, isVisible, isFinished, isFound, isOpen This is the naming convention for boolean methods...
Read more >
Tips on naming boolean variables - Cleaner Code
There is a convention to prefix boolean variables and function names with "is" or "has". You know, something like isLoggedIn , hasAccess or ......
Read more >
chore(deps): update dependency io.quarkus:quarkus ... - GitLab
Something went wrong while fetching comments. Please try again. chore(deps): update dependency io.quarkus:quarkus- ...
Read more >
Clean Code in JavaScript - FreePdf-books.com
Increment and decrement (prefix and postfix) operators ... In 1997, not long after its creation, JavaScript was standardized by Ecma International.
Read more >
Ace the Programming Interview - PDFiles.net
All other trademarks are the property of their respective owners. ... less experienced developers reading and reflecting on the issues in this chapter....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found