Closed pmendelski closed 4 months ago
Thanks for the sample. BlockHound has detected two blocking calls:
Both of these are triggered from Spring Framework code. We'll transfer this issue to the Framework repository so that they can take a look.
Perfect, thanks
I am not able to reproduce this particular issue.
When I clone the project, BlockHound does not appear to be used.
After adding BlockHound.install()
in the main method, I get a different BlockHound error:
Caused by: reactor.blockhound.BlockingOperationError: Blocking call! java.io.RandomAccessFile#readBytes
at java.base/java.io.RandomAccessFile.readBytes(RandomAccessFile.java)
at java.base/java.io.RandomAccessFile.read(RandomAccessFile.java:406)
at java.base/java.io.RandomAccessFile.readFully(RandomAccessFile.java:470)
at java.base/java.util.zip.ZipFile$Source.readFullyAt(ZipFile.java:1318)
at java.base/java.util.zip.ZipFile$ZipFileInputStream.initDataOffset(ZipFile.java:1003)
at java.base/java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:1018)
at java.base/java.util.zip.ZipFile$ZipFileInflaterInputStream.fill(ZipFile.java:468)
at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:159)
at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:123)
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:83)
at java.base/java.io.DataInputStream.readInt(DataInputStream.java:392)
at kotlin.reflect.jvm.internal.impl.metadata.builtins.BuiltInsBinaryVersion$Companion.readFrom(BuiltInsBinaryVersion.kt:29)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins.BuiltInsPackageFragmentImpl$Companion.create(BuiltInsPackageFragmentImpl.kt:38)
at kotlin.reflect.jvm.internal.impl.builtins.jvm.JvmBuiltInsPackageFragmentProvider.findPackage(JvmBuiltInsPackageFragmentProvider.kt:61)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.AbstractDeserializedPackageFragmentProvider$fragments$1.invoke(AbstractDeserializedPackageFragmentProvider.kt:35)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.AbstractDeserializedPackageFragmentProvider$fragments$1.invoke(AbstractDeserializedPackageFragmentProvider.kt:34)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:578)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.AbstractDeserializedPackageFragmentProvider.collectPackageFragments(AbstractDeserializedPackageFragmentProvider.kt:43)
at kotlin.reflect.jvm.internal.impl.descriptors.PackageFragmentProviderKt.collectPackageFragmentsOptimizedIfPossible(PackageFragmentProvider.kt:50)
at kotlin.reflect.jvm.internal.impl.descriptors.impl.CompositePackageFragmentProvider.collectPackageFragments(CompositePackageFragmentProvider.kt:47)
at kotlin.reflect.jvm.internal.impl.descriptors.PackageFragmentProviderKt.collectPackageFragmentsOptimizedIfPossible(PackageFragmentProvider.kt:50)
at kotlin.reflect.jvm.internal.impl.descriptors.impl.CompositePackageFragmentProvider.collectPackageFragments(CompositePackageFragmentProvider.kt:47)
at kotlin.reflect.jvm.internal.impl.descriptors.PackageFragmentProviderKt.collectPackageFragmentsOptimizedIfPossible(PackageFragmentProvider.kt:50)
This error appears to be coming from Kotlin itself, not Spring. I am running on macOS, not Ubuntu.
Could you please verify that the sample reproduces the issue?
It reproduced it for me, @poutsma. Did you check out the blockhound-error
branch? IIRC, I was tripped up initially as I forgot to do so and the default branch doesn't reproduce the problem.
Thanks for pointing that out, @wilkinsona. I must have read over that branch name.
I can reproduce the issue now, but do not think it's possible to solve without changing the contract of AbstractUrlBasedView::checkResourceExists(Locale)
and FreeMarkerView::getTemplate(Locale)
. If these would return a Mono
instead of a concrete type, we could schedule them to occur on the bounded elastic scheduler, like we do with other blocking code.
Do you see another way to solve this, @rstoyanchev ?
Here a WIP commit that fixes the Blockhound error, but changes the signature of several protected methods:
https://github.com/poutsma/spring-framework/commit/e1989e81e3536d5b844fb84d44f265c40fd48949
Thanks for looking at this problem.
I can see that you moved the blocking operation to Schedulers.boundedElastic()
. There is one edge case though. When template uses a lazy import to another template, the imported template is read in resolution phase. I'm not a pro in FreeMarker but I would test it.
Closed in favor of #30903.
There is a blocking call detected by BlockHound when FreeMarker template is loaded Spring Boot WebFlux 2.4.4 application. Program was run with JDK 11 on Ubuntu 20.04.1.
I created a sample project that contains basic configuration with single FreeMarker template and two endpoints. When page is fetched Blockhound detects an error.
In most cases each template is loaded once and is stored in the FreeMarker cache, but what about a case when cache is deliberately disabled or templates are loaded from DB?