Summary

  • SpringBoot: 3.0.3
  • Kotlin: 1.7.22
  • Java: 17.0.5 Temurin (on Ubuntu 64 Bit)
  • simple SpringBoot Web project, see: https://github.com/steinsag/spring-native-xml
  • Spring OXM is used to marshal some simple XML structure to a string
  • JVM execution works as expected
  • AOT also successful
  • BUT: native execution fails with:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloXmlService': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'createJaxbMarshaller': Proxy class defined by interfaces [interface jakarta.xml.bind.annotation.XmlAccessorType, interface org.glassfish.jaxb.core.v2.model.annotation.Locatable] not found. Generating proxy classes at runtime is not supported. Proxy classes need to be defined at image build time by specifying the list of interfaces that they implement. To define proxy classes use -H:DynamicProxyConfigurationFiles= and -H:DynamicProxyConfigurationResources= options.

expected behavior: All XML runtime classes automatically discovered during AOT as official Spring OXM approach is used.

How to reproduce

sample project: https://github.com/steinsag/spring-native-xml

git clone git@github.com:steinsag/spring-native-xml.git spring-native-xml
cd spring-native-xml
./mvnw spring-boot:build-image -Pnative
docker run --rm -p 8080:8080 spring-native-xml:0.0.1-SNAPSHOT

Full stacktrace

$ docker run --rm -p 8080:8080 spring-native-xml:0.0.1-SNAPSHOT

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.3)

2023-02-23T20:22:00.351Z  INFO 1 --- [           main] s.p.s.SpringNativeXmlApplicationKt       : Starting AOT-processed SpringNativeXmlApplicationKt using Java 17.0.6 with PID 1 (/workspace/services.progressit.springnativexml.SpringNativeXmlApplicationKt started by cnb in /workspace)
2023-02-23T20:22:00.351Z  INFO 1 --- [           main] s.p.s.SpringNativeXmlApplicationKt       : No active profile set, falling back to 1 default profile: "default"
2023-02-23T20:22:00.374Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2023-02-23T20:22:00.375Z  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-02-23T20:22:00.375Z  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.5]
2023-02-23T20:22:00.382Z  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-02-23T20:22:00.382Z  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 31 ms
2023-02-23T20:22:00.402Z  WARN 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloXmlService': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'createJaxbMarshaller': Proxy class defined by interfaces [interface jakarta.xml.bind.annotation.XmlAccessorType, interface org.glassfish.jaxb.core.v2.model.annotation.Locatable] not found. Generating proxy classes at runtime is not supported. Proxy classes need to be defined at image build time by specifying the list of interfaces that they implement. To define proxy classes use -H:DynamicProxyConfigurationFiles=<comma-separated-config-files> and -H:DynamicProxyConfigurationResources=<comma-separated-config-resources> options.
2023-02-23T20:22:00.403Z  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2023-02-23T20:22:00.404Z ERROR 1 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloXmlService': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'createJaxbMarshaller': Proxy class defined by interfaces [interface jakarta.xml.bind.annotation.XmlAccessorType, interface org.glassfish.jaxb.core.v2.model.annotation.Locatable] not found. Generating proxy classes at runtime is not supported. Proxy classes need to be defined at image build time by specifying the list of interfaces that they implement. To define proxy classes use -H:DynamicProxyConfigurationFiles=<comma-separated-config-files> and -H:DynamicProxyConfigurationResources=<comma-separated-config-resources> options.
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:351) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArguments(BeanInstanceSupplier.java:271) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:206) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1226) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1211) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1158) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:961) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:917) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:3.0.3]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:3.0.3]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:3.0.3]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:3.0.3]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1304) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:3.0.3]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1293) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:3.0.3]
        at services.progressit.springnativexml.SpringNativeXmlApplicationKt.main(SpringNativeXmlApplication.kt:13) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'createJaxbMarshaller': Proxy class defined by interfaces [interface jakarta.xml.bind.annotation.XmlAccessorType, interface org.glassfish.jaxb.core.v2.model.annotation.Locatable] not found. Generating proxy classes at runtime is not supported. Proxy classes need to be defined at image build time by specifying the list of interfaces that they implement. To define proxy classes use -H:DynamicProxyConfigurationFiles=<comma-separated-config-files> and -H:DynamicProxyConfigurationResources=<comma-separated-config-resources> options.
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1752) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1405) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:334) ~[na:na]
        ... 21 common frames omitted
Caused by: com.oracle.svm.core.jdk.UnsupportedFeatureError: Proxy class defined by interfaces [interface jakarta.xml.bind.annotation.XmlAccessorType, interface org.glassfish.jaxb.core.v2.model.annotation.Locatable] not found. Generating proxy classes at runtime is not supported. Proxy classes need to be defined at image build time by specifying the list of interfaces that they implement. To define proxy classes use -H:DynamicProxyConfigurationFiles=<comma-separated-config-files> and -H:DynamicProxyConfigurationResources=<comma-separated-config-resources> options.
        at com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89) ~[na:na]
        at com.oracle.svm.core.reflect.proxy.DynamicProxySupport.getProxyClass(DynamicProxySupport.java:171) ~[na:na]
        at java.base@17.0.6/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:47) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:na]
        at java.base@17.0.6/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1037) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:na]
        at org.glassfish.jaxb.runtime.v2.model.annotation.LocatableAnnotation.create(LocatableAnnotation.java:53) ~[na:na]
        at org.glassfish.jaxb.runtime.v2.model.annotation.RuntimeInlineAnnotationReader.getClassAnnotation(RuntimeInlineAnnotationReader.java:92) ~[na:na]
        at org.glassfish.jaxb.runtime.v2.model.annotation.RuntimeInlineAnnotationReader.getClassAnnotation(RuntimeInlineAnnotationReader.java:29) ~[na:na]
        at org.glassfish.jaxb.runtime.v2.model.impl.ClassInfoImpl.getClassOrPackageAnnotation(ClassInfoImpl.java:434) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.2 - d104f19]
        at org.glassfish.jaxb.runtime.v2.model.impl.ClassInfoImpl.getAccessType(ClassInfoImpl.java:446) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.2 - d104f19]
        at org.glassfish.jaxb.runtime.v2.model.impl.ClassInfoImpl.getProperties(ClassInfoImpl.java:293) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.2 - d104f19]
        at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeClassInfoImpl.getProperties(RuntimeClassInfoImpl.java:159) ~[na:na]
        at org.glassfish.jaxb.runtime.v2.model.impl.ModelBuilder.getClassInfo(ModelBuilder.java:219) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.2 - d104f19]
        at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeModelBuilder.getClassInfo(RuntimeModelBuilder.java:72) ~[na:na]
        at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeModelBuilder.getClassInfo(RuntimeModelBuilder.java:52) ~[na:na]
        at org.glassfish.jaxb.runtime.v2.model.impl.ModelBuilder.getClassInfo(ModelBuilder.java:185) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.2 - d104f19]
        at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeModelBuilder.getClassInfo(RuntimeModelBuilder.java:67) ~[na:na]
        at org.glassfish.jaxb.runtime.v2.model.impl.RuntimeModelBuilder.getClassInfo(RuntimeModelBuilder.java:52) ~[na:na]
        at org.glassfish.jaxb.runtime.v2.model.impl.ModelBuilder.getTypeInfo(ModelBuilder.java:332) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.2 - d104f19]
        at org.glassfish.jaxb.runtime.v2.model.impl.ModelBuilder.getTypeInfo(ModelBuilder.java:347) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.2 - d104f19]
        at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:415) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.2 - d104f19]
        at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:255) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.2 - d104f19]
        at org.glassfish.jaxb.runtime.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1115) ~[na:na]
        at org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:144) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.2 - d104f19]
        at org.glassfish.jaxb.runtime.v2.JAXBContextFactory.createContext(JAXBContextFactory.java:44) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.2 - d104f19]
        at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:368) ~[na:na]
        at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:605) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.0]
        at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:546) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:4.0.0]
        at org.springframework.oxm.jaxb.Jaxb2Marshaller.createJaxbContextFromClasses(Jaxb2Marshaller.java:559) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.oxm.jaxb.Jaxb2Marshaller.getJaxbContext(Jaxb2Marshaller.java:508) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.oxm.jaxb.Jaxb2Marshaller.afterPropertiesSet(Jaxb2Marshaller.java:485) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1798) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1748) ~[services.progressit.springnativexml.SpringNativeXmlApplicationKt:6.0.5]
        ... 31 common frames omitted

Comment From: sdeleuze

After a deeper look to the sample, I tend to think this issue is not Spring specific and should be raised with a non Spring repro on https://github.com/oracle/graalvm-reachability-metadata side. The proxy interfaces seems not dependent of user classes.

When you provide them with for example @ImportRuntimeHints(Hints::class) and:

class Hints : RuntimeHintsRegistrar {
    override fun registerHints(hints: RuntimeHints, classLoader: ClassLoader?) {
        hints.proxies().registerJdkProxy(XmlAccessorType::class.java, Locatable::class.java)
    }
}

An org.glassfish.jaxb.runtime.v2.runtime.IllegalAnnotationsException is thrown but I guess it will be fixable on reachability metadata side as well.

As a consequence I close this issue on Spring side, if you can, please add a comment with the reachability metadata issue.

Comment From: steinsag

It seems there is a relevant feature request on GraalVM reachability metadata issue: https://github.com/oracle/graalvm-reachability-metadata/issues/137