Using Spring Boot WebFlux 2.4.3, there are blocking calls, detected by BlockHound when properties are loaded during the call. Program was run with JDK 11 on Windows 10.

A simple program is attached. It contains a few static images, but when a unexisting image is requested, BlockHound detects a blocking call when the framework reads a properties file, to find the configuration for the error handling.

See the test class in the attached program.

spring-reactor-webflux-blockhound properties.zip

Comment From: wilkinsona

Thanks @JanVdloock. As discussed on Gitter this should be a Framework issue. We’ll transfer it over.

Comment From: rstoyanchev

From Gitter:

Having Spring Boot 2.4.3 with webflux and BlockHound.install(), getting static content (e.g. /error.png) throws a blocking call exception from BlockHound :

reactor.blockhound.BlockingOperationError: Blocking call! java.io.RandomAccessFile#readBytes
at java.base/java.io.RandomAccessFile.readBytes(RandomAccessFile.java) ~[na:na]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ HTTP GET "/error.png" [ExceptionHandlingWebHandler]
Stack trace:
at java.base/java.io.RandomAccessFile.readBytes(RandomAccessFile.java) ~[na:na]
at java.base/java.io.RandomAccessFile.read(RandomAccessFile.java:406) ~[na:na]
at java.base/java.io.RandomAccessFile.readFully(RandomAccessFile.java:470) ~[na:na]
at java.base/java.util.zip.ZipFile$Source.readFullyAt(ZipFile.java:1298) ~[na:na]
at java.base/java.util.zip.ZipFile$ZipFileInputStream.initDataOffset(ZipFile.java:997) ~[na:na]
at java.base/java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:1012) ~[na:na]
at java.base/java.util.zip.ZipFile$ZipFileInflaterInputStream.fill(ZipFile.java:467) ~[na:na]
at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:159) ~[na:na]
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:133) ~[na:na]
at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) ~[na:na]
at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) ~[na:na]
at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) ~[na:na]
at java.base/java.io.InputStreamReader.read(InputStreamReader.java:185) ~[na:na]
at java.base/java.io.BufferedReader.fill(BufferedReader.java:161) ~[na:na]
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:326) ~[na:na]
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:392) ~[na:na]
at org.springframework.http.MediaTypeFactory.parseMimeTypes(MediaTypeFactory.java:71) ~[spring-web-5.3.4.jar:5.3.4]
at org.springframework.http.MediaTypeFactory.<clinit>(MediaTypeFactory.java:47) ~[spring-web-5.3.4.jar:5.3.4]
at org.springframework.web.reactive.resource.ResourceWebHandler.getMediaType(ResourceWebHandler.java:579) ~[spring-webflux-5.3.4.jar:5.3.4]
at org.springframework.web.reactive.resource.ResourceWebHandler.lambda$handle$2(ResourceWebHandler.java:407) ~[spring-webflux-5.3.4.jar:5.3.4]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125) ~[reactor-core-3.4.3.jar:3.4.3]
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:73) ~[reactor-core-3.4.3.jar:3.4.3]

Comment From: rstoyanchev

We can create a Blockhound rule to suppress it since this only happens once.