Skip to content

Controllers implementing interfaces not mapped when the observability module is used #933

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

Closed
anguzo opened this issue Nov 14, 2024 · 5 comments
Assignees
Labels
in: observability Observability support type: improvement Minor improvements
Milestone

Comments

@anguzo
Copy link

anguzo commented Nov 14, 2024

Description

When using Interface-Driven Controllers in a Spring project configured with spring-web, spring-modulith, and spring-boot-actuator, the controllers do not function as expected. The issue appears specifically when including spring-modulith-observability as a runtime dependency.

For example, the following setup fails to work:

@RestController
class HelloController : HelloResource {
    override fun hello(testText: String): String {
        return testText
    }
}

interface HelloResource {
    @GetMapping("/api/hello")
    fun hello(@RequestParam("testText") testText: String): String
}

Reproducing the Issue

Here is a minimal sample to reproduce the issue:
demo.zip

When adding runtimeOnly("org.springframework.modulith:spring-modulith-observability") in the Gradle configuration, Interface-Driven Controllers fail to function. Removing this dependency allows the controllers to work as expected.

Expected Behavior

The application should process requests to the /api/hello endpoint and return the provided testText parameter as expected.

Observed Behavior

When spring-modulith-observability is included as a dependency, the endpoint does not work.

@anguzo
Copy link
Author

anguzo commented Nov 14, 2024

I will also include Java/Maven based minimal sample, the problem persists in it as well.
demo_java.zip

@odrotbohm
Copy link
Member

This kind of works as designed. We use the default setup of ProxyFactory to create the proxy required to add the observability interceptors. That in turn uses JDK proxies if the object to be proxied implements interfaces. As a result of that, the resulting proxy class does not carry the@RestController annotation of the original class. That annotation missing on the proxy type is the reason that Spring MVC then does not scan that type for mapping annotations.

An easy and recommended workaround is to consistently keep the annotations on the interface, if you decide to implement interfaces with the controller.

I think for 1.4, we should move to pick up the proxying mechanism globally configured for the Spring Boot application (it already seems to default to class-based proxies), but it's too late to change that for 1.3.

@odrotbohm odrotbohm self-assigned this Nov 15, 2024
@odrotbohm odrotbohm added in: observability Observability support type: improvement Minor improvements labels Nov 15, 2024
@odrotbohm odrotbohm added this to the 1.4 M1 milestone Nov 15, 2024
@odrotbohm odrotbohm changed the title Issue with Interface-Driven Controllers in Spring Modulith Project with Spring Boot Actuator Observability Controllers implementing interfaces not mapped when the observability module is used Nov 15, 2024
odrotbohm added a commit that referenced this issue Nov 22, 2024
We now lookup the AbstractAutoProxyCreator registered for global proxy settings and apply that to the ProxyFactory used to create the proxies applying the observability decoration.
@odrotbohm
Copy link
Member

We now consider the global AOP proxying settings when applying the observability decoration. Please give the 1.4 snapshots a try!

@anguzo
Copy link
Author

anguzo commented Nov 28, 2024

Thank you, tried 1.4.0-SNAPSHOT and the issue is indeed resolved.

@odrotbohm
Copy link
Member

Thanks for the feedback and happy coding! 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: observability Observability support type: improvement Minor improvements
Projects
None yet
Development

No branches or pull requests

2 participants