1717
1818package org .openqa .selenium .environment .webserver ;
1919
20+ import static com .google .common .net .HttpHeaders .CONTENT_TYPE ;
21+ import static java .util .Collections .singletonMap ;
22+ import static org .openqa .selenium .json .Json .JSON_UTF_8 ;
23+ import static org .openqa .selenium .remote .http .Contents .string ;
24+
2025import com .google .common .collect .ImmutableMap ;
26+
27+ import net .jodah .failsafe .Failsafe ;
28+ import net .jodah .failsafe .RetryPolicy ;
29+
2130import org .openqa .selenium .grid .config .CompoundConfig ;
2231import org .openqa .selenium .grid .config .Config ;
2332import org .openqa .selenium .grid .config .MapConfig ;
2837import org .openqa .selenium .io .TemporaryFilesystem ;
2938import org .openqa .selenium .net .PortProber ;
3039import org .openqa .selenium .netty .server .NettyServer ;
40+ import org .openqa .selenium .netty .server .ServerBindException ;
3141import org .openqa .selenium .remote .http .Contents ;
3242import org .openqa .selenium .remote .http .HttpClient ;
3343import org .openqa .selenium .remote .http .HttpHandler ;
4050import java .io .UncheckedIOException ;
4151import java .net .MalformedURLException ;
4252import java .net .URL ;
43-
44- import static com .google .common .net .HttpHeaders .CONTENT_TYPE ;
45- import static java .util .Collections .singletonMap ;
46- import static org .openqa .selenium .json .Json .JSON_UTF_8 ;
47- import static org .openqa .selenium .remote .http .Contents .string ;
53+ import java .time .temporal .ChronoUnit ;
54+ import java .util .logging .Level ;
55+ import java .util .logging .Logger ;
4856
4957public class NettyAppServer implements AppServer {
5058
5159 private final static Config sslConfig = new MapConfig (
5260 singletonMap ("server" , singletonMap ("https-self-signed" , true )));
53-
54- private final Server <?> server ;
55- private final Server <?> secure ;
61+ private static final Logger LOG = Logger .getLogger (NettyAppServer .class .getName ());
62+ private Server <?> server ;
63+ private Server <?> secure ;
64+ private final RetryPolicy <Object > retryPolicy = new RetryPolicy <>()
65+ .withMaxAttempts (5 )
66+ .withDelay (100 , 1000 , ChronoUnit .MILLIS )
67+ .handle (ServerBindException .class )
68+ .onRetry (e -> {
69+ LOG .log (Level .WARNING , String .format ("NettyAppServer retry #%s. " , e .getAttemptCount ()));
70+ initValues ();
71+ })
72+ .onRetriesExceeded (e -> LOG .log (Level .WARNING , "NettyAppServer start aborted." ));
5673
5774 public NettyAppServer () {
75+ initValues ();
76+ }
77+
78+ public NettyAppServer (HttpHandler handler ) {
79+ this (
80+ createDefaultConfig (),
81+ Require .nonNull ("Handler" , handler ));
82+ }
83+
84+ private NettyAppServer (Config config , HttpHandler handler ) {
85+ Require .nonNull ("Config" , config );
86+ Require .nonNull ("Handler" , handler );
87+
88+ server = new NettyServer (new BaseServerOptions (new MemoizedConfig (config )), handler );
89+ secure = null ;
90+ }
91+
92+ private static Config createDefaultConfig () {
93+ return new MemoizedConfig (new MapConfig (
94+ singletonMap ("server" , singletonMap ("port" , PortProber .findFreePort ()))));
95+ }
96+
97+ public static void main (String [] args ) {
98+ MemoizedConfig
99+ config =
100+ new MemoizedConfig (new MapConfig (singletonMap ("server" , singletonMap ("port" , 2310 ))));
101+ BaseServerOptions options = new BaseServerOptions (config );
102+
103+ HttpHandler handler = new HandlersForTests (
104+ options .getHostname ().orElse ("localhost" ),
105+ options .getPort (),
106+ TemporaryFilesystem .getDefaultTmpFS ().createTempDir ("netty" , "server" ).toPath ());
107+
108+ NettyAppServer server = new NettyAppServer (
109+ config ,
110+ handler );
111+ server .start ();
112+
113+ System .out .printf ("Server started. Root URL: %s%n" , server .whereIs ("/" ));
114+ }
115+
116+ private void initValues () {
58117 Config config = createDefaultConfig ();
59118 BaseServerOptions options = new BaseServerOptions (config );
60119
@@ -78,31 +137,16 @@ public NettyAppServer() {
78137 secure = new NettyServer (secureOptions , secureHandler );
79138 }
80139
81- public NettyAppServer (HttpHandler handler ) {
82- this (
83- createDefaultConfig (),
84- Require .nonNull ("Handler" , handler ));
85- }
86-
87- private NettyAppServer (Config config , HttpHandler handler ) {
88- Require .nonNull ("Config" , config );
89- Require .nonNull ("Handler" , handler );
90-
91- server = new NettyServer (new BaseServerOptions (new MemoizedConfig (config )), handler );
92- secure = null ;
93- }
94-
95- private static Config createDefaultConfig () {
96- return new MemoizedConfig (new MapConfig (
97- singletonMap ("server" , singletonMap ("port" , PortProber .findFreePort ()))));
98- }
99-
100140 @ Override
101141 public void start () {
102- server .start ();
103- if (secure != null ) {
104- secure .start ();
105- }
142+ Failsafe .with (retryPolicy ).run (
143+ () -> {
144+ server .start ();
145+ if (secure != null ) {
146+ secure .start ();
147+ }
148+ }
149+ );
106150 }
107151
108152 @ Override
@@ -181,21 +225,4 @@ public String getHostName() {
181225 public String getAlternateHostName () {
182226 return AppServer .detectAlternateHostname ();
183227 }
184-
185- public static void main (String [] args ) {
186- MemoizedConfig config = new MemoizedConfig (new MapConfig (singletonMap ("server" , singletonMap ("port" , 2310 ))));
187- BaseServerOptions options = new BaseServerOptions (config );
188-
189- HttpHandler handler = new HandlersForTests (
190- options .getHostname ().orElse ("localhost" ),
191- options .getPort (),
192- TemporaryFilesystem .getDefaultTmpFS ().createTempDir ("netty" , "server" ).toPath ());
193-
194- NettyAppServer server = new NettyAppServer (
195- config ,
196- handler );
197- server .start ();
198-
199- System .out .printf ("Server started. Root URL: %s%n" , server .whereIs ("/" ));
200- }
201228}
0 commit comments