2323import java .util .concurrent .ExecutionException ;
2424import java .util .concurrent .Executor ;
2525import java .util .concurrent .RejectedExecutionException ;
26+ import java .util .concurrent .atomic .AtomicBoolean ;
2627import java .util .concurrent .atomic .AtomicInteger ;
2728import java .util .function .BiConsumer ;
2829import java .util .function .BiFunction ;
4647import io .netty .handler .codec .http .HttpHeaderNames ;
4748import io .netty .handler .codec .http .HttpResponseStatus ;
4849import io .quarkus .arc .Arc ;
50+ import io .quarkus .arc .ArcContainer ;
4951import io .quarkus .arc .InstanceHandle ;
5052import io .quarkus .arc .runtime .BeanContainer ;
5153import io .quarkus .bootstrap .runner .Timing ;
7173import io .quarkus .tls .runtime .config .TlsConfig ;
7274import io .quarkus .vertx .core .runtime .VertxCoreRecorder ;
7375import io .quarkus .vertx .core .runtime .config .VertxConfiguration ;
76+ import io .quarkus .vertx .http .DomainSocketServerStart ;
7477import io .quarkus .vertx .http .HttpServerOptionsCustomizer ;
78+ import io .quarkus .vertx .http .HttpServerStart ;
79+ import io .quarkus .vertx .http .HttpsServerStart ;
7580import io .quarkus .vertx .http .ManagementInterface ;
7681import io .quarkus .vertx .http .runtime .HttpConfiguration .InsecureRequests ;
7782import io .quarkus .vertx .http .runtime .devmode .RemoteSyncHandler ;
@@ -744,8 +749,9 @@ private static CompletableFuture<String> initializeMainHttpServer(Vertx vertx, H
744749 launchMode , websocketSubProtocols , registry );
745750
746751 // Customize
747- if (Arc .container () != null ) {
748- List <InstanceHandle <HttpServerOptionsCustomizer >> instances = Arc .container ()
752+ ArcContainer container = Arc .container ();
753+ if (container != null ) {
754+ List <InstanceHandle <HttpServerOptionsCustomizer >> instances = container
749755 .listAll (HttpServerOptionsCustomizer .class );
750756 for (InstanceHandle <HttpServerOptionsCustomizer > instance : instances ) {
751757 HttpServerOptionsCustomizer customizer = instance .get ();
@@ -784,12 +790,17 @@ private static CompletableFuture<String> initializeMainHttpServer(Vertx vertx, H
784790 CompletableFuture <String > futureResult = new CompletableFuture <>();
785791
786792 AtomicInteger connectionCount = new AtomicInteger ();
793+
794+ // Note that a new HttpServer is created for each IO thread but we only want to fire the events (HttpServerStart etc.) once,
795+ // for the first server that started listening
796+ // See https://vertx.io/docs/vertx-core/java/#_server_sharing for more information
797+ AtomicBoolean startEventsFired = new AtomicBoolean ();
798+
787799 vertx .deployVerticle (new Supplier <Verticle >() {
788800 @ Override
789801 public Verticle get () {
790802 return new WebDeploymentVerticle (httpMainServerOptions , httpMainSslServerOptions , httpMainDomainSocketOptions ,
791- launchMode ,
792- insecureRequestStrategy , httpConfiguration , connectionCount , registry );
803+ launchMode , insecureRequestStrategy , httpConfiguration , connectionCount , registry , startEventsFired );
793804 }
794805 }, new DeploymentOptions ().setInstances (ioThreads ), new Handler <AsyncResult <String >>() {
795806 @ Override
@@ -1129,11 +1140,12 @@ private static class WebDeploymentVerticle extends AbstractVerticle implements R
11291140 private final HttpConfiguration quarkusConfig ;
11301141 private final AtomicInteger connectionCount ;
11311142 private final List <Long > reloadingTasks = new CopyOnWriteArrayList <>();
1143+ private final AtomicBoolean startEventsFired ;
11321144
11331145 public WebDeploymentVerticle (HttpServerOptions httpOptions , HttpServerOptions httpsOptions ,
11341146 HttpServerOptions domainSocketOptions , LaunchMode launchMode ,
11351147 InsecureRequests insecureRequests , HttpConfiguration quarkusConfig , AtomicInteger connectionCount ,
1136- TlsConfigurationRegistry registry ) {
1148+ TlsConfigurationRegistry registry , AtomicBoolean startEventsFired ) {
11371149 this .httpOptions = httpOptions ;
11381150 this .httpsOptions = httpsOptions ;
11391151 this .launchMode = launchMode ;
@@ -1142,6 +1154,7 @@ public WebDeploymentVerticle(HttpServerOptions httpOptions, HttpServerOptions ht
11421154 this .quarkusConfig = quarkusConfig ;
11431155 this .connectionCount = connectionCount ;
11441156 this .registry = registry ;
1157+ this .startEventsFired = startEventsFired ;
11451158 org .crac .Core .getGlobalContext ().register (this );
11461159 }
11471160
@@ -1166,6 +1179,9 @@ public void start(Promise<Void> startFuture) {
11661179 .fail (new IllegalArgumentException ("Must configure at least one of http, https or unix domain socket" ));
11671180 }
11681181
1182+ ArcContainer container = Arc .container ();
1183+ boolean notifyStartObservers = container != null ? startEventsFired .compareAndSet (false , true ) : false ;
1184+
11691185 if (httpServerEnabled ) {
11701186 httpServer = vertx .createHttpServer (httpOptions );
11711187 if (insecureRequests == HttpConfiguration .InsecureRequests .ENABLED ) {
@@ -1196,27 +1212,34 @@ public void handle(HttpServerRequest req) {
11961212 }
11971213 });
11981214 }
1199- setupTcpHttpServer (httpServer , httpOptions , false , startFuture , remainingCount , connectionCount );
1215+ setupTcpHttpServer (httpServer , httpOptions , false , startFuture , remainingCount , connectionCount ,
1216+ container , notifyStartObservers );
12001217 }
12011218
12021219 if (domainSocketOptions != null ) {
12031220 domainSocketServer = vertx .createHttpServer (domainSocketOptions );
12041221 domainSocketServer .requestHandler (ACTUAL_ROOT );
1205- setupUnixDomainSocketHttpServer (domainSocketServer , domainSocketOptions , startFuture , remainingCount );
1222+ setupUnixDomainSocketHttpServer (domainSocketServer , domainSocketOptions , startFuture , remainingCount ,
1223+ container , notifyStartObservers );
12061224 }
12071225
12081226 if (httpsOptions != null ) {
12091227 httpsServer = vertx .createHttpServer (httpsOptions );
12101228 httpsServer .requestHandler (ACTUAL_ROOT );
1211- setupTcpHttpServer (httpsServer , httpsOptions , true , startFuture , remainingCount , connectionCount );
1229+ setupTcpHttpServer (httpsServer , httpsOptions , true , startFuture , remainingCount , connectionCount ,
1230+ container , notifyStartObservers );
12121231 }
12131232 }
12141233
12151234 private void setupUnixDomainSocketHttpServer (HttpServer httpServer , HttpServerOptions options ,
12161235 Promise <Void > startFuture ,
1217- AtomicInteger remainingCount ) {
1236+ AtomicInteger remainingCount , ArcContainer container , boolean notifyStartObservers ) {
12181237 httpServer .listen (SocketAddress .domainSocketAddress (options .getHost ()), event -> {
12191238 if (event .succeeded ()) {
1239+ if (notifyStartObservers ) {
1240+ container .beanManager ().getEvent ().select (DomainSocketServerStart .class )
1241+ .fireAsync (new DomainSocketServerStart (options ));
1242+ }
12201243 if (remainingCount .decrementAndGet () == 0 ) {
12211244 startFuture .complete (null );
12221245 }
@@ -1240,7 +1263,8 @@ private void setupUnixDomainSocketHttpServer(HttpServer httpServer, HttpServerOp
12401263 }
12411264
12421265 private void setupTcpHttpServer (HttpServer httpServer , HttpServerOptions options , boolean https ,
1243- Promise <Void > startFuture , AtomicInteger remainingCount , AtomicInteger currentConnectionCount ) {
1266+ Promise <Void > startFuture , AtomicInteger remainingCount , AtomicInteger currentConnectionCount ,
1267+ ArcContainer container , boolean notifyStartObservers ) {
12441268
12451269 if (quarkusConfig .limits .maxConnections .isPresent () && quarkusConfig .limits .maxConnections .getAsInt () > 0 ) {
12461270 var tracker = vertx .isMetricsEnabled ()
@@ -1315,11 +1339,20 @@ public void handle(AsyncResult<HttpServer> event) {
13151339 }
13161340
13171341 if (https ) {
1318- CDI . current (). select (HttpCertificateUpdateEventListener .class ).get ()
1342+ container . instance (HttpCertificateUpdateEventListener .class ).get ()
13191343 .register (event .result (), quarkusConfig .tlsConfigurationName .orElse (TlsConfig .DEFAULT_NAME ),
13201344 "http server" );
13211345 }
13221346
1347+ if (notifyStartObservers ) {
1348+ Event <Object > startEvent = container .beanManager ().getEvent ();
1349+ if (https ) {
1350+ startEvent .select (HttpsServerStart .class ).fireAsync (new HttpsServerStart (options ));
1351+ } else {
1352+ startEvent .select (HttpServerStart .class ).fireAsync (new HttpServerStart (options ));
1353+ }
1354+ }
1355+
13231356 if (remainingCount .decrementAndGet () == 0 ) {
13241357 //make sure we only complete once
13251358 startFuture .complete (null );
0 commit comments