-
Notifications
You must be signed in to change notification settings - Fork 38.1k
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
StackOverflowError when using WebFlux multipart file data handler with Undertow [SPR-16545] #21088
Comments
Tamas Eppel commented With Netty as server it seems to be working. |
Tamas Eppel commented Additionally it seems that the example: https://github.com/sdeleuze/webflux-multipart/ Does not compile anymore. Errors in: https://github.com/sdeleuze/webflux-multipart/blob/master/src/main/java/com/example/MultipartController.java It would be good to have this documented as well. The official docs only mention the Controller based approach and not the Router-Handler approach: https://docs.spring.io/spring/docs/5.0.4.RELEASE/spring-framework-reference/web-reactive.html#webflux-multipart-forms |
Rossen Stoyanchev commented I've created a PR to update the sample. In the process of upgrading the sample, I did find and address one other issue, see #21089. After that, with the latest (Boot 2.0 GA, Spring Framework 5.0.5 snapshot) I am unable to reproduce the Undertow issue. Note that in the sample I removed the explicit (outdated 1.0.2) version of Would you mind retrying with the updates to confirm? |
Rossen Stoyanchev commented Also for the documentation updates I've created a separate ticket #21090 since it requires some restructuring. |
Tamas Eppel commented I have used the updated sample. With Undertow I get the same StackOverflow. With Netty it works. |
Rossen Stoyanchev commented Hm, it works fine for me:
|
Tamas Eppel commented I am sorry for the late reply, was on holiday. I have prepared a sample project. (zip, and input files attached) Steps to reproduce:
To switch to netty uncomment the netty line in build.gradle and comment out undertow. |
Rossen Stoyanchev commented I spend some time trying to get the docker-compose command to run but but failed (and I'm not familiar enough). Is it possible to provide something that doesn't require Docker and Kafka to demonstrate the issue? For example can you make it fail in the webflux-multipart sample? Looking at your MultimediaHandler, this code looks problematic: val filePart = parts.getFirst("import") as FilePart
filePart.transferTo(tmpFile.toFile())
.then(Mono.just(Files.newBufferedReader(tmpFile).lines().use { it.forEach { importProcessor.importLine().send(GenericMessage<String>(it)) } }))
.then(ServerResponse.ok().body(BodyInserters.fromObject(importId.toString()))) You want val filePart = parts.getFirst("import") as FilePart
filePart.transferTo(tmpFile.toFile())
.then(Mono.defer(() -> {
// read file ..
return ServerResponse.ok().body(BodyInserters.fromObject(importId.toString()));
}); Even then the file reading and calls to importLine are synchronously executed and potentially blocking but they shouldn't block the event loop thread? I'm not sure if the send is blocking or not given it's Kafka. I presume it might in which case you might have to use publishOn. All of those things aren't the original issue, but again I need a sample I can execute to be more specific or a full stack trace at least. |
Tamas Eppel commented I have uploaded one without kafka/docker. Thanks for the suggestions. My original intention was to send each line on the file as it arrives, but then I realized I would need to parse the characters for new line (because a line can be in more parts) so I just do with the tempfile approach. |
Rossen Stoyanchev commented Okay I'll take a look at this sample. As for your intent, it sounds like you might want to feed the raw |
Tamas Eppel commented Thanks for the suggestion I have rewritten it like this: package de.techmatrix.dc.matcher.handler
import de.techmatrix.dc.matcher.component.UploadService
import org.springframework.core.ResolvableType
import org.springframework.core.codec.StringDecoder
import org.springframework.core.io.buffer.DataBuffer
import org.springframework.stereotype.Component
import org.springframework.util.MimeTypeUtils
import org.springframework.web.reactive.function.BodyExtractors
import org.springframework.web.reactive.function.BodyInserters
import org.springframework.web.reactive.function.server.ServerRequest
import org.springframework.web.reactive.function.server.ServerResponse
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import reactor.core.publisher.toFlux
import reactor.core.scheduler.Schedulers
import java.util.*
fun dataBuffers(request: ServerRequest): Flux<DataBuffer> =
request.body(BodyExtractors.toMultipartData())
.toFlux()
.publishOn(Schedulers.parallel())
.flatMap { parts -> parts.flatMap { it.value }.toFlux() }.flatMap { it.content() }
@Component
class MultimediaHandler(val uploadService: UploadService) {
fun upload(request: ServerRequest): Mono<ServerResponse> {
val importId = UUID.randomUUID()
return StringDecoder.allMimeTypes().decode(
dataBuffers(request), ResolvableType.forClass(String::class.java), MimeTypeUtils.TEXT_PLAIN, emptyMap())
.index()
.publishOn(Schedulers.parallel())
.doOnNext { uploadService.importLine(importId, it.t2, it.t1.toInt()) }
.map { 1 }
.reduce { a, b -> a + b }
.doOnSuccess { uploadService.importFinished(importId, it) }
.then(ServerResponse.ok().body(BodyInserters.fromObject(importId.toString())))
}
} It would be quite good to describe this, I did not find anything in the WebFlux documentation, or by searching. |
Rossen Stoyanchev commented Okay, thanks for that. I've been able to confirm the recursion issue:
This is triggered by the
The codecs are documented here. We have planned #21081. Any clues what you searched on, or what you expected to find? |
Rossen Stoyanchev commented This should be fixed now with f9df8c. Violeta Georgieva if you could, please take a look to see if this fix raises any concerns. |
Violeta Georgieva commented LGTM |
Tamas Eppel opened SPR-16545 and commented
I am using Spring Boot 2 RC2 - Spring 5.0.3 with WebFlux and the Router abstraction. The server is Undertow.
I have created the handler according to: https://github.com/sdeleuze/webflux-multipart/blob/master/src/main/java/com/example/MultipartRoute.java
I have a router handler like this:
I am getting a StackOverflowError:
Affects: 5.0.3
Attachments:
Issue Links:
Referenced from: commits f9df8c7
The text was updated successfully, but these errors were encountered: