Closed turing85 closed 7 months ago
/cc @Karm (mandrel), @galderz (mandrel), @gsmet (jaxb), @zakkak (mandrel)
Hello @turing85,
Can I try to tackle this issue if it's not already in someone's hands? Thanks!
@ibourdier feel free. The ticket is unassigned. Although it might be worth consulting @gsmet first.
Ok thanks! @gsmet can you give his inputs on this issue first please ?
@ibourdier I'm not aware of some working on this actively. please go ahead and dive into the reproducer and investigate.
Sure will do, thanks! I was a bit struggling with setting up the local env to start the reproducer but now it's all done and good.
Hello again ! @maxandersen @turing85 @gsmet I am kind of stuck on this one actually ... :/ If possible I'd like a little bit of help. So far I found out that this particular error is thrown using native compilation :
2023-10-29 14:40:30,050 FINE [jak.xml.bind] (executor-thread-1) Checking system property jakarta.xml.bind.JAXBContextFactory
2023-10-29 14:40:30,050 FINE [jak.xml.bind] (executor-thread-1) not found
2023-10-29 14:40:30,050 FINE [jak.xml.bind] (executor-thread-1) Trying to create the platform default provider
2023-10-29 14:40:30,050 FINE [jak.xml.bind] (executor-thread-1) Unable to find from OSGi: [jakarta.xml.bind.JAXBContextFactory]: java.lang.ClassNotFoundException: org.glassfish.hk2.osgiresourcelocator.ServiceLoader. This exception was synthesized during native image building from a call to java.lang.Class.forName(String) with constant arguments.
I tried to search around if there was a similar issue but got nothing good. I'm not even sure the issue is really coming from Quarkus, it may come from GraalVM instead. What is your point of view on this?
Btw when executing with non-native it seems to be fine :
2023-10-29 14:35:13,769 FINE [jak.xml.bind] (executor-thread-1) Checking system property jakarta.xml.bind.JAXBContextFactory
2023-10-29 14:35:13,769 FINE [jak.xml.bind] (executor-thread-1) not found
2023-10-29 14:35:13,771 FINE [jak.xml.bind] (executor-thread-1) ServiceProvider loading Facility used; returning object [org.glassfish.jaxb.runtime.v2.JAXBContextFactory]
2023-10-29 14:35:13,771 FINE [jak.xml.bind] (executor-thread-1) Using jakarta.xml.bind-api on the class path.
Thanks a lot for helping :)
@rysurd The exception you posted indicates that the said class cannot be found on the classpath.
Please check to see if org.glassfish.hk2:osgi-resource-locator
(the maven artefact providing org.glassfish.hk2.osgiresourcelocator.ServiceLoader
) is in the project's dependencies. You can do this with something like:
mvn dependency:tree | grep osgi-resource-locator
If the dependency is present check to see if it's declared as optional, when compiling native images only compile dependencies are considered, so you might need to explicitly add the dependency as a compile dependency.
Thanks for the insights ... I'll try to check this week!
The dependency is not present. I added the dependency explicitly to my demo project. This, however, does not change the behaviour.
The (relevant) error is:
...
2023-10-31 00:34:54,666 FINE [jak.xml.bind] (executor-thread-1) Checking system property jakarta.xml.bind.JAXBContextFactory
2023-10-31 00:34:54,666 FINE [jak.xml.bind] (executor-thread-1) not found
2023-10-31 00:34:54,666 FINE [jak.xml.bind] (executor-thread-1) Trying to create the platform default provider
2023-10-31 00:34:54,666 FINE [jak.xml.bind] (executor-thread-1) Unable to find from OSGi: [jakarta.xml.bind.JAXBContextFactory]: java.lang.reflect.InvocationTargetException
at java.base@17.0.8/java.lang.reflect.Method.invoke(Method.java:568)
at jakarta.xml.bind.ServiceLoaderUtil.lookupUsingOSGiServiceLoader(ServiceLoaderUtil.java:60)
at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:373)
at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:605)
at io.quarkus.jaxb.runtime.JaxbContextProducer.createJAXBContext(JaxbContextProducer.java:80)
at io.quarkus.jaxb.runtime.JaxbContextProducer.jaxbContext(JaxbContextProducer.java:31)
at io.quarkus.jaxb.runtime.JaxbContextProducer_ProducerMethod_jaxbContext_6a6d20272304edd64c7bdfa35e3ed5d5971a3949_Bean.doCreate(Unknown Source)
at io.quarkus.jaxb.runtime.JaxbContextProducer_ProducerMethod_jaxbContext_6a6d20272304edd64c7bdfa35e3ed5d5971a3949_Bean.create(Unknown Source)
at io.quarkus.jaxb.runtime.JaxbContextProducer_ProducerMethod_jaxbContext_6a6d20272304edd64c7bdfa35e3ed5d5971a3949_Bean.create(Unknown Source)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:113)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:37)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:34)
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:34)
at io.quarkus.jaxb.runtime.JaxbContextProducer_ProducerMethod_jaxbContext_6a6d20272304edd64c7bdfa35e3ed5d5971a3949_Bean.get(Unknown Source)
at io.quarkus.jaxb.runtime.JaxbContextProducer_ProducerMethod_jaxbContext_6a6d20272304edd64c7bdfa35e3ed5d5971a3949_Bean.get(Unknown Source)
at io.quarkus.arc.impl.Instances$3.get(Instances.java:132)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.LazyInstanceHandle.instanceInternal(LazyInstanceHandle.java:32)
at io.quarkus.arc.impl.AbstractInstanceHandle.get(AbstractInstanceHandle.java:46)
at de.turing85.converter.FooConverter.getContext(FooConverter.java:61)
at de.turing85.converter.FooConverter.unmarshalFromString(FooConverter.java:42)
at de.turing85.converter.FooConverter.unmarshal(FooConverter.java:36)
at java.base@17.0.8/java.lang.reflect.Method.invoke(Method.java:568)
at org.apache.camel.support.ObjectHelper.invokeMethod(ObjectHelper.java:355)
at org.apache.camel.impl.converter.StaticMethodTypeConverter.convertTo(StaticMethodTypeConverter.java:55)
at org.apache.camel.impl.converter.CoreTypeConverterRegistry.doConvert(CoreTypeConverterRegistry.java:531)
at org.apache.camel.impl.converter.CoreTypeConverterRegistry.doConvertTo(CoreTypeConverterRegistry.java:456)
at org.apache.camel.impl.converter.CoreTypeConverterRegistry.doConvertTo(CoreTypeConverterRegistry.java:350)
at org.apache.camel.impl.converter.CoreTypeConverterRegistry.mandatoryConvertTo(CoreTypeConverterRegistry.java:276)
at org.apache.camel.support.MessageSupport.getMandatoryBody(MessageSupport.java:126)
at org.apache.camel.support.processor.ConvertBodyProcessor.process(ConvertBodyProcessor.java:118)
at org.apache.camel.support.processor.ConvertBodyProcessor.process(ConvertBodyProcessor.java:159)
at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:475)
at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.executeReactiveWork(DefaultReactiveExecutor.java:196)
at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:164)
at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:59)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:163)
at org.apache.camel.impl.engine.CamelInternalProcessor.process(CamelInternalProcessor.java:383)
at org.apache.camel.component.platform.http.vertx.VertxPlatformHttpConsumer.lambda$handleRequest$2(VertxPlatformHttpConsumer.java:198)
at io.vertx.core.impl.ContextBase.lambda$null$0(ContextBase.java:137)
at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:264)
at io.vertx.core.impl.ContextBase.lambda$executeBlocking$1(ContextBase.java:135)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
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@17.0.8/java.lang.Thread.run(Thread.java:833)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:807)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:210)
Caused by: java.lang.NullPointerException
at org.glassfish.hk2.osgiresourcelocator.ServiceLoader.lookupProviderClasses(ServiceLoader.java:132)
... 53 more
...
Shouldn't this be JaxbContextFactory
instead of JaxbContext
?
So I added
providerItem
.produce(new ServiceProviderBuildItem(JAXBContextFactory.class.getName(),
"org.glassfish.jaxb.runtime.v2.JAXBContextFactory"));
to the method above (I left the line I posted above)
Now, the application finds the JAXBContextFactory
:
...
2023-10-31 02:51:02,978 FINE [jak.xml.bind] (executor-thread-1) Checking system property jakarta.xml.bind.JAXBContextFactory
2023-10-31 02:51:02,979 FINE [jak.xml.bind] (executor-thread-1) not found
2023-10-31 02:51:02,979 FINE [jak.xml.bind] (executor-thread-1) ServiceProvider loading Facility used; returning object [org.glassfish.jaxb.runtime.v2.JAXBContextFactory]
but alas, the application still fails with a slightly different stack trace:
...
Caused by: org.glassfish.jaxb.runtime.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Property expression appears in @XmlType.propOrder, but no such property exists. Maybe you meant executorService?
this problem is related to the following location:
at org.apache.camel.model.ThrottleDefinition
at org.glassfish.jaxb.runtime.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:83)
at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:421)
at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:255)
at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1115)
at org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:144)
at org.glassfish.jaxb.runtime.v2.JAXBContextFactory.createContext(JAXBContextFactory.java:44)
at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:373)
at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:605)
at io.quarkus.jaxb.runtime.JaxbContextProducer.createJAXBContext(JaxbContextProducer.java:80)
... 49 more
...
So I dug a bit deeper and found the message template for the error message. The template is:
PROPERTY_ORDER_CONTAINS_UNUSED_ENTRY = \
Property {0} appears in @XmlType.propOrder, but no such property exists. Maybe you meant {1}?
Thus, it so not Property expression
, but Property "expression"
. Now the question is where this comes from. And where executorService
comes from. This pretty much looks like JAXB is very, very confused.
In jaxb-runtime package, class ClassInfoImpl there is this method checkUnusedProperties() that throw our error :
/**
* Report errors for unused propOrder entries.
*/
public void checkUnusedProperties() {
for( int i=0; i<used.length; i++ )
if(used[i]==null) {
String unusedName = propOrder[i];
String nearest = EditDistance.findNearest(unusedName, new AbstractList<>() {
@Override
public String get(int index) {
return properties.get(index).getName();
}
@Override
public int size() {
return properties.size();
}
});
boolean isOverriding = i <= (properties.size() - 1) && properties.get(i).hasAnnotation(OverrideAnnotationOf.class);
if (!isOverriding) {
builder.reportError(new IllegalAnnotationException(
Messages.PROPERTY_ORDER_CONTAINS_UNUSED_ENTRY.format(unusedName,nearest),ClassInfoImpl.this));
}
}
}
I don't exactly know the working of that method but it look like it's searching for unused property names, and it found property "expression".
Hi,
I am facing a similar error, also testing with Graal VM using ghcr.io/graalvm/graalvm-community:17
as base image.
I receive the error with stacktrace (XXXXXXX for privacy's reason)
Error creating bean with name 'xmlConverter': Instantiation of supplied bean failed
2023-11-18T20:30:02.100322108Z at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:317)
2023-11-18T20:30:02.100323590Z at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArguments(BeanInstanceSupplier.java:260)
2023-11-18T20:30:02.100324963Z at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:200)
2023-11-18T20:30:02.100326436Z at org.springframework.beans.factory.support.DefaultListableBeanFactory.obtainInstanceFromSupplier(DefaultListableBeanFactory.java:947)
2023-11-18T20:30:02.100329221Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1214)
2023-11-18T20:30:02.100330684Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1158)
2023-11-18T20:30:02.100332086Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560)
2023-11-18T20:30:02.100333629Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
2023-11-18T20:30:02.100335022Z at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
2023-11-18T20:30:02.100336535Z at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
2023-11-18T20:30:02.100338057Z at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
2023-11-18T20:30:02.100339580Z at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
2023-11-18T20:30:02.100342496Z at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
2023-11-18T20:30:02.100344019Z at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1417)
2023-11-18T20:30:02.100345542Z at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337)
2023-11-18T20:30:02.100347115Z at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:910)
2023-11-18T20:30:02.100348547Z at org.springframework.beans.factory.support.RegisteredBean.resolveAutowiredArgument(RegisteredBean.java:229)
2023-11-18T20:30:02.100350100Z at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:314)
2023-11-18T20:30:02.100351483Z ... 56 common frames omitted
2023-11-18T20:30:02.100353016Z Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xmlConverter': Instantiation of supplied bean failed
2023-11-18T20:30:02.100354478Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1220)
2023-11-18T20:30:02.100356602Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1158)
2023-11-18T20:30:02.100358195Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560)
2023-11-18T20:30:02.100359768Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
2023-11-18T20:30:02.100364056Z at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
2023-11-18T20:30:02.100365629Z at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
2023-11-18T20:30:02.100367072Z at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
2023-11-18T20:30:02.100368595Z at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
2023-11-18T20:30:02.100370198Z at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
2023-11-18T20:30:02.100371621Z at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1417)
2023-11-18T20:30:02.100373504Z at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337)
2023-11-18T20:30:02.100374937Z at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:910)
2023-11-18T20:30:02.100376490Z at org.springframework.beans.factory.support.RegisteredBean.resolveAutowiredArgument(RegisteredBean.java:229)
2023-11-18T20:30:02.100377902Z at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:314)
2023-11-18T20:30:02.100379435Z ... 73 common frames omitted
2023-11-18T20:30:02.100380728Z Caused by: org.glassfish.jaxb.runtime.v2.runtime.IllegalAnnotationsException: 5 counts of IllegalAnnotationExceptions
2023-11-18T20:30:02.100382220Z at org.glassfish.jaxb.runtime.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:83)
2023-11-18T20:30:02.100383703Z at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:421)
2023-11-18T20:30:02.100385056Z at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:255)
2023-11-18T20:30:02.100386659Z at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1115)
2023-11-18T20:30:02.100388081Z at org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:144)
2023-11-18T20:30:02.100389534Z at org.glassfish.jaxb.runtime.v2.JAXBContextFactory.createContext(JAXBContextFactory.java:44)
2023-11-18T20:30:02.100391007Z at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:373)
2023-11-18T20:30:02.100392339Z at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:605)
2023-11-18T20:30:02.100393712Z at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:546)
2023-11-18T20:30:02.100395225Z at XXXXXXX.XmlConverter.<init>(XmlConverter.java:32)
2023-11-18T20:30:02.100396668Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1252)
2023-11-18T20:30:02.100400084Z at org.springframework.beans.factory.support.DefaultListableBeanFactory.obtainInstanceFromSupplier(DefaultListableBeanFactory.java:949)
2023-11-18T20:30:02.100401547Z at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1214)
2023-11-18T20:30:02.100403100Z ... 86 common frames omitted
The constructor of my XmlConverter around line 32 looks like
@Component
public final class XmlConverter {
// some constants
private final JAXBContext requestContext;
private final JAXBContext responseContext;
public XmlConverter() throws JAXBException {
this.requestContext = JAXBContext.newInstance(RequestType.class); // <-- line 32
this.responseContext = JAXBContext.newInstance(ResponseType.class);
}
// other code
}
This getTypeInfoSet
method is
public RuntimeTypeInfoSet getTypeInfoSet() throws IllegalAnnotationsException {
// check cache
if(typeInfoSetCache!=null) {
RuntimeTypeInfoSet r = typeInfoSetCache.get();
if(r!=null)
return r;
}
final RuntimeModelBuilder builder = new RuntimeModelBuilder(this,annotationReader,subclassReplacements,defaultNsUri);
IllegalAnnotationsException.Builder errorHandler = new IllegalAnnotationsException.Builder();
builder.setErrorHandler(errorHandler);
for( Class c : classes ) {
if(c==CompositeStructure.class)
// CompositeStructure doesn't have TypeInfo, so skip it.
// We'll add JaxBeanInfo for this later automatically
continue;
builder.getTypeInfo(new Ref<>(c));
}
this.hasSwaRef |= builder.hasSwaRef;
RuntimeTypeInfoSet r = builder.link();
errorHandler.check(); // <-- line 421
assert r!=null : "if no error was reported, the link must be a success";
typeInfoSetCache = new WeakReference<>(r);
return r;
}
Any support is appreciated.
Thanks in advance and kind regards :)
My wild guess is that the fields in https://github.com/apache/camel/blob/main/core/camel-core-model/src/main/java/org/apache/camel/model/ExpressionNode.java#L44 are not registered for reflection.
I would try the following patch:
diff --git a/extensions/jaxb/deployment/src/main/java/io/quarkus/jaxb/deployment/JaxbProcessor.java b/extensions/jaxb/deployment/src/main/java/io/quarkus/jaxb/deployment/JaxbProcessor.java
index 17768f6d8e6..accd8006d4f 100644
--- a/extensions/jaxb/deployment/src/main/java/io/quarkus/jaxb/deployment/JaxbProcessor.java
+++ b/extensions/jaxb/deployment/src/main/java/io/quarkus/jaxb/deployment/JaxbProcessor.java
@@ -238,7 +238,7 @@ void processAnnotationsAndIndexFiles(
JAXB_ANNOTATIONS.stream()
.map(Class::getName)
.forEach(className -> {
- addReflectiveClass(reflectiveClass, true, false, className);
+ addReflectiveClass(reflectiveClass, true, true, className);
});
// Register @XmlSeeAlso
Nice findings @gsmet ... I'll try this asap and post here if this works but indeed that looks like it will ;)
Ideally we would need a fix and a test (reproducing the issue outside of Camel, issue being with https://github.com/apache/camel/blob/main/core/camel-core-model/src/main/java/org/apache/camel/model/ThrottleDefinition.java#L40 ).
I also wonder if instead of registering all the fields for reflection, we should be more fine-grained and only release the ones referenced in XmlType#propOrder
but I'm not completely sure how reflection works for hierarchy. Probably worth giving it a try.
@turing85 @rysurd if one of you is up to contribute a test and experiment with a fix, that would be awesome.
I for sure can try to make the fix, and as for the test I can also give a shot. It'd be like a unit test or something more complex? If it's just to replicate the issue of a field not being registered for reflection I guess it'd be simple ... Otherwise let's just try :D
The tests needs to be added to https://github.com/quarkusio/quarkus/tree/main/integration-tests/jaxb .
I would reproduce the fact that expression
is in a parent as it's interesting, especially if someone wants to experiment with being more fine grained for propOrder
.
I tested and it seems like it doesn't solve our issue. I still got the @XmlType.propOrder expression doesn't exist error ... Even if I changed JaxbProcessor class with the change you suggested. But I noticed that the error message suggest "executorService" as next field... which is the first to appear after "correlationExpression".
And the field we want - expression - only appear in the extended class ExpressionNode. Could it be that adding XmlType fields for reflection is not enough because the field missing is not directly declared in the same class but rather in the extended one?
Edit : the @XmlTransient annotation in parent class ExpressionNode should allow ThrottleDefinition to get that missing field, but it's like this doesn't work at all in native mode.
@gsmet I found something really interesting. I added -H:ReflectionConfigurationFiles=reflection-config.json flag to the reproducer's application.properties in order to add this config :
[
{
"name" : "org.apache.camel.model.ExpressionNode",
"allDeclaredConstructors" : true,
"allPublicConstructors" : true,
"allDeclaredMethods" : true,
"allPublicMethods" : true,
"allDeclaredFields" : true,
"allPublicFields" : true
}
]
And this time it worked. So explicitly marking ExpressionNode for reflection seems to solve our issue, meaning the problem is the fact that this class is not marked for reflection at all. Is there a way within quarkus to do this? Mark a class for reflection without the need to add a json config file?
Thanks a lot!
EDIT : Found it. I added
addReflectiveClass(reflectiveClass, true, true, "org.apache.camel.model.ExpressionNode");
At line 275 in JaxbProcessor and it worked! I'll do more tests and if good I'm adding an integration test and will open a PR. However I'm wondering if a better fix would be to go deeper and see why ExpressionNode wasn't automatically marked for reflexion ... Which is weird.
However I'm wondering if a better fix would be to go deeper and see why ExpressionNode wasn't automatically marked for reflexion ... Which is weird.
@rysurd If I am getting this right, there is currently no logic in Quarkus for registering it automatically. In https://github.com/quarkusio/quarkus/blob/4a5006e3240c65688c19e48bb22a04c65272bdfa/extensions/jaxb/deployment/src/main/java/io/quarkus/jaxb/deployment/JaxbProcessor.java#L207 Quarkus registers the annotated (with XMlType
) classes themselves for reflection, but doesn't do this reflectively for their superclasses.
I believe the right fix is to change the logic there to register the classes reflectively (using io.quarkus.deployment.builditem.nativeimage.ReflectiveHierarchyBuildItem.Builder
).
Regarding @gsmet's comment of only registering the fields mentioned in propOrder
, although it sounds the right thing to do I am afraid we currently lack the support for doing such fine grain registrations in Quarkus, so you would need to extend io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem
and io.quarkus.deployment.steps.NativeImageReflectConfigStep
as well. Probably best done in a separate PR.
Thanks @zakkak ! I'll try to do the change with ReflectiveHierarchyBuildItem then.
@rysurd I'm not sure it's worth being more fine-grained for the specific fields. Just adding the parent would work. Using ReflectiveHierarchyBuildItem
at the line @zakkak pointed out should be enough to fix the issue.
I would really appreciate if we could add a test to the -deployment
module in passing so that it doesn't get broken again later.
@gsmet so adding a test in the deployment module as well as adding an integration test for jaxb ?
@gsmet @zakkak Hello ! I have made the changes using ReflectiveHierarchyBuildItem but I got an error stating that I needed to add all the Jaxb annotations into a Jandex index. I searched and added this into the jaxb deployment pom.xml :
<plugin>
<groupId>io.smallrye</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<executions>
<execution>
<id>make-index</id>
<goals>
<goal>jandex</goal>
</goals>
</execution>
</executions>
</plugin>
In the build logs I now see this :
[INFO] --- jandex:3.1.5:jandex (make-index) @ quarkus-jaxb-deployment ---
[INFO] Saving Jandex index: C:\quarkus\extensions\jaxb\deployment\target\classes\META-INF\jandex.idx
But at the end of the build I still got this issue :
Unable to properly register the hierarchy of the following classes for reflection as they are not in the Jandex index
But I noticed that the build is still successful and the reproducer still is successful too with native compilation. Am I doing something wrong there ? :( I followed these instructions : https://quarkus.io/guides/cdi-reference#how-to-generate-a-jandex-index
@gsmet could you please help with that? I have no experience with Jandex indexing.
No idea for this jandex issue @gsmet ? I am currently finishing writing an integration test for jaxb replicating the issue, I think I might open a PR after that but ideally I should know if the jandex messages are a showstopper or not 😄
Hello @rysurd, @ppalaga, @gsmet!
I can verify that the fix works for quarkus version 3.6.6
. However, if I use a quarkus version > 3.6.6
, the test starts failing again, with the same error message. I tested with versions 3.6.7
, 3.6.9
and 3.7.1
. So it seems that we have a regression. I have updated the reproducer to use quarkus 3.6.9
.
Can we re-open the issue?
Hello @turing85 ! The fix has unfortunately been reverted here https://github.com/quarkusio/quarkus/pull/38224 since 3.6.7, until further notice.
Can we re-open the issue then? Or is there another issue to track the status?
@turing85 Hi Turing, have u fixed this error with jaxb integrated with graalvm native? I am using jaxb2-maven-plugin@3.1.0 to generate Java classes from XML Schema, then constructing Java objects, and generating files through Marshaller. I encountered an issue where the program runs fine in a normal project, but when I use Spring Native to package and generate an exe, it encounters problems. It gives errors related to the generated Java objects, preventing further execution. The error is as follows:
Property expression appears in @XmlType.propOrder, but no such property exists. Maybe you meant null?
this problem is related to the following location:
at FmiModelDescription
is there any way to fix this or walkaround?
This has been fixed in #38217 which is part of 3.9.
@Terrency the problem is probably due to your classes/fields/methods not being marked for reflection. That is important for GraalVM to notice them and make sure they are not removed from the native executable.
That's one of the reason why we have Quarkus extensions.
Describe the bug
When a class annotated with JAXB annotations is unmarshalled, the unmarshalling fails with
Expected behavior
The object gets unmarshalled
Actual behavior
The above exception is thrown.
How to Reproduce?
Reproducer:
Output of
uname -a
orver
Linux ecco 5.15.0-52-generic #58-Ubuntu SMP Thu Oct 13 08:03:55 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Output of
java -version
openjdk version "17.0.8" 2023-07-18 OpenJDK Runtime Environment Temurin-17.0.8+7 (build 17.0.8+7) OpenJDK 64-Bit Server VM Temurin-17.0.8+7 (build 17.0.8+7, mixed mode, sharing)
GraalVM version (if different from Java)
mandrel-23.0.1.2-java17
Quarkus version or git rev
3.2.6.Final
Build tool (ie. output of
mvnw --version
orgradlew --version
)Apache Maven 3.9.3 (21122926829f1ead511c958d89bd2f672198ae9f) Maven home: /home/marco/.m2/wrapper/dists/apache-maven-3.9.3-bin/326f10f4/apache-maven-3.9.3 Java version: 17.0.8, vendor: Eclipse Adoptium, runtime: /opt/java/mandrel/23.0.1.2-java17 Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "5.15.0-52-generic", arch: "amd64", family: "unix"
Additional information
Foo.java
norBar.java
definepropOrder
. Defining them does not change the behaviour.Foo
andBar
for reflectoin and serialization does not change the behaviour.