Bug description

Here is a class extends OncePerRequestFilter implements Order, add @Value to set Order, just like

public class AFilter extends OncePerRequestFilter implements Order {
    @Value("${filterOrder:0}")
    protected Integer filterOrder;

    @Override
    public int getOrder() {
        return filterOrder;
    }

    ......
}

then

@Bean
public AFilter aFilter() {
    return new AFilter()
}

Those can be compile with GraalVM Native Image, but run it failed

Expected behavior

It can run successfully with JVM mode, so that is also fine in Native mode

Actual behavior

Refer to exception:

2022-12-27 12:17:18.464 ERROR 20996 --- [           main]     o.s.boot.SpringApplication               : Application run failed
org.springframework.context.ApplicationContextException: Unable to start web server
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:164)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:578)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
        at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:150)
        at com.nepxion.discovery.guide.service.DiscoveryGuideServiceA1.main(DiscoveryGuideServiceA1.java:31)
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
        at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:142)
        at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104)
        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:486)
        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:210)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:183)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:161)
        ... 7 common frames omitted
Caused by: java.lang.NullPointerException: null
        at com.nepxion.discovery.plugin.strategy.service.filter.AbstractServiceStrategyRouteFilter.getOrder(AbstractServiceStrategyRouteFilter.java:61)
        at org.springframework.core.OrderComparator.findOrder(OrderComparator.java:145)
        at org.springframework.core.annotation.AnnotationAwareOrderComparator.findOrder(AnnotationAwareOrderComparator.java:64)
        at org.springframework.core.OrderComparator.getOrder(OrderComparator.java:128)
        at org.springframework.core.OrderComparator.getOrder(OrderComparator.java:116)
        at org.springframework.core.OrderComparator.doCompare(OrderComparator.java:86)
        at org.springframework.core.OrderComparator.compare(OrderComparator.java:73)
        at org.springframework.boot.web.servlet.ServletContextInitializerBeans.lambda$getOrderedBeansOfType$1(ServletContextInitializerBeans.java:215)
        at java.base@17.0.5/java.util.TimSort.countRunAndMakeAscending(TimSort.java:356)
        at java.base@17.0.5/java.util.TimSort.sort(TimSort.java:220)
        at java.base@17.0.5/java.util.Arrays.sort(Arrays.java:1307)
        at java.base@17.0.5/java.util.ArrayList.sort(ArrayList.java:1721)
        at org.springframework.boot.web.servlet.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:215)
        at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:171)
        at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:166)
        at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAdaptableBeans(ServletContextInitializerBeans.java:151)
        at org.springframework.boot.web.servlet.ServletContextInitializerBeans.<init>(ServletContextInitializerBeans.java:86)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getServletContextInitializerBeans(ServletWebServerApplicationContext.java:261)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.selfInitialize(ServletWebServerApplicationContext.java:235)
        at org.springframework.boot.web.embedded.tomcat.TomcatStarter.onStartup(TomcatStarter.java:52)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5144)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383)
        at java.base@17.0.5/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at java.base@17.0.5/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:886)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1383)
        at java.base@17.0.5/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at java.base@17.0.5/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916)
        at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:252)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardService.startInternal(StandardService.java:430)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:926)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.startup.Tomcat.start(Tomcat.java:485)
        at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:123)
        ... 12 common frames omitted

Is it a bug? Or what mistake I have made?

I guess it is related with this line (lambda?)

org.springframework.boot.web.servlet.ServletContextInitializerBeans.lambda$getOrderedBeansOfType$1(ServletContextInitializerBeans.java:215)

org.springframework.boot.web.servlet.ServletContextInitializerBeans.java

    private <T> List<Entry<String, T>> getOrderedBeansOfType(ListableBeanFactory beanFactory, Class<T> type,
            Set<?> excludes) {
        String[] names = beanFactory.getBeanNamesForType(type, true, false);
        Map<String, T> map = new LinkedHashMap<>();
        for (String name : names) {
            if (!excludes.contains(name) && !ScopedProxyUtils.isScopedTarget(name)) {
                T bean = beanFactory.getBean(name, type);
                if (!excludes.contains(bean)) {
                    map.put(name, bean);
                }
            }
        }
        List<Entry<String, T>> beans = new ArrayList<>(map.entrySet());
                // this line will be failed in GraalVM Native Image?
        beans.sort((o1, o2) -> AnnotationAwareOrderComparator.INSTANCE.compare(o1.getValue(), o2.getValue()));
        return beans;
    }

I use

  • GraalVM version: 22.3.0
  • JDK major version: Java17
  • OS: Windows 10
  • Architecture: AMD64
  • Spring Boot: 3.0.1
  • Spring Cloud: 2022.0.0

Comment From: wilkinsona

Thanks for the report. This looks like a Spring Framework issue to me as it would appear that @Value on AFilter's filterOrder field has not be honoured. We'll transfer the issue so that the Framework team can take a look.

Comment From: sdeleuze

@HaojunRen I tried to replicate the issue, but was not able to reproduce, so please provide a reproducer to allow me to have a deeper look.

Comment From: spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: spring-projects-issues

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.