public void start()

in runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/JettyServletEngineAdapter.java [99:208]


  public void start(String serverInfo, ServletEngineAdapter.Config runtimeOptions) {
    boolean isHttpConnectorMode = Boolean.getBoolean(HTTP_CONNECTOR_MODE);
    QueuedThreadPool threadPool =
        new QueuedThreadPool(MAX_THREAD_POOL_THREADS, MIN_THREAD_POOL_THREADS);
    // Try to enable virtual threads if requested and on java21:
    if (Boolean.getBoolean("appengine.use.virtualthreads")
        && "java21".equals(GAE_RUNTIME)) {
      threadPool.setVirtualThreadsExecutor(VirtualThreads.getDefaultVirtualThreadsExecutor());
      logger.atInfo().log("Configuring Appengine web server virtual threads.");
    }

    server =
        new Server(threadPool) {
          @Override
          public InvocationType getInvocationType() {
            return InvocationType.BLOCKING;
          }
        };

    // Don't add the RPC Connector if in HttpConnector mode.
    if (!isHttpConnectorMode) {
      rpcConnector =
          new DelegateConnector(server, "RPC") {
            @Override
            public void run(Runnable runnable) {
              // Override this so that it does the initial run in the same thread.
              // Currently, we block until completion in serviceRequest() so no point starting new
              // thread.
              runnable.run();
            }
          };

      HttpConfiguration httpConfiguration = rpcConnector.getHttpConfiguration();
      httpConfiguration.setSendDateHeader(false);
      httpConfiguration.setSendServerVersion(false);
      httpConfiguration.setSendXPoweredBy(false);

      // If runtime is using EE8, then set URI compliance to LEGACY to behave like Jetty 9.4.
      if (Objects.equals(AppVersionHandlerFactory.getEEVersion(), AppVersionHandlerFactory.EEVersion.EE8)) {
        httpConfiguration.setUriCompliance(UriCompliance.LEGACY);
      }

      if (LEGACY_MODE) {
        httpConfiguration.setUriCompliance(UriCompliance.LEGACY);
        httpConfiguration.setHttpCompliance(HttpCompliance.RFC7230_LEGACY);
        httpConfiguration.setRequestCookieCompliance(CookieCompliance.RFC2965);
        httpConfiguration.setResponseCookieCompliance(CookieCompliance.RFC2965);
        httpConfiguration.setMultiPartCompliance(MultiPartCompliance.LEGACY);
      }

      server.addConnector(rpcConnector);
    }

    AppVersionHandlerFactory appVersionHandlerFactory =
        AppVersionHandlerFactory.newInstance(server, serverInfo);
    appVersionHandler = new AppVersionHandler(appVersionHandlerFactory);
    server.setHandler(appVersionHandler);

    // In HttpConnector mode we will combine both SizeLimitHandlers.
    boolean ignoreResponseSizeLimit = Boolean.getBoolean(IGNORE_RESPONSE_SIZE_LIMIT);
    if (!ignoreResponseSizeLimit && !isHttpConnectorMode) {
      server.insertHandler(new SizeLimitHandler(-1, MAX_RESPONSE_SIZE));
    }

    boolean startJettyHttpProxy = false;
    if (runtimeOptions.useJettyHttpProxy()) {
      AppInfoFactory appInfoFactory;
      AppVersionKey appVersionKey;
      /* The init actions are not done in the constructor as they are not used when testing */
      try {
        String appRoot = runtimeOptions.applicationRoot();
        String appPath = runtimeOptions.fixedApplicationPath();
        appInfoFactory = new AppInfoFactory(System.getenv());
        AppinfoPb.AppInfo appinfo = appInfoFactory.getAppInfoFromFile(appRoot, appPath);
        // TODO Should we also call ApplyCloneSettings()?
        LocalRpcContext<EmptyMessage> context = new LocalRpcContext<>(EmptyMessage.class);
        EvaluationRuntimeServerInterface evaluationRuntimeServerInterface =
            Objects.requireNonNull(runtimeOptions.evaluationRuntimeServerInterface());
        evaluationRuntimeServerInterface.addAppVersion(context, appinfo);
        context.getResponse();
        appVersionKey = AppVersionKey.fromAppInfo(appinfo);
      } catch (Exception e) {
        throw new IllegalStateException(e);
      }
      if (isHttpConnectorMode) {
        logger.atInfo().log("Using HTTP_CONNECTOR_MODE to bypass RPC");
        server.insertHandler(
            new JettyHttpHandler(
                runtimeOptions, appVersionHandler.getAppVersion(), appVersionKey, appInfoFactory));
        JettyHttpProxy.insertHandlers(server, ignoreResponseSizeLimit);
        server.addConnector(JettyHttpProxy.newConnector(server, runtimeOptions));
      } else {
        server.setAttribute(
            "com.google.apphosting.runtime.jetty.appYaml",
            JettyServletEngineAdapter.getAppYaml(runtimeOptions));
        // Delay start of JettyHttpProxy until after the main server and application is started.
        startJettyHttpProxy = true;
      }
    }
    try {
      server.start();
      if (startJettyHttpProxy) {
        JettyHttpProxy.startServer(runtimeOptions);
      }
    } catch (Exception ex) {
      // TODO: Should we have a wrapper exception for this
      // type of thing in ServletEngineAdapter?
      throw new RuntimeException(ex);
    }
  }