-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JAXB unmarshalling fails in native mode #36479
Comments
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 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 :
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
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:
|
quarkus/extensions/jaxb/deployment/src/main/java/io/quarkus/jaxb/deployment/JaxbProcessor.java Line 296 in 3149ece
Shouldn't this be |
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 ...
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:
Thus, it so not |
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 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 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 @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 |
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. |
@rysurd If I am getting this right, there is currently no logic in Quarkus for registering it automatically. In quarkus/extensions/jaxb/deployment/src/main/java/io/quarkus/jaxb/deployment/JaxbProcessor.java Line 207 in 4a5006e
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 Regarding @gsmet's comment of only registering the fields mentioned in |
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 I would really appreciate if we could add a test to the |
@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 :
But at the end of the build I still got this issue :
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! Can we re-open the issue? |
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?
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:
git clone https://github.com/turing85/quarkus-camel-jaxb.git cd quarkus-camel-jaxb
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.The text was updated successfully, but these errors were encountered: