Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Spring Boot management port at runtime when management.port=0

I'm looking for advice on how to get the port that was assigned to the embedded tomcat that is serving the actuator endpoint when setting management.port property to 0 in integration tests.

Im using Spring Boot 1.3.2 with the following application.yml configuration:

server.port: 8080
server.contextPath: /my-app-context-path

management.port: 8081
management.context-path: /manage

...

my integration tests are then annotated with @WebIntegrationTest, setting the ports shown above to 0

@WebIntegrationTest({ "server.port=0", "management.port=0" })

and the following utility class should be used to get access to the application configuration when doing full integration tests:

@Component
@Profile("testing")
class TestserverInfo {

    @Value( '${server.contextPath:}' )
    private String contextPath;

    @Autowired
    private EmbeddedWebApplicationContext server;

    @Autowired
    private ManagementServerProperties managementServerProperties


    public String getBasePath() {
        final int serverPort = server.embeddedServletContainer.port

        return "http://localhost:${serverPort}${contextPath}"
    }

    public String getManagementPath() {
        // The following wont work here:
        // server.embeddedServletContainer.port -> regular server port
        // management.port -> is zero just as server.port as i want random ports

        final int managementPort = // how can i get this one ?
        final String managementPath = managementServerProperties.getContextPath()

        return "http://localhost:${managementPort}${managementPath}"
    }
}

I allready know the standard port can be get by using the local.server.port and there seems to be some equivalent for the management endpoint named local.management.port. But that one seems to have a different meaning.

Edit: The official documentation doesn't mention a way to do this: (http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-discover-the-http-port-at-runtime)

Is there currently any undocumented way to get a hand on that management port?


Solution Edit:

As I am using the Spock-Framework and Spock-Spring for testing my spring-boot application, i have to initialize the application using:

@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = MyApplication.class)

Somehow Spock-Spring or the test-initialization seems to affect the evaluation of the @Value Annotation so that @Value("${local.management.port}") resulted in

java.lang.IllegalArgumentException: Could not resolve placeholder 'local.management.port' in string value "${local.management.port}"

With your solution i knew the property existed, so I simply use the spring Environment directly to retrieve the property-value at test runtime:

@Autowired
ManagementServerProperties managementServerProperties

@Autowired
Environment environment

public String getManagementPath() {
    final int managementPort = environment.getProperty('local.management.port', Integer.class)
    final String managementPath = managementServerProperties.getContextPath()

    return "http://localhost:${managementPort}${managementPath}"
}
like image 761
mawi Avatar asked Apr 12 '16 08:04

mawi


People also ask

How do you get the spring boot host and port address during run time?

You can get this information via Environment for the port and the host you can obtain by using InternetAddress . Getting the port this way will only work, if a) the port is actually configured explicitly, and b) it is not set to 0 (meaning the servlet container will choose a random port on startup).

How do I change the running port of spring boot?

We can change the port of the Spring Boot in the following ways: By Adding the configuration in the application properties of the Spring Boot project. By Implementing the WebServerFactoryCustomizer interface in the component class. Changing the configuration of VM options.


1 Answers

Management port needs to be set to 0 via the @SpringBootTest's properties field and then to get the port in the tests use @LocalServerPort and/or @LocalManagementPort annotations.

Examples:

From Spring Boot 2.0.0:
properties = {"management.server.port=0"}

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
        "management.server.port=0" })
public class HealthCheckIT {

    @Autowired
    private WebTestClient webTestClient;

    @LocalManagementPort
    int managementPort;

    @Test
    public void testManagementPort() {
        webTestClient
                .get().uri("http://localhost:" + managementPort + "/actuator/health")
                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus().isOk();
    }
}

For older versions: [1.4.0 - 1.5.x]:
properties = {"management.port=0"}

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
    "management.port=0", "management.context-path=/admin" })
public class SampleTest {

    @LocalServerPort
    int port;

    @LocalManagementPort
    int managementPort;
like image 179
magiccrafter Avatar answered Oct 19 '22 15:10

magiccrafter