Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In Kotlin, specifying a default entity graph make query fail with Stackoverflow exception #119

Open
mr-nothing opened this issue Aug 2, 2023 · 3 comments

Comments

@mr-nothing
Copy link

For some reason specifying DynamicEntityGraph as a default one make repository.findById(id: String) fail with stackoverflow exception. Was unable to understand if it is a bug or I just misuse/misconfigured something.

Steps to reproduce the behaviour:

  1. Define repository as follows:
@Repository
interface MyEntityRepository : EntityGraphJpaRepository<MyEntity, String> {
    override fun defaultEntityGraph(): Optional<EntityGraph> {
        return Optional.of(
            DynamicEntityGraph.loading(listOf("field1", "field2", "field3", "field4"))
        )
    }
// Here goes some custom methods
}

Where fieldN is a OneToOne relation fields.

  1. Call findById repository method as follows:
class MyService(
    private val myEntityRepository: MyEntityRepository
) {
fun getMyEntityById(entityId: String): MyEntity {
    return myRepository.findById(entityId).orElseThrow {
        NotFoundException("Entity not found")
    }
}
  1. Make this method be called by any of your rest endpoints.

What is the expected output ?

DynamicEntityGraph should be used to fetch MyEntity data.

What happens instead ?

Query fails with stackoverflow error.
error.log

Environment

  • Spring Data JPA version: 3.1.0
  • Hibernate (hibernate-core-6.2.2.Final, hibernate-commons-annotations-6.0.6.Final, hibernate-validator-8.0.0.Final.jar)
  • spring-data-jpa-entity-graph version: 3.0.1

Link to an automated test demonstrating the problem

Unfortunately I was unable to reproduce this on sample project and I can't share my project. Will try to investigate this further but maybe stacktrace can be of some help to understand what is going on.

Additional context

n/a

@mr-nothing
Copy link
Author

mr-nothing commented Aug 3, 2023

BTW This is probably somehow related to kotlin(the project I'm working on is written in Kotlin), since spring may create some additional proxies for repositories in Kotlin (or can do this in a specific way) and, as a consequence, DefaultEntityGraphMethods can't do it's job to call defaultEntityGraph to get default entity graph for repository.

@reda-alaoui
Copy link
Member

Hello @mr-nothing ,

It looks like we need to add a recursive gard. But we have to imagine an automated test allowing to reproduce the issue first.

@mr-nothing
Copy link
Author

Hello, @reda-alaoui and thanks a lot for reply
I was able to fix this issue with use of some kotlin compiler compatibility tweaks. The only possible way to make default entity graphs work in kotlin project is to implement repository like this:

@Repository
@JvmDefaultWithoutCompatibility <<<---------------- This line makes all the magic
interface MyEntityRepository : EntityGraphJpaRepository<MyEntity, String> {
    override fun defaultEntityGraph(): Optional<EntityGraph> {
        return Optional.of(
            DynamicEntityGraph.loading(listOf("field1", "field2", "field3", "field4"))
        )
    }
// Here goes some custom methods
}

Instead of @JvmDefaultWithoutCompatibility you can use @JvmDefaultCompatibility or deprecated @JvmDefault. Besides this kotlin compiler need to be instructed to use jvm-default flag:

compileKotlin {
    kotlinOptions.freeCompilerArgs = ['-Xjvm-default=all']    <<<---There are some options for jvm-default flag, refer documentation
}

All the stuff above makes kotlin compiler generate java 8 compatible default interface methods instead of public static final (kinda companion) class that contains this implementation. See SO thread for more details.

I will try to make a test case for this issue so we can understand how we can defend this lib from stackoverflow errors with kotlin. Also it would be nice to mention this kind of issues in documnetation.

@reda-alaoui reda-alaoui changed the title Specifying default dynamic entity graph make query fail with Stackoverflow exception In Kotlin, specifying default entity graph make query fail with Stackoverflow exception Aug 3, 2023
@reda-alaoui reda-alaoui changed the title In Kotlin, specifying default entity graph make query fail with Stackoverflow exception In Kotlin, specifying a default entity graph make query fail with Stackoverflow exception Aug 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants