Im trying to build my quarkus application in native mode using a dependency called EsperTech, and there is a specific snippet of code that after countless hours of debugging I discover that is causing issues for me. Basically it deals with some bytes being written to a buffer and read just after it (where it causes the following error).
java.io.InvalidClassException: my.package.CustomConfigurationClass; no valid constructor
The snippet of code is this one (I adapted to code to kotlin):
import com.espertech.esper.common.internal.util.SimpleByteArrayOutputStream
import com.espertech.esper.common.internal.util.ObjectInputStreamWithTCCL
import my.package.CustomConfigurationClass
import java.io.IOException
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
fun <T> copy(configObj: T): T {
val fbos = SimpleByteArrayOutputStream()
val outStream = ObjectOutputStream(fbos)
try {
outStream.writeObject(orig)
outStream.flush()
} finally {
outStream.close()
}
// ...
val inStream: ObjectInputStream = ObjectInputStreamWithTCCL(fbos.inputStream)
inStream.readObject() // Where the error happens
}
As you can see it throws exactly in the readObject
function, I already checked, and yes, the buffer was properly saved before trying to read from it.
As the error suggests I try to make my class ready for native mode like this (worked for serialization when doing request/response apis, but not for this case, when working with java.io library).
@RegisterForReflection
@kotlinx.serialization.Serializable
data class CustomConfigurationClass(
val name: String = "CustomConfigurationClass",
) : Serializable {
constructor() : this("CustomConfigurationClass") // I know I do not need this but I try it to ensure either way
}
Is there any other way to handle this kind of serialization issues with the java.io
std library?
I am assuming that this is the issue btw, but it can also be something else.
I tried to exclude this piece of code together with the java.io library from the native build using:
gradle build -x test -Dquarkus.package.type=native -Dquarkus.native.additional-build-args="--initialize-at-run-time=java.io\,<esper_package>\,etc"
But also no luck.
Solved!
I used the same solution posted here: Quarkus hibernate Exception in native mode
My serialization-config.json
file:
[
{"name":"java.io.ObjectInputStream"},
{"name":"java.io.ObjectOutputStream"},
{"name":"java.lang.String"},
{"name":"my.custom.package.config.ConfigurationCustom"},
... Other esper library package
]
Every time I re-executed the native build I got this error messages:
Caused by: com.oracle.svm.core.jdk.UnsupportedFeatureError: SerializationConstructorAccessor class not found for declaringClass: com.espertech.esper.common.client.configuration.compiler.ConfigurationCompilerLanguage (targetConstructorClass: java.lang.Object). Usually adding com.espertech.esper.common.client.configuration.compiler.ConfigurationCompilerLanguage to serialization-config.json fixes the problem.
And just by following the suggestions (adding more packages to the serialization-config.json
) I was able to execute successfully.
The only downside is to build every single time just to spot one more class/package to add in my json file, but this is how I manage to solve for now.