Quarkus兼容spring-boot-starter-web构建报索引缺失问题咨询
Quarkus JVM模式迁移Spring Boot应用构建报错排查
背景
- 正在推进高复杂度Spring Boot应用向Quarkus迁移,第一阶段目标为最小化代码改动,先让应用在Quarkus JVM模式(非原生编译)下正常运行
- 已完成Quarkus Spring扩展未覆盖的
spring-orm、spring-jdbc、spring-web(客户端部分)依赖适配,后续遇到构建失败问题
报错信息
[ERROR] Failed to execute goal io.quarkus:quarkus-maven-plugin:2.2.1.Final:build (default) on project rules-engine-core: Failed to build quarkus application: io.quarkus.builder.BuildException: Build failure: Build failed due to errors [ERROR] [error]: Build step io.quarkus.arc.deployment.ArcProcessor#registerBeans threw an exception: java.lang.IllegalArgumentException: Producer method return type not found in index: org.springframework.boot.web.servlet.ServletRegistrationBean
关联代码
import javax.ws.rs.core.Application; import org.apache.cxf.transport.servlet.CXFServlet; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.apache.catalina.valves.StuckThreadDetectionValve; import org.springframework.beans.factory.annotation.Autowired; @Configuration @SpringBootApplication( exclude = TransactionAutoConfiguration.class ) public class WebApplicationConfiguration extends SpringBootServletInitializer { @Autowired private [ApplicationName]ExecutorSemaphoreValve semaphoreValve; // Replaces the need for web.xml @Bean public ServletRegistrationBean servletRegistrationBean( ApplicationContext context ) { return new ServletRegistrationBean( new CXFServlet(), "/*" ); } // Configure the embedded tomcat to use same settings as default standalone // tomcat deploy @Bean public AbstractServletWebServerFactory embeddedServletContainerFactory() { // Made to match the context path when deploying to standalone tomcat- // can easily be kept in sync w/ properties TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory( CorePropertyUtils.engineContext(), CorePropertyUtils.enginePort() ); StuckThreadDetectionValve stuckThreadValve = new StuckThreadDetectionValve(); semaphoreValve.setBlock( false ); semaphoreValve.setFairness( false ); factory.addContextValves( stuckThreadValve, semaphoreValve ); return factory; } // Used when deploying to a standalone servlet container, i.e. tomcat @Override protected SpringApplicationBuilder configure( SpringApplicationBuilder application ) { return application.sources( Application.class ); } }
已排查结论
- 同类报错常见根因为未引入对应Quarkus Spring扩展,已确认当前场景不属于该情况
问题解答
1. 该报错是否仅仅是jandex索引配置问题导致的?
不是。
这个报错的核心原因是ServletRegistrationBean属于Spring Boot嵌入式Tomcat启动链路专属组件,Quarkus的Spring兼容层本身不提供这部分类的运行时支撑。即使手动把Spring Boot相关包加入Jandex索引,Arc容器扫描到对应@Bean生产者方法时,依然会因为缺少配套的启动逻辑、容器适配逻辑无法完成Bean注册,单纯补索引解决不了问题。
2. 在迁移第一阶段,我是否必须修改使用spring-boot-web依赖的相关代码?
不需要全量修改普通业务代码,但必须移除/替换嵌入式容器启动相关的配置逻辑,也就是你贴的WebApplicationConfiguration里和Spring Boot内嵌Tomcat强绑定的部分:
- 移除
SpringBootServletInitializer继承逻辑,Quarkus不走Spring Boot的Servlet容器初始化流程 - 删除
ServletRegistrationBean的Bean定义:CXF在Quarkus下有官方扩展可以直接集成,不需要手动注册CXFServlet;如果需要注册其他Servlet,直接用Quarkus自带的@RegisterServlet注解或对应配置即可 - 删除
TomcatServletWebServerFactory相关Bean定义:Quarkus默认使用Undertow/Vert.x作为Web运行时,不会启动Spring Boot管理的嵌入式Tomcat,你之前配置的Tomcat Valve(StuckThreadDetectionValve、自定义的ExecutorSemaphoreValve)需要替换为Quarkus支持的Servlet Filter或Vert.x Handler实现
其余普通Spring Web相关代码(比如@RestController、@RequestMapping、参数绑定注解等)只要引入quarkus-spring-web扩展就可以直接兼容,不需要改动。
额外提示:你当前使用的2.2.1.Final版本Quarkus过老,Spring兼容层覆盖度远低于后续LTS版本,第一阶段追求最小改动的话建议先升级到2.16.x或3.x LTS版本,能减少很多无意义的兼容工作量。注意不要把Spring Boot内嵌Tomcat的依赖带进Quarkus应用,会和Quarkus自带的Web运行时产生类冲突。
内容的提问来源于stack exchange,提问作者msfbrasil
相关产品推荐
相关产品推荐

