001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.microservice.test; 018 019import java.time.*; 020 021import org.apache.juneau.commons.inject.*; 022import org.apache.juneau.microservice.jetty.*; 023import org.eclipse.jetty.ee11.servlet.*; 024import org.eclipse.jetty.server.*; 025 026/** 027 * A {@code @Configuration} that supplies a Jetty {@link Server} bound to an OS-assigned ephemeral port 028 * (port {@code 0}) for use by {@link MicroserviceExtension @MicroserviceTest}-driven integration tests. 029 * 030 * <p> 031 * The server has a single {@link ServerConnector} on port 0 and a single root {@link ServletContextHandler} 032 * at context path {@code "/"}. {@code JettyServerComponent} discovers the handler via the 033 * {@code "ServletContextHandler"} server attribute (the same convention used by {@code jetty.xml}). 034 * 035 * <p> 036 * The extension installs this {@code @Configuration} automatically after the user-supplied configurations, so 037 * a user-supplied {@code @Bean Server} (if any) still wins (the bean store returns the first registered match). 038 * Tests supply their {@code @Bean Servlet} definitions, which {@code JettyServerComponent} auto-mounts at the 039 * resource's {@code @Rest(path=...)}. 040 * 041 * @since 10.0.0 042 */ 043@Configuration 044public class EphemeralJettyServerConfig { 045 046 /** 047 * Provides the bean-supplied Jetty {@link Server} that {@code JettyServerComponent} consumes during 048 * {@code onStart()}. 049 * 050 * @return A configured {@link Server} bound to port 0 (OS-assigned ephemeral port). 051 */ 052 @Bean 053 @SuppressWarnings({ 054 "resource" // connector is added to and owned by the server; closed when the server stops. 055 }) 056 public Server jettyServer() { 057 var server = new Server(); 058 var connector = new ServerConnector(server); 059 connector.setPort(0); 060 server.addConnector(connector); 061 var sch = new ServletContextHandler(); 062 sch.setContextPath("/"); 063 server.setAttribute("ServletContextHandler", sch); 064 server.setHandler(sch); 065 return server; 066 } 067 068 /** 069 * Disables the 30s graceful-shutdown drain wait for integration tests. 070 * 071 * <p> 072 * {@code JettyServerComponent} applies a 30s {@code stopTimeout} default to support zero-downtime k8s 073 * rollouts. In ephemeral test servers there are no load balancers or in-flight production traffic, so 074 * the drain wait only adds ~1s per test class to the suite runtime. Setting it to zero restores fast 075 * shutdown. 076 * 077 * @return {@link JettySettings} with {@code stopTimeout} set to zero. 078 */ 079 @Bean 080 public JettySettings jettySettings() { 081 return JettySettings.create() 082 .stopTimeout(Duration.ZERO) 083 .build(); 084 } 085}