Skip to content

ControllerLinkBuilder doesn't work with Groovy/Kotlin #222

Open
@danveloper

Description

@danveloper

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions