-
Notifications
You must be signed in to change notification settings - Fork 320
Kotlin coroutines handler don't work with "org.springframework.boot:spring-boot-starter-validation" #344
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
Comments
Are you using the latest version of the library? I remember having some issues with coroutines, but with the later versions this all works fine. |
everything from milestone:
|
I think the issue lies somewhere else in your code; if I create a sample app using https://start.spring.io and create something similar as what you commented above everything is working fine. data class PersonInput(
val firstName: String,
val lastName: String
)
@Controller
class PersonController(private val personService: PersonService) {
@MutationMapping("createPerson")
suspend fun createPerson(@Argument("input") personInput: PersonInput): Person {
return personService.createPerson()
}
}
// ...
@Service
class PersonService {
fun createPerson(): Person {
return Person(firstName = "Foo")
}
}
// ...
data class Person(val firstName: String) # src/main/resources/graphql/schema.graphqls
schema {
query: Query
mutation: Mutation
}
type Query {
hello: String
}
input PersonInput {
firstName: String
lastName: String
}
type Person {
id: ID
firstName: String
lastName: String
}
type Mutation {
createPerson(input: PersonInput): Person
} |
Ok I found problem. It is because of Line 78 in b40375f
and stack trace:
|
You're using |
No, funniest fact is that I haven't added validation yet, only package. I have similar problem with query mapping. @Controller
class PersonController(val service: PersonService) {
@QueryMapping
suspend fun people(): List<Person> {
return service.getAllPeople()
}
@MutationMapping( "createPerson")
suspend fun createPerson(@Argument("input") personInput: PersonInput) : Person {
return Person(firstName = personInput.firstName, lastName = personInput.lastName, id = null)
}
} and error:
What you expect to share? |
It is an old issues when using validation with Kotlin Coroutines. And there are some solutions in the original issues. For Kotlin Coroutines, when compiling, there is an additional There are several issues like this in Spring issue tracker, but they did think it is should be fixed by the upstream projects. @nenros Check my example includes a solution from the issue comments, https://github.com/hantsy/spring-puzzles/tree/master/validation-ktco I think you can use the same method to resolve this issue. |
@hantsy I think that problem is in spring-graphql as this @RestController
@RequestMapping("/person")
class PersonRestController(val personService: PersonService) {
@GetMapping
suspend fun listPeople(): Flow<Person> {
return personService.getAllPeople()
}
@PostMapping
suspend fun createPerson(@Valid @RequestBody personInput: PersonInput) : Person {
return personService.createPerson();
}
} works correctly |
@nenros since your stack trace shows I'm using |
@nenros Your example is validating the request body, if you validate the request param in the method, you will encounter this problem. spring-projects/spring-framework#23499 (comment) It is a little wired, spring uses different mechanism to process the arg validation and request body validation. |
Indeed what @hantsy shared has links to issues that are referring to the same stacktrace. Originally reported in spring-projects/spring-framework#23499 and then corresponding issue in HV https://hibernate.atlassian.net/browse/HV-1638. It is a lower level issue, we're simply invoking Hibernate Validator which fails while introspecting method parameters. There is one workaround posted in spring-projects/spring-framework#23499 (comment) customizing parameter discovery, but I have not tried or evaluated it.
This is a good point @nenros as currently we are invoking HV for every method as long as bean validation is present but could consider doing so only for methods with |
adding magic configuration helped |
I've updated the documentation on this. |
Hi. class Foo(
val bar: Boolean = true
)
@Controller
class SuspendTestController {
@QueryMapping
fun foo(): Foo {
return Foo()
}
private suspend fun theSuspend(): String {
return "123"
}
} I think this is a very breaking behavior. |
@turboezh you must have |
@rstoyanchev, yes, I need a validation so I have I discovered that declaring such a bean magically fixes the problem: @Bean
fun validator(): Validator {
return Validation.buildDefaultValidatorFactory().validator
} I took it from Eventually it leads to utilizing In fail case So I see this error not in the Spring and not in HV. It is in communication between them. In some other projects I use to validate GraphQL controllers with Is there any benefits from "manually" invoking HV for every method (as you mentioned) instead of just using AOP |
Thanks for the commenting. I can't really comment on your approach. It sounds like what you have works for you, but there be cases that don't if you exclude In terms of not relying on I wonder if we should simply suppress validation for coroutine methods while this remains an issue? We could further couple that we checks on startup to reject coroutine methods that method or parameter validation annotations. |
On further thought and some internal discussion, I've created #445, which should address the points you're raising about control and validation via AOP vs the built-in support. In effect, validation should become opt-in and will not impact methods that aren't expressing using any validation annotations. |
Sorry, I forgot to describe one more important detail that I mentioned in my first comment. HV |
Thanks for the tip, please continue the discussion under #445. |
Uh oh!
There was an error while loading. Please reload this page.
Hi!
I have problems with Webflux + Kotlin + Coroutines. When I have something like that:
and I try to make request
I get
But when I change to response type mono
request works
After some investigation I found that problem was in validation starter:
and this is wrong line
spring-graphql/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/HandlerMethodInputValidator.java
Line 78 in b40375f
question if it isn't related to https://hibernate.atlassian.net/browse/HV-1796
The text was updated successfully, but these errors were encountered: