I have to create a custom logging provider for my Quarkus application to convert the log entries to the Google Cloud JSON format.
For this, the provider class (which is written in Kotlin) has to extend an abstract class called ExtFormatter (from a 3rd-party lib, written in Java), which has these two methods:
package org.jboss.logmanager;
[...]
public abstract class ExtFormatter extends Formatter {
public final String format(final LogRecord record) {
return format(ExtLogRecord.wrap(record));
}
[...]
}
public abstract String format(ExtLogRecord record);
ExtLogRecord is a subclass of LogRecord, so the method signatures are quite similar.
My logging provider implements the abstract method like this:
import io.quarkiverse.loggingjson.JsonProvider
import org.jboss.logmanager.ExtFormatter
import org.jboss.logmanager.ExtLogRecord
[...]
class JsonLoggingProvider : JsonProvider, ExtFormatter() {
override fun format(extLogRecord: ExtLogRecord?) = null
}
When I run the application (not at compile time), I get this error:
java.lang.VerifyError: class com.mycompany.logging.JsonLoggingProvider_Subclass overrides final method org.jboss.logmanager.ExtFormatter.format(Ljava/util/logging/LogRecord;)Ljava/lang/String;
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:437)
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:397)
at com.mycompany.logging.JsonLoggingProvider_Bean.create(JsonLoggingProvider_Bean.zig:368)
at com.mycompany.logging.JsonLoggingProvider_Bean.create(JsonLoggingProvider_Bean.zig:394)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at com.mycompany.logging.JsonLoggingProvider_Bean.get(JsonLoggingProvider_Bean.zig:426)
at com.mycompany.logging.JsonLoggingProvider_Bean.get(JsonLoggingProvider_Bean.zig:442)
at io.quarkus.arc.impl.InstanceImpl.getBeanInstance(InstanceImpl.java:210)
at io.quarkus.arc.impl.InstanceImpl$InstanceIterator.next(InstanceImpl.java:246)
at java.base/java.lang.Iterable.forEach(Iterable.java:74)
at io.quarkiverse.loggingjson.LoggingJsonRecorder.initializeJsonLogging(LoggingJsonRecorder.java:62)
at io.quarkus.deployment.steps.LoggingJsonProcessor$setUpFormatter-614569086.deploy_0(LoggingJsonProcessor$setUpFormatter-614569086.zig:88)
at io.quarkus.deployment.steps.LoggingJsonProcessor$setUpFormatter-614569086.deploy(LoggingJsonProcessor$setUpFormatter-614569086.zig:40)
at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:666)
at io.quarkus.runtime.Application.start(Application.java:101)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:101)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:66)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:42)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:119)
at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:98)
at java.base/java.lang.Thread.run(Thread.java:829)
For some reason the wrong method (or both methods?) seem to be overridden.
I suspect that it happens because the methods have more or less the same signature.
Is there a way to make the Kotlin override more precise to avoid this issue?