嵌入 Jetty 10 的 GraphQL 订阅

GraphQL subscription with Jetty 10 embedded

我的 objective 是将最新的 Graphql-java 的功能版本与 Jetty 版本 10 混合使用。

我做了很多测试,使用了不同的方法,现在我对 9.4 和 10.0.6 版本之间的 WebSocket 实现(在 Jetty 上)的差异感到困惑。

为了测试我正在处理 graphQL repository sample.

中的示例的实现

我的测试是在子项目 servlet-hello-world 上进行的,其中完成了一个简单的 graphQL 订阅并在 jetty 9.4

上工作

我已经更新 gradle 以使用最新版本

def jettyVersion = '9.4.43.v20210629'

dependencies {
    implementation "com.graphql-java-kickstart:graphql-java-servlet:$LIB_GRAPHQL_SERVLET_VER"
    implementation "io.projectreactor:reactor-core:3.4.9"
    implementation 'ch.qos.logback:logback-classic:1.2.5'
    implementation 'org.slf4j:slf4j-simple:2.0.0-alpha4'
    implementation "org.eclipse.jetty:jetty-webapp:${jettyVersion}"
    implementation "org.eclipse.jetty:jetty-annotations:${jettyVersion}"
    implementation "org.eclipse.jetty.websocket:websocket-api:${jettyVersion}"
    implementation "org.eclipse.jetty.websocket:websocket-server:${jettyVersion}"
    implementation "org.eclipse.jetty.websocket:javax-websocket-server-impl:${jettyVersion}"
    implementation "org.eclipse.jetty.websocket:websocket-common:${jettyVersion}"
}

def jettyVersion = '10.0.6'

dependencies {
    implementation "com.graphql-java-kickstart:graphql-java-servlet:$LIB_GRAPHQL_SERVLET_VER"
    implementation "io.projectreactor:reactor-core:3.4.9"
    implementation 'ch.qos.logback:logback-classic:1.2.5'
    implementation 'org.slf4j:slf4j-simple:2.0.0-alpha4'
//    implementation "org.eclipse.jetty:jetty-webapp:${jettyVersion}"
//    implementation "org.eclipse.jetty:jetty-annotations:${jettyVersion}"
    implementation "org.eclipse.jetty.websocket:websocket-jetty-api:${jettyVersion}"
    implementation "org.eclipse.jetty.websocket:websocket-jetty-server:${jettyVersion}"
//    implementation "org.eclipse.jetty.websocket:javax-websocket-server-impl:${jettyVersion}"
//    implementation "org.eclipse.jetty.websocket:websocket-common:${jettyVersion}"
}

然后我卡在 API 中的更改,其中 WebSocketServletContainerInitalizer 被 JettyWebSocketServletContainerInitializer 替换:

    var server = new Server();
    var connector = new ServerConnector(server);
    connector.setPort(PORT);
    server.addConnector(connector);

    var context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/");
    context.addServlet(HelloServlet.class, "/graphql");
    server.setHandler(context);

    WebSocketServerContainerInitializer.configure(
        context,
        (servletContext, serverContainer) ->
            serverContainer.addEndpoint(
                ServerEndpointConfig.Builder.create(SubscriptionEndpoint.class, "/subscriptions")
                    .configurator(new GraphQLWSEndpointConfigurer())
                    .build()));

    server.setHandler(context);

    server.start();
    server.dump(System.err);
    server.join();
  }

不同之处在于配置器已将配置器的类型从 ServletContainer 更改为 JettyWebSocketServerContainer,并且不再有 addEndpoint 方法将我的 SubscriptionEndpoint 连接到。

我完全不知道如何连接我的 GraphQLWebsocketServlet

Jetty 的旧版本是 websocket 实现中立的(核心,javax.websocket,jetty 本机 websocket 等)。当同时使用多个实现时,事实证明这太复杂了。

新的 Jetty 10+ 实施要求您为您正在使用的实施使用适当的 <Impl>WebSocketServletContainerInitializer。 (其中 <Impl>JavaxJakartaJetty 之一)

因为您似乎在使用 javax.websocket,所以这里是合适的 class。

JavaxWebSocketServletContainerInitializer.configure(context, (servletContext, wsContainer) ->
{
    // This lambda will be called at the appropriate place in the
    // ServletContext initialization phase where you can initialize
    // and configure  your websocket container.

    // Configure defaults for container
    wsContainer.setDefaultMaxTextMessageBufferSize(65535);

    // Add WebSocket endpoint to javax.websocket layer
    wsContainer.addEndpoint(
        ServerEndpointConfig.Builder.create(
            SubscriptionEndpoint.class, "/subscriptions")
            .configurator(new GraphQLWSEndpointConfigurer())
        .build());
});