tl;博士
您使用的swagger 版本不支持jakarta 命名空间。您必须升级到2.1.7 或更高版本,并将相关的-jakarta 后缀添加到工件描述符中。此外,您使用的是不受支持的 jackson,它也不支持 jakarta。你必须切换到jackson-jakarta-rs-providers(详见下文)。
详细解释
为了重现部署过程,我快速将以下插件配置添加到您的 pom.xml 中,以便通过 tomee:run 在 Maven 中运行 TomEE
<plugin>
<groupId>org.apache.tomee.maven</groupId>
<artifactId>tomee-maven-plugin</artifactId>
<version>8.0.7</version>
<configuration>
<tomeeVersion>9.0.0-M7</tomeeVersion>
<tomeeClassifier>plume</tomeeClassifier>
<debug>true</debug>
<tomeeHttpPort>8282</tomeeHttpPort>
<debugPort>5005</debugPort>
<args>-Dfoo=bar</args>
<config>${project.basedir}/src/test/tomee/conf</config>
<skipCurrentProject>true</skipCurrentProject>
<webapps>
<webapp>
fr.pause-piano:pause-piano-backend:1.0-SNAPSHOT?name=ROOT
</webapp>
</webapps>
</configuration>
</plugin>
然后它会尝试部署您的 webapp,它会在控制台输出中打印一些 ClassNotFoundExceptions,表明 javax 和 jakarta 命名空间之间存在一些麻烦。
您使用的swagger 版本不支持jakarta 命名空间。 official repository on GitHub 声明:
注意:自 2.1.7 版以来,Swagger Core 还支持 Jakarta
命名空间,带有一组带有 -jakarta 后缀的并行工件,
提供与“标准”javax 命名空间相同的功能
那些。详情请查看维基
这意味着,您必须将代码中的相关工件和后缀升级为:
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2-jakarta</artifactId>
<version>2.1.10</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2-servlet-initializer-v2-jakarta</artifactId>
<version>2.1.10</version>
</dependency>
但是,这还不够,因为 web 应用程序仍在使用不受支持的 jackson 版本,它不支持 jakarta 命名空间(请参阅 GitHub):
(*) 注意! JAX-RS 是 javax.ws.rs 下定义的“旧”API; 2019年
左右,甲骨文决定将其分叉成“雅加达”
jakarta.ws.ws 下的变体。截至 2021 年,大多数框架仍使用
旧 API,但如果您确实需要/想要使用较新的 API,请查看 Jakarta-RS
jackson-jakarta-rs-providers 的供应商回购
你必须切换到jackson-jakarta-rs-providers,将项目中的jackson依赖替换为
<dependency>
<groupId>com.fasterxml.jackson.jakarta.rs</groupId>
<artifactId>jackson-jakarta-rs-json-provider</artifactId>
<version>2.13.0-rc2</version>
</dependency>
应用这些更改后,webapp 仍会抛出另一个ClassNotFoundException。使用mvn dependency:tree,我们可以看到,更新后的swagger-jaxrs2-jakarta 引入了jackson-jaxrs-provider 依赖项。奇怪,不是吗?所以我们需要排除它:
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2-jakarta</artifactId>
<version>2.1.10</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
</exclusion>
</exclusions>
</dependency>
更改后,我们可以通过运行mvn clean install 和mvn tomee:run 再试一次。日志输出记录良好并显示已部署的端点:
31-Aug-2021 14:46:20.894 INFORMATION [main] org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints REST Application: http://localhost:8282/sample -> fr.theogiraudet.swagger.Swagger@f25176a
31-Aug-2021 14:46:20.903 INFORMATION [main] org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints Service URI: http://localhost:8282/sample/openapi -> Pojo io.swagger.v3.jaxrs2.integration.resources.AcceptHeaderOpenApiResource
31-Aug-2021 14:46:20.903 INFORMATION [main] org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints GET http://localhost:8282/sample/openapi -> Response getOpenApiJson(HttpHeaders, UriInfo) throws Exception
31-Aug-2021 14:46:20.903 INFORMATION [main] org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints GET http://localhost:8282/sample/openapi -> Response getOpenApiYaml(HttpHeaders, UriInfo) throws Exception
31-Aug-2021 14:46:20.905 INFORMATION [main] org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints Service URI: http://localhost:8282/sample/openapi.{type:json|yaml} -> Pojo io.swagger.v3.jaxrs2.integration.resources.OpenApiResource
31-Aug-2021 14:46:20.905 INFORMATION [main] org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints GET http://localhost:8282/sample/openapi.{type:json|yaml} -> Response getOpenApi(HttpHeaders, UriInfo, String) throws Exception
31-Aug-2021 14:46:20.905 INFORMATION [main] org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints Service URI: http://localhost:8282/sample/pianos -> Pojo fr.theogiraudet.rest.PianoResource
31-Aug-2021 14:46:20.905 INFORMATION [main] org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints DELETE http://localhost:8282/sample/pianos -> Response deleteAllPianos()
31-Aug-2021 14:46:20.906 INFORMATION [main] org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints GET http://localhost:8282/sample/pianos -> Response getAllPianos(UriInfo)
31-Aug-2021 14:46:20.906 INFORMATION [main] org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints GET http://localhost:8282/sample/pianos/{id} -> Response getPiano(int)
31-Aug-2021 14:46:20.906 INFORMATION [main] org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints POST http://localhost:8282/sample/pianos -> Response postPiano(PianoData)
31-Aug-2021 14:46:20.956 INFORMATION [main] jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke Deployment of web application archive [/home/zowallar/IdeaProjects/PausePiano-Backend/target/apache-tomee/webapps/ROOT.war] has finished in [4.433] ms
31-Aug-2021 14:46:20.968 INFORMATION [main] org.apache.catalina.core.StandardContext.setClassLoaderProperty Unable to set the web application class loader property [clearReferencesRmiTargets] to [true] as the property does not exist.
31-Aug-2021 14:46:20.969 INFORMATION [main] org.apache.catalina.core.StandardContext.setClassLoaderProperty Unable to set the web application class loader property [clearReferencesObjectStreamClassCaches] to [true] as the property does not exist.
31-Aug-2021 14:46:20.969 INFORMATION [main] org.apache.catalina.core.StandardContext.setClassLoaderProperty Unable to set the web application class loader property [clearReferencesObjectStreamClassCaches] to [true] as the property does not exist.
31-Aug-2021 14:46:20.969 INFORMATION [main] org.apache.catalina.core.StandardContext.setClassLoaderProperty Unable to set the web application class loader property [clearReferencesThreadLocals] to [true] as the property does not exist.
31-Aug-2021 14:46:20.989 INFORMATION [main] jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke Starting ProtocolHandler ["http-nio-8282"]
31-Aug-2021 14:46:21.003 INFORMATION [main] jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke Server startup in [4564] milliseconds
但是,调用相关端点会导致另一个异常:
jakarta.servlet.ServletException: Servlet.init() for servlet [fr.theogiraudet.swagger.Swagger] threw exception
org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:45)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:543)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.tomee.catalina.OpenEJBSecurityListener$RequestCapturer.invoke(OpenEJBSecurityListener.java:97)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:353)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:870)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1696)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:829)
引起
java.lang.IllegalStateException: The resource configuration is not modifiable in this context.
org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:248)
org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:195)
org.glassfish.jersey.server.ResourceConfig.register(ResourceConfig.java:428)
org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:306)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:347)
jakarta.servlet.GenericServlet.init(GenericServlet.java:158)
org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:45)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:543)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.tomee.catalina.OpenEJBSecurityListener$RequestCapturer.invoke(OpenEJBSecurityListener.java:97)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:353)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:870)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1696)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:829)
查看日志会发现jackson 存在一些问题:
java.lang.NoClassDefFoundError: com/fasterxml/jackson/module/jaxb/JaxbAnnotationIntrospector
总结
看起来,与 jackson 结合使用的相关工具 (swagger) 尚未准备好完全使用 jakarta 命名空间。如果您不习惯使用 9,您可以使用工作工具简单地切换到 8(因为 9 仅包含命名空间更改)。