spring-projects / spring-projects/spring-hateoas

ControllerLinkBuilder doesn't work with Groovy/Kotlin

Open
#222 14 comments 5 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

kotlin
Dominant language
Java
Stars
1.1k
Forks
476
PR merge metrics
No merged PRs in 30d

Description

The InvocationRecordingMethodInterceptor overflows the stack when using non-statically compiled Groovy. The problem exists because the interceptor is returning a new proxy with each invocation, and Groovy's method dispatching workflow inspects the metaClass of each object to determine the appropriate call site to use.

Simple example demonstrating the issue:

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableJpaRepositories
@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
class Main {
  static void main(_) {
     SpringApplication.run this, [] as String[]
  }
}

@javax.persistence.Entity
class Foo {
  @javax.persistence.Id
  Long id
  String name
}

@Repository
interface Foos extends CrudRepository<Foo, Long> {
}

@RestController
@RequestMapping("/foo")
class FooController {

  @Autowired
  Foos foos

  @RequestMapping(method = GET)
  Resources<Foo> list() {
    def foos = foos.findAll()
    def resources = new Resources<>(foos)
    if (resources) {
      resources.add(linkTo(methodOn(this.class).list()).withSelfRel())
    }
    resources
  }
}

A "fix" would be to statically compile the FooController, but this means that we can't use the metaClass:

@CompileStatic
@RestController
@RequestMapping("/foo")
class FooController {
  ...
}

I'm not sure what the best solution to this is... It seems like there should be a way to ascertain if the current invocation is identical to the last invocation, though I'm not sure how that could be determined given a new proxy object is returned each time. Probably need help from @melix on this one.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the InvocationRecordingMethodInterceptor and reproduce the stack overflow using the Groovy example in the issue, focusing on ControllerLinkBuilder and methodOn. Investigate how repeated proxy creation interacts with Groovy metaClass dispatch and Kotlin usage. Done means the example no longer overflows while link generation continues to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
groovy, java, kotlin, spring
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.