无法使用 Javal 11、Jetty 和 Jersey 将 HttpServletRequest 注入 ContainerRequestFilter

Can't inject HttpServletRequest into ContainerRequestFilter with Javal 11, Jetty and Jersey

我正在 Java 11 上将 Java 8 网络服务更新到 运行。我不熟悉 Java,我更熟悉 C# dotnet环境。我已经阅读了数十篇与此问题相关的文章和问题,我非常确信我的代码应该可以工作,但我的项目设置是错误的。

我的原始项目只有一个 Eclipse 项目文件,我添加了 Maven,并重新组织了我的项目,以便我可以构建一个展开的 WAR 并从那里进行调试。目前,违规代码如下所示:

@Provider
@Priority(Priorities.AUTHENTICATION)
public class SecurityFilter implements ContainerRequestFilter {
    @Inject
    private jakarta.inject.Provider<HttpServletRequest> requestProvider;
    
    @Override
    public void filter(ContainerRequestContext filterContext) throws IOException {
        var servletRequest = requestProvider.get();
    }
}

这给我一个错误,例如:

jakarta.servlet.ServletException: jakarta.servlet.ServletException: A MultiException has 2 exceptions.  They are:
1. java.lang.IllegalArgumentException: org.glassfish.hk2.api.ProxyCtl referenced from a method is not visible from class loader
2. java.lang.IllegalArgumentException: While attempting to create a Proxy for jakarta.servlet.http.HttpServletRequest in scope org.glassfish.jersey.process.internal.RequestScoped an error occured while creating the proxy
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:157)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
    at org.eclipse.jetty.server.Server.handle(Server.java:562)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle[=11=](HttpChannel.java:406)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:663)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:398)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:319)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
    at org.eclipse.jetty.io.SocketChannelEndPoint.run(SocketChannelEndPoint.java:101)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:412)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:381)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:268)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.produce(AdaptiveExecutionStrategy.java:190)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:894)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1038)
    at java.base/java.lang.Thread.run(Thread.java:831)
Caused by: jakarta.servlet.ServletException: A MultiException has 2 exceptions.  They are:
1. java.lang.IllegalArgumentException: org.glassfish.hk2.api.ProxyCtl referenced from a method is not visible from class loader
2. java.lang.IllegalArgumentException: While attempting to create a Proxy for jakarta.servlet.http.HttpServletRequest in scope org.glassfish.jersey.process.internal.RequestScoped an error occured while creating the proxy
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:410)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:366)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:319)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
    at org.eclipse.jetty.servlet.ServletHolder$NotAsync.service(ServletHolder.java:1410)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:508)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:131)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:580)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:223)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1571)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1370)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:463)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1544)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1292)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:192)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:141)
    ... 16 more

我的原始代码如下所示:

@Provider
@Priority(Priorities.AUTHENTICATION)
public class SecurityFilter implements ContainerRequestFilter {
    @Context
    private HttpServletRequest servletRequest;
    
    @Override
    public void filter(ContainerRequestContext filterContext) throws IOException {
    }
}

这给出了相同的两个异常加上另外 4 个。@Inject 方法在调用操作时导致异常,@Context 在服务器启动时导致异常,但在任何一种情况下,很明显 httpServletRequest 不能由迪 Container/Scope.

我不是 100% 确定所有这些位是如何协同工作的,但如果我没记错的话,该应用程序使用 Jetty 11.0.6 自托管 Web 服务器和 Jersey 3.0.2 容器,运行ning Jakarta Platform 9.1.0 - Servlet API V5.0 和 Jakarta JAXB Web 服务。我认为我缺少依赖项,但我无法确定它是什么。这是我的 POM 和 Web.xml 文件:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>Demo-Server</groupId>
    <artifactId>Demo-Server</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>Demo Server</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <release>16</release>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.3</version>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.5</version>
        </dependency>
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.17</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.10.9.2</version>
        </dependency>
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>9.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>5.0.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-util</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-http</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-plus</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>3.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
            <version>3.0.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.32</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.32</version>
        </dependency>
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <version>9.2.1.jre11</version>
        </dependency>
        <dependency>
            <groupId>com.sap.cloud.db.jdbc</groupId>
            <artifactId>ngdbc</artifactId>
            <version>2.9.12</version>
            <type>pom</type>
        </dependency>
    </dependencies>
    <repositories>
        <repository>
            <id>maven2</id>
            <url>https://repo1.maven.org/maven2/</url>
        </repository>
    </repositories>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" version="5.0">
    <servlet>
        <servlet-name>demo</servlet-name>
        <servlet-class>com.demo.bridge.app.Application</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>demo</servlet-name>
        <url-pattern>/demo/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>demo</servlet-name>
        <url-pattern>/webts/*</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.demo.rest.service</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/service/*</url-pattern>
    </servlet-mapping>
</web-app>

我真的希望有人知道我错过了什么。仅供参考 - 我已将所有当前依赖项留在我的 POM 中,而不仅仅是那些我认为相关的依赖项,因为可能是我有多个依赖项导致了问题。

服务器启动代码更难清理,但如果需要我可以post它 - 主要位是一个 WebAppContext,它似乎确实读取了 Servlets - 如果我不这样做,servlets 也会响应'不使用@Context,它们只是因为空引用或错误的 DI 设置而崩溃。

非常感谢任何帮助。

--更新--

我一直在切入和切出一些 Maven 依赖项。我很确定我有 Jetty、Jakarta、JAXB 和 Jersey 的基本依赖项,但我仍然遇到 @Context/@Inject 的问题。我可以说我绝对需要 org.glassfish.jersey.inject:jersey-hk2 包,因为如果我遗漏它,我会得到一个错误:java.lang.IllegalStateException: InjectionManagerFactory not found.。如果我还添加 jakarta.inject:jakarta-inject-api,我仍然得到原来的错误。

所以基本上我有两个注入包,@Context/@Inject 不适用于其中一个或两个。我想知道 Jakarta 9 是否需要一些设置代码,但我在任何示例中都没有看到。

我的 pom 依赖项现在看起来像这样 - 仍然没有快乐(我也遗漏了应用程序部门):

        <!-- Jakarta -->
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>9.1.0</version>
            <scope>provided</scope>
        </dependency>
         <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>5.0.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jakarta.inject</groupId>
            <artifactId>jakarta.inject-api</artifactId>
            <version>2.0.0</version>
        </dependency>
    
        <!-- JAXB -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>3.0.1</version>
        </dependency>
    
        <!-- Jetty -->
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-webapp</artifactId>
            <version>11.0.6</version>
        </dependency>
    
        <!-- Jersey -->
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>3.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
            <version>3.0.2</version>
        </dependency>

最新更新:

于是又换回了OpenJDK 8,期待项目能运行,结果发现不行。在将 Jars 与原始项目进行比较时,我注意到我的新程序有不同的 Jars。再往下看,现有项目没有HK2文件,但这些文件是在jersey-common包中发货的。

有谁知道如何在不运送 HK2 jar 的情况下在项目中拥有 Jersey,因为 HttpServletRequest 的注入在没有它们的情况下也能正常工作?

马克

所以这个问题很难解决,因为元素在 Jetty、Jakarta 和 Jersey 之间交互的方式在 运行 时间都在幕后,即程序成功编译了任意数量的排列那行不通。

总之,经过7天左右的实验,HttpServletRequest注入有效的包集合如下:

        <!-- Jakarta -->
        <dependency>
          <groupId>org.eclipse.jetty.toolchain</groupId>
          <artifactId>jetty-jakarta-servlet-api</artifactId>
          <version>5.0.1</version>
          <!-- <scope>provided</scope> -->
        </dependency>
        <dependency>
            <groupId>org.glassfish.hk2.external</groupId>
            <artifactId>jakarta.inject</artifactId>
            <version>2.6.1</version>
        </dependency>

        <!-- JAXB -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>3.0.1</version>
        </dependency>
    
        <!-- Jetty -->
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-http</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-io</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-security</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-util</artifactId>
            <version>11.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-webapp</artifactId>
            <version>11.0.6</version>
        </dependency>
            <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-xml</artifactId>
            <version>11.0.6</version>
        </dependency>
    
        <!-- Jersey -->
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-client</artifactId>
            <version>3.0.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-common</artifactId>
            <version>3.0.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>3.0.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>3.0.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>3.0.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
            <version>3.0.2</version>
            <scope>provided</scope>
        </dependency>

我在Java 8编译我的原始项目时发现了这个问题(因为它是在我添加Maven之前)并且我发现我的非Maven项目没有输出3个hk2相关库,hk2-api-2.2.0-b21.jar, hk2-locator-2.2.0-b21.jar, hk2-utils-2.2.0-b21.jar。删除这些文件允许程序正常 运行。

然后我尝试使用依赖项排除,但即使我最终得到了相同的库,该程序也无法运行。现在我不太确定这是如何工作的,但我记得读过可以将依赖项的范围限定为 'provided' 这就是说(如果我理解正确的话) - 所需的 class 实现已经存在于某些您已经拥有的库(如 JRE 或其他依赖项),因此您不必再次包含这些库。

再说一次 - 我不明白为什么会这样,但绝对必须这样设置。我真的希望这可以节省几天时间!