2016-01-08 4 views
3

В документации API для Java Spark (не искры Apache) вы можете указать порт 0, чтобы он автоматически выбирал порт. Большой!Как получить автоматически определенный порт для приложения Spark Java?

Однако я не могу понять, как получить этот порт после запуска сервера. Я могу видеть это в журналах:

15:41:12.459 [Thread-2] INFO spark.webserver.JettySparkServer - >> Listening on 0.0.0.0:63134 

Но мне нужно, чтобы иметь возможность получить к нему программно, так что мои тесты интеграции способны надежно работать каждый раз.

Так как я могу получить этот порт?

+0

Есть ли что-то в Sparks собственные тесты? – Marged

+0

https://github.com/perwendel/spark/blob/master/src/test/java/spark/servlet/ServletTest.java#L23 Они используют жестко кодированные порты в своих тестах, а не случайные :( – BeepDog

ответ

2

Я не мог найти способ получить эту информацию в API, поэтому я подал issue on their github.

я был в состоянии получить на него через уродливую груду отражения:

/** 
* Meant to be called from a different thread, once the spark app is running 
* This is probably only going to be used during the integration testing process, not ever in prod! 
* 
* @return the port it's running on 
*/ 
public static int awaitRunningPort() throws Exception { 
    awaitInitialization(); 
    //I have to get the port via reflection, which is fugly, but the API doesn't exist :(
    //Since we'll only use this in testing, it's not going to kill us 
    Object instance = getInstance(); 
    Class theClass = instance.getClass(); 
    Field serverField = theClass.getDeclaredField("server"); 
    serverField.setAccessible(true); 
    Object oneLevelDeepServer = serverField.get(instance); 

    Class jettyServerClass = oneLevelDeepServer.getClass(); 
    Field jettyServerField = jettyServerClass.getDeclaredField("server"); 
    jettyServerField.setAccessible(true); 
    //Have to pull in the jetty server stuff to do this mess 
    Server jettyServer = (Server)jettyServerField.get(oneLevelDeepServer); 

    int acquiredPort = ((ServerConnector)jettyServer.getConnectors()[0]).getLocalPort(); 

    log.debug("Acquired port: {}", acquiredPort); 
    return acquiredPort; 
} 

Это хорошо работает для меня в наших тестах интеграции, но я не использую протокол HTTPS, и он достигнет около двух уровней глубоко в API через захват защищенных полей. Я не мог найти другого способа сделать это. Был бы рад оказаться ошибочным.

1

Это будет работать на Спарк 2.6.0:

public static int start (String keystoreFile, String keystorePw) 
{ 
    secure(keystoreFile, keystorePw, null, null); 
    port(0); 

    staticFiles.location("/public"); 

    get(Path.CLOCK, ClockController.time); 
    get(Path.CALENDAR, CalendarController.date); 

    // This is the important line. It must be *after* creating the routes and *before* the call to port() 
    awaitInitialization(); 

    return port(); 
} 

Без вызова awaitInitialization() порт() возвращает 0.