How to use JAXB in native image without using agent

61 Views Asked by At

Marshalling or demarshalling from XML results in the following exception in native mode:

  JUnit Jupiter:MainTest:testToXml()
    MethodSource [className = 'org.acme.MainTest', methodName = 'testToXml', methodParameterTypes = '']
    => org.graalvm.nativeimage.MissingReflectionRegistrationError: The program tried to reflectively invoke method public org.glassfish.jaxb.runtime.v2.runtime.property.SingleElementNodeProperty(org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl,org.glassfish.jaxb.runtime.v2.model.runtime.RuntimeElementPropertyInfo) without it being registered for runtime reflection. Add public org.glassfish.jaxb.runtime.v2.runtime.property.SingleElementNodeProperty(org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl,org.glassfish.jaxb.runtime.v2.model.runtime.RuntimeElementPropertyInfo) to the reflection metadata to solve this problem. See https://www.graalvm.org/latest/reference-manual/native-image/metadata/#reflection for help.
       org.graalvm.nativeimage.builder/com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils.forQueriedOnlyExecutable(MissingReflectionRegistrationUtils.java:72)
       [email protected]/java.lang.reflect.Constructor.acquireConstructorAccessor(Constructor.java:74)
       [email protected]/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
       [email protected]/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
       org.glassfish.jaxb.runtime.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:94)
       org.glassfish.jaxb.runtime.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:148)
       org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:464)
       org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:283)
       org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1115)
       org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:144)
       [...]

Example code:

    public static String toXml(MyAnnotatedClass instance) {
        StringWriter out = new StringWriter();
        JAXB.marshal(instance, out);
        return out.toString();
    }

and META-INF/native-image/org.acme/issue-reproducer/reflect-config.json:

[
  {
    "name":"org.acme.MyAnnotatedClass",
    "allDeclaredFields":true,
    "queryAllDeclaredMethods":true,
    "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"getType","parameterTypes":[] }]
  }
]

Maven build configuration:

      <build>
        <plugins>
          <plugin>
            <groupId>org.graalvm.buildtools</groupId>
            <artifactId>native-maven-plugin</artifactId>
            <version>0.10.0</version>
            <extensions>true</extensions>
            <executions>
              <execution>
                <id>build-native</id>
                <goals>
                  <goal>compile-no-fork</goal>
                </goals>
                <phase>package</phase>
              </execution>
              <execution>
                <id>test-native</id>
                <goals>
                  <goal>test</goal>
                </goals>
                <phase>test</phase>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>

GraalVM version: 21.0.2 CE

Am I correct in thinking the above is all that should be needed to use JAX-B in native image without using the agent, since the reachability metadata repository is enabled by default when using 0.9.12 or above of the native-maven-plugin? Moreover,the reachability metadata is used according to the logs:

[INFO] [graalvm reachability metadata repository for org.glassfish.jaxb:jaxb-runtime:4.0.4]: Configuration directory not found. Trying latest version.
[INFO] [graalvm reachability metadata repository for org.glassfish.jaxb:jaxb-runtime:4.0.4]: Configuration directory is org.glassfish.jaxb/jaxb-runtime/3.0.2

Example project: https://github.com/Christopher-Chianelli/issue-reproducer/tree/graalvm-xml-native/project

Adding the class to the reflect-config.json fixes the issue, but not preferable:

[
  {
    "name":"org.acme.MyAnnotatedClass",
    "allDeclaredFields":true,
    "queryAllDeclaredMethods":true,
    "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"getType","parameterTypes":[] }]
  },
  {
    "name":"org.glassfish.jaxb.runtime.v2.runtime.property.SingleElementNodeProperty",
    "queryAllPublicConstructors":true,
    "methods":[{"name":"<init>","parameterTypes":["org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl","org.glassfish.jaxb.runtime.v2.model.runtime.RuntimeElementPropertyInfo"] }]
  }
]
0

There are 0 best solutions below