Add startup Actuator endpoint
This commit builds on top of gh-22603 and exposes data collected by the `BufferingApplicationStartup` on a dedicated `"/startup"` Actuator endpoint. Closes gh-23213pull/23215/head
parent
6be4409fde
commit
676e1809fb
@ -0,0 +1,28 @@
|
|||||||
|
[[startup]]
|
||||||
|
= Application Startup (`startup`)
|
||||||
|
|
||||||
|
The `startup` endpoint provides information about the application's startup sequence.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[startup-retrieving]]
|
||||||
|
== Retrieving the Application Startup steps
|
||||||
|
|
||||||
|
To retrieve the steps recorded so far during the application startup phase , make a `GET` request to `/actuator/startup`, as shown in the following curl-based example:
|
||||||
|
|
||||||
|
include::{snippets}/startup/curl-request.adoc[]
|
||||||
|
|
||||||
|
The resulting response is similar to the following:
|
||||||
|
|
||||||
|
include::{snippets}/startup/http-response.adoc[]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[startup-retrieving-response-structure]]
|
||||||
|
=== Response Structure
|
||||||
|
|
||||||
|
The response contains details of the application startup steps recorded so far by the application.
|
||||||
|
The following table describes the structure of the response:
|
||||||
|
|
||||||
|
[cols="2,1,3"]
|
||||||
|
include::{snippets}/startup/response-fields.adoc[]
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2019 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.actuate.autoconfigure.startup;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
|
||||||
|
import org.springframework.boot.actuate.startup.StartupEndpoint;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||||
|
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ConditionContext;
|
||||||
|
import org.springframework.context.annotation.Conditional;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.metrics.ApplicationStartup;
|
||||||
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link EnableAutoConfiguration Auto-configuration} for the {@link StartupEndpoint}.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
* @since 2.4.0
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnAvailableEndpoint(endpoint = StartupEndpoint.class)
|
||||||
|
@Conditional(StartupEndpointAutoConfiguration.ApplicationStartupCondition.class)
|
||||||
|
public class StartupEndpointAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public StartupEndpoint startupEndpoint(BufferingApplicationStartup applicationStartup) {
|
||||||
|
return new StartupEndpoint(applicationStartup);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link SpringBootCondition} checking the configured
|
||||||
|
* {@link org.springframework.core.metrics.ApplicationStartup}.
|
||||||
|
* <p>
|
||||||
|
* Endpoint is enabled only if the configured implementation is
|
||||||
|
* {@link BufferingApplicationStartup}.
|
||||||
|
*/
|
||||||
|
static class ApplicationStartupCondition extends SpringBootCondition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||||
|
ConditionMessage.Builder message = ConditionMessage.forCondition("ApplicationStartup");
|
||||||
|
ApplicationStartup applicationStartup = context.getBeanFactory().getApplicationStartup();
|
||||||
|
if (applicationStartup instanceof BufferingApplicationStartup) {
|
||||||
|
return ConditionOutcome.match(
|
||||||
|
message.because("configured applicationStartup is of type BufferingApplicationStartup."));
|
||||||
|
}
|
||||||
|
return ConditionOutcome.noMatch(message.because("configured applicationStartup is of type "
|
||||||
|
+ applicationStartup.getClass() + ", expected BufferingApplicationStartup."));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-configuration for actuator ApplicationStartup concerns.
|
||||||
|
*/
|
||||||
|
package org.springframework.boot.actuate.autoconfigure.startup;
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.actuate.startup.StartupEndpoint;
|
||||||
|
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.core.metrics.StartupStep;
|
||||||
|
import org.springframework.restdocs.payload.JsonFieldType;
|
||||||
|
import org.springframework.restdocs.payload.ResponseFieldsSnippet;
|
||||||
|
|
||||||
|
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||||
|
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||||
|
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for generating documentation describing {@link StartupEndpoint}.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
*/
|
||||||
|
class StartupEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void appendSampleStartupSteps(@Autowired BufferingApplicationStartup applicationStartup) {
|
||||||
|
StartupStep starting = applicationStartup.start("spring.boot.application.starting");
|
||||||
|
starting.tag("mainApplicationClass", "com.example.startup.StartupApplication");
|
||||||
|
starting.end();
|
||||||
|
|
||||||
|
StartupStep instantiate = applicationStartup.start("spring.beans.instantiate");
|
||||||
|
instantiate.tag("beanName", "homeController");
|
||||||
|
instantiate.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void startup() throws Exception {
|
||||||
|
ResponseFieldsSnippet responseFields = responseFields(
|
||||||
|
fieldWithPath("springBootVersion").type(JsonFieldType.STRING)
|
||||||
|
.description("Spring Boot version for this application.").optional(),
|
||||||
|
fieldWithPath("timeline.startTime").description("Start time of the application."),
|
||||||
|
fieldWithPath("timeline.events")
|
||||||
|
.description("An array of steps collected during application startup so far."),
|
||||||
|
fieldWithPath("timeline.events.[].startTime").description("The timestamp of the start of this event."),
|
||||||
|
fieldWithPath("timeline.events.[].endTime").description("The timestamp of the end of this event."),
|
||||||
|
fieldWithPath("timeline.events.[].duration").description("The precise duration of this event."),
|
||||||
|
fieldWithPath("timeline.events.[].startupStep.name").description("The name of the StartupStep."),
|
||||||
|
fieldWithPath("timeline.events.[].startupStep.id").description("The id of this StartupStep."),
|
||||||
|
fieldWithPath("timeline.events.[].startupStep.parentId")
|
||||||
|
.description("The parent id for this StartupStep."),
|
||||||
|
fieldWithPath("timeline.events.[].startupStep.tags")
|
||||||
|
.description("An array of key/value pairs with additional step info."),
|
||||||
|
fieldWithPath("timeline.events.[].startupStep.tags[].key")
|
||||||
|
.description("The key of the StartupStep Tag."),
|
||||||
|
fieldWithPath("timeline.events.[].startupStep.tags[].value")
|
||||||
|
.description("The value of the StartupStep Tag."));
|
||||||
|
|
||||||
|
this.mockMvc.perform(get("/actuator/startup")).andExpect(status().isOk())
|
||||||
|
.andDo(document("startup", responseFields));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@Import(BaseDocumentationConfiguration.class)
|
||||||
|
static class TestConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
StartupEndpoint startupEndpoint(BufferingApplicationStartup startup) {
|
||||||
|
return new StartupEndpoint(startup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
BufferingApplicationStartup bufferingApplicationStartup() {
|
||||||
|
return new BufferingApplicationStartup(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.actuate.autoconfigure.startup;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.startup.StartupEndpoint;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
|
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||||
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link StartupEndpointAutoConfiguration}
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
*/
|
||||||
|
class StartupEndpointAutoConfigurationTests {
|
||||||
|
|
||||||
|
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
|
.withConfiguration(AutoConfigurations.of(StartupEndpointAutoConfiguration.class));
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runShouldNotHaveStartupEndpoint() {
|
||||||
|
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(StartupEndpoint.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runWhenMissingAppStartupShouldNotHaveStartupEndpoint() {
|
||||||
|
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=startup")
|
||||||
|
.run((context) -> assertThat(context).doesNotHaveBean(StartupEndpoint.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runShouldHaveStartupEndpoint() {
|
||||||
|
new ApplicationContextRunner(() -> {
|
||||||
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||||
|
context.setApplicationStartup(new BufferingApplicationStartup(1));
|
||||||
|
return context;
|
||||||
|
}).withConfiguration(AutoConfigurations.of(StartupEndpointAutoConfiguration.class))
|
||||||
|
.withPropertyValues("management.endpoints.web.exposure.include=startup")
|
||||||
|
.run((context) -> assertThat(context).hasSingleBean(StartupEndpoint.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.actuate.startup;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringBootVersion;
|
||||||
|
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||||
|
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||||
|
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||||
|
import org.springframework.boot.context.metrics.buffering.StartupTimeline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Endpoint @Endpoint} to expose the timeline of the
|
||||||
|
* {@link org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup
|
||||||
|
* application startup}.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
* @since 2.4.0
|
||||||
|
*/
|
||||||
|
@Endpoint(id = "startup")
|
||||||
|
public class StartupEndpoint {
|
||||||
|
|
||||||
|
private final BufferingApplicationStartup applicationStartup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code StartupEndpoint} that will describe the timeline of buffered
|
||||||
|
* application startup events.
|
||||||
|
* @param applicationStartup the application startup
|
||||||
|
*/
|
||||||
|
public StartupEndpoint(BufferingApplicationStartup applicationStartup) {
|
||||||
|
this.applicationStartup = applicationStartup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReadOperation
|
||||||
|
public StartupResponse startup() {
|
||||||
|
StartupTimeline startupTimeline = this.applicationStartup.drainBufferedTimeline();
|
||||||
|
return new StartupResponse(startupTimeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A description of an application startup, primarily intended for serialization to
|
||||||
|
* JSON.
|
||||||
|
*/
|
||||||
|
public static final class StartupResponse {
|
||||||
|
|
||||||
|
private final String springBootVersion;
|
||||||
|
|
||||||
|
private final StartupTimeline timeline;
|
||||||
|
|
||||||
|
private StartupResponse(StartupTimeline timeline) {
|
||||||
|
this.timeline = timeline;
|
||||||
|
this.springBootVersion = SpringBootVersion.getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSpringBootVersion() {
|
||||||
|
return this.springBootVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StartupTimeline getTimeline() {
|
||||||
|
return this.timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actuator support for {@link org.springframework.core.metrics.ApplicationStartup}.
|
||||||
|
*/
|
||||||
|
package org.springframework.boot.actuate.startup;
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.actuate.startup;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringBootVersion;
|
||||||
|
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||||
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link StartupEndpoint}.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
*/
|
||||||
|
class StartupEndpointTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void startupEventsAreFound() {
|
||||||
|
BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(256);
|
||||||
|
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
|
.withInitializer((context) -> context.setApplicationStartup(applicationStartup))
|
||||||
|
.withUserConfiguration(EndpointConfiguration.class);
|
||||||
|
contextRunner.run((context) -> {
|
||||||
|
StartupEndpoint.StartupResponse startup = context.getBean(StartupEndpoint.class).startup();
|
||||||
|
assertThat(startup.getSpringBootVersion()).isEqualTo(SpringBootVersion.getVersion());
|
||||||
|
assertThat(startup.getTimeline().getStartTime())
|
||||||
|
.isEqualTo(applicationStartup.getBufferedTimeline().getStartTime());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void bufferIsDrained() {
|
||||||
|
BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(256);
|
||||||
|
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
|
.withInitializer((context) -> context.setApplicationStartup(applicationStartup))
|
||||||
|
.withUserConfiguration(EndpointConfiguration.class);
|
||||||
|
contextRunner.run((context) -> {
|
||||||
|
StartupEndpoint.StartupResponse startup = context.getBean(StartupEndpoint.class).startup();
|
||||||
|
assertThat(startup.getTimeline().getEvents()).isNotEmpty();
|
||||||
|
assertThat(applicationStartup.getBufferedTimeline().getEvents()).isEmpty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class EndpointConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
StartupEndpoint endpoint(BufferingApplicationStartup applicationStartup) {
|
||||||
|
return new StartupEndpoint(applicationStartup);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue