quarkiverse / quarkus-cxf

Quarkus CXF Extension to support SOAP based web services.
Apache License 2.0
79 stars 60 forks source link

Native Executable: java.lang.IllegalStateException: Failed to find class `com.fasterxml.jackson.databind.ext.CoreXMLSerializers #1133

Closed kjq closed 11 months ago

kjq commented 11 months ago

I am more than likely missing something I think.

JVM mode runs fine / Native executable fails with this:

Failed to find class `com.fasterxml.jackson.databind.ext.CoreXMLSerializers` for handling values of type `com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl`, problem: (java.lang.ClassNotFoundException) com.fasterxml.jackson.databind.ext.CoreXMLSerializers: java.lang.IllegalStateException: Failed to find class `com.fasterxml.jackson.databind.ext.CoreXMLSerializers` for handling values of type `com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl`, problem: (java.lang.ClassNotFoundException) com.fasterxml.jackson.databind.ext.CoreXMLSerializers
        at com.fasterxml.jackson.databind.ext.OptionalHandlerFactory.instantiate(OptionalHandlerFactory.java:242)
        at com.fasterxml.jackson.databind.ext.OptionalHandlerFactory.findSerializer(OptionalHandlerFactory.java:163)
        at com.fasterxml.jackson.databind.ser.BasicSerializerFactory.findOptionalStdSerializer(BasicSerializerFactory.java:496)
        at com.fasterxml.jackson.databind.ser.BasicSerializerFactory.findSerializerByPrimaryType(BasicSerializerFactory.java:432)
        at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:235)
        at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:174)
        at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1503)
        at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1451)
        at com.fasterxml.jackson.databind.SerializerProvider.findPrimaryPropertySerializer(SerializerProvider.java:717)
        at com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap.findAndAddPrimarySerializer(PropertySerializerMap.java:64)
        at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._findAndAddDynamic(BeanPropertyWriter.java:901)
        at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:710)
        at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:772)
        at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
        at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:732)
        at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:772)
        at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
        at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:732)
        at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:772)
        at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
        at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:479)
        at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:318)
        at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1572)
        at com.fasterxml.jackson.databind.ObjectWriter._writeValueAndClose(ObjectWriter.java:1273)
        at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString(ObjectWriter.java:1140)
        at org.jboss.resteasy.reactive.server.jackson.JacksonMessageBodyWriterUtil.doLegacyWrite(JacksonMessageBodyWriterUtil.java:63)
        at io.quarkus.resteasy.reactive.jackson.runtime.serialisers.BasicServerJacksonMessageBodyWriter.writeTo(BasicServerJacksonMessageBodyWriter.java:48)
        at org.jboss.resteasy.reactive.server.core.StreamingUtil.serialiseEntity(StreamingUtil.java:75)
        at org.jboss.resteasy.reactive.server.core.StreamingUtil.send(StreamingUtil.java:36)
        at org.jboss.resteasy.reactive.server.handlers.PublisherResponseHandler$StreamingMultiSubscriber.onNext(PublisherResponseHandler.java:134)
        at io.smallrye.mutiny.helpers.HalfSerializer.onNext(HalfSerializer.java:30)
        at io.smallrye.mutiny.helpers.StrictMultiSubscriber.onItem(StrictMultiSubscriber.java:84)
        at io.smallrye.mutiny.operators.multi.MultiConcatMapOp$ConcatMapMainSubscriber.tryEmit(MultiConcatMapOp.java:188)
        at io.smallrye.mutiny.operators.multi.MultiConcatMapOp$ConcatMapInner.onItem(MultiConcatMapOp.java:282)
        at io.smallrye.mutiny.operators.multi.builders.IterableBasedMulti$IteratorSubscription.slowPath(IterableBasedMulti.java:159)
        at io.smallrye.mutiny.operators.multi.builders.IterableBasedMulti$IteratorSubscription.request(IterableBasedMulti.java:71)
        at io.smallrye.mutiny.subscription.SwitchableSubscriptionSubscriber.setOrSwitchUpstream(SwitchableSubscriptionSubscriber.java:205)
        at io.smallrye.mutiny.subscription.SwitchableSubscriptionSubscriber.onSubscribe(SwitchableSubscriptionSubscriber.java:107)
        at io.smallrye.mutiny.operators.multi.builders.IterableBasedMulti.subscribe(IterableBasedMulti.java:48)
        at io.smallrye.mutiny.operators.multi.builders.IterableBasedMulti.subscribe(IterableBasedMulti.java:32)
        at io.smallrye.mutiny.operators.AbstractMulti.subscribe(AbstractMulti.java:39)
        at io.smallrye.mutiny.operators.multi.MultiConcatMapOp$ConcatMapMainSubscriber.onItem(MultiConcatMapOp.java:150)
        at io.smallrye.mutiny.subscription.MultiSubscriber.onNext(MultiSubscriber.java:61)
        at io.smallrye.mutiny.operators.multi.MultiRepeatUntilOp$RepeatUntilProcessor.onItem(MultiRepeatUntilOp.java:128)
        at io.smallrye.mutiny.subscription.MultiSubscriber.onNext(MultiSubscriber.java:61)
        at io.smallrye.mutiny.converters.uni.UniToMultiPublisher$UniToMultiSubscription.onItem(UniToMultiPublisher.java:92)
        at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:43)
        at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onItem(UniOperatorProcessor.java:47)
        at io.smallrye.mutiny.operators.uni.builders.UniCreateFromFuture.lambda$dispatchDeferredResult$1(UniCreateFromFuture.java:96)
        at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base@21.0.1/java.lang.Thread.runWith(Thread.java:1596)
        at java.base@21.0.1/java.lang.Thread.run(Thread.java:1583)
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:832)
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:211)

Quarkus: 3.6.1 (and using CXF BOM from there)

ppalaga commented 11 months ago

Thanks for the report, @kjq! It is quite possible that the class needs to be registered for reflections, which would be an omission on our side. I wonder whether you could give a hint how to reproduce this, so that we can add a test to see that the fix really works?

The following could work as a quick workaround on your side: just add a class like this to your application:

@RegisterForReflection(classNames = "com.fasterxml.jackson.databind.ext.CoreXMLSerializers")
class ReflectionRegistrations {}
kjq commented 11 months ago

Working on getting you a reproducer.

Interestingly enough, when I add @RegisterForReflection(classNames = "com.fasterxml.jackson.databind.ext.CoreXMLSerializers") seems to blow the native build out of the water with OOM.

Removing it builds natively successfully / including it, no matter what XMX, throws an OOM.

kjq commented 11 months ago

I could not replicate it using a simple example using a public Calculator service, ill have to work on it some more but i was able to get a better error - around this com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl which may be the culprit.

Failed to find class `com.fasterxml.jackson.databind.ext.CoreXMLSerializers` for handling values of type `com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl`, problem: (java.lang.ClassNotFoundException) com.fasterxml.jackson.databind.ext.CoreXMLSerializers: java.lang.IllegalStateException: Failed to find class `com.fasterxml.jackson.databind.ext.CoreXMLSerializers` for handling values of type `com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl`, problem: (java.lang.ClassNotFoundException) com.fasterxml.jackson.databind.ext.CoreXMLSerializers

For whatever reason today, adding the suggested work-around, works now so I probably just messed something up before.

@RegisterForReflection(
    classNames = "com.fasterxml.jackson.databind.ext.CoreXMLSerializers")
class ExampleRegistration {
}
ppalaga commented 11 months ago

I'd still be interested to know how to reproduce this. Do you happen to have JAXB entities with some sort of date/time fields? What type are they exactly?

kjq commented 11 months ago

I think it does have to do with the entities but i need to whittle it down to give you a reproducer.

ppalaga commented 11 months ago

I have added a service with with java.util.Calendar and java.time.LocalDateTime params in https://github.com/quarkiverse/quarkus-cxf/pull/1144 and they work just fine.

kjq commented 11 months ago

Still working through trying to get you a reproducer (balancing with getting a first cut of this service out).

There are generated types like this:

    @XmlElement(name = "Source", required = true)
    protected String source;
    @XmlElement(name = "ProvidedOn")
    @XmlSchemaType(name = "dateTime")
    protected XMLGregorianCalendar providedOn;

Lining up to this in the XSD

<xs:complexType name="LabelDataSource">
        <xs:sequence>
            <xs:element name="Source" type="fssi:String15" minOccurs="1" maxOccurs="1" />
            <xs:element name="ProvidedOn" type="xs:dateTime" minOccurs="0" maxOccurs="1" />
        </xs:sequence>
    </xs:complexType>
kjq commented 11 months ago

Interestingly enough, I did the following because I was either having issues compiling natively (blowing the heap) or serialization issues as well but it seems I can create a shared API (where I do the WSDL generation), a gateway service that calls the SOAP service using a RESTClient, and the Quarkus SOAP service. End-to-end they all work in jvm/native mode now.

  1. I moved my WSDL generation to another dependency so I could share it between project. Marked CXF as optional in this POM and generated the service/entities.

  2. Created a gateway that uses a RESTClient to talk to the Quarkus CXF SOAP service. Included the CXF extension.

I had to add this to the gateway service and now it works JVM/native:

@RegisterForReflection(
    classNames = {
            "com.fasterxml.jackson.databind.ext.CoreXMLSerializers",
            "com.fasterxml.jackson.databind.ext.CoreXMLDeserializers"})
class GatewayApplication {
}
  1. Have the original Quarkus CXF SOAP service (where I started out with the issues) with this. CXF and HC5 is included here. This service works JVM/Native.
@RegisterForReflection(
    classNames = "com.fasterxml.jackson.databind.ext.CoreXMLSerializers")
class SOAPApplication {
}

The error is pretty much the same as before but adding the @RegisterForReflection did get me past it.

For whatever reason also, depending on how I included the Quarkus CXF extension in the POM mixed with the @RegisterForReflection it would blow up consistently when compiling natively on the heap (and I have more than enough allocated to it). Ill pay attention to this later and see if I can produce an example as well.

ppalaga commented 11 months ago

I have added a test that serializes javax.xml.datatype.XMLGregorianCalendar in https://github.com/quarkiverse/quarkus-cxf/pull/1159 and it works as expected.

Looking once again at your original stack trace, the exception is thrown when RESTeasy serializes your entity to JSON. I believe this is not something we should fix in Quarkus CXF. Indeed the issue is reproducible on plain Quarkus. I have filed https://github.com/quarkusio/quarkus/issues/37934 and submitted a reproducer https://github.com/quarkusio/quarkus/pull/37935

kjq commented 11 months ago

Makes sense. Thank you for your help, I appreciated it.