mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Improve context hierarchy handling in Actuator endpoints
Previously, a number of Actuator endpoints ignored a context hierarchy or assumed that it would always be linear. This commit reworks the affected endpoints so that the no longer assume a linear hierarchy. A side-effect of a non-linear hierarchy is that there may be multiple different beans with the same name (in a linear hierarchy, a bean with the same name as one in an ancestor context, replaces that bean). The affected endpoints have also been updated so that, when bean names are used as keys, those keys are grouped by application context. This prevents a bean in one context from accidentially overwriting a bean in another context. Closes gh-11019
This commit is contained in:
parent
81d6afe5ac
commit
5b8a2f9675
@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.actuate.autoconfigure.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -32,6 +33,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionEvaluationRepor
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport.ConditionAndOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport.ConditionAndOutcomes;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
@ -50,24 +53,58 @@ import org.springframework.util.StringUtils;
|
||||
@Endpoint(id = "conditions")
|
||||
public class ConditionsReportEndpoint {
|
||||
|
||||
private final ConditionEvaluationReport conditionEvaluationReport;
|
||||
private final ConfigurableApplicationContext context;
|
||||
|
||||
public ConditionsReportEndpoint(ConditionEvaluationReport conditionEvaluationReport) {
|
||||
this.conditionEvaluationReport = conditionEvaluationReport;
|
||||
public ConditionsReportEndpoint(ConfigurableApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public Report getEvaluationReport() {
|
||||
return new Report(this.conditionEvaluationReport);
|
||||
public ApplicationConditionEvaluation applicationConditionEvaluation() {
|
||||
Map<String, ContextConditionEvaluation> contextConditionEvaluations = new HashMap<>();
|
||||
ConfigurableApplicationContext target = this.context;
|
||||
while (target != null) {
|
||||
contextConditionEvaluations.put(target.getId(),
|
||||
new ContextConditionEvaluation(target));
|
||||
target = getConfigurableParent(target);
|
||||
}
|
||||
return new ApplicationConditionEvaluation(contextConditionEvaluations);
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext getConfigurableParent(
|
||||
ConfigurableApplicationContext context) {
|
||||
ApplicationContext parent = context.getParent();
|
||||
if (parent instanceof ConfigurableApplicationContext) {
|
||||
return (ConfigurableApplicationContext) parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts {@link ConditionEvaluationReport} to a JSON friendly structure.
|
||||
* A description of an application's condition evaluation, primarily intended for
|
||||
* serialization to JSON.
|
||||
*/
|
||||
public static final class ApplicationConditionEvaluation {
|
||||
|
||||
private final Map<String, ContextConditionEvaluation> contexts;
|
||||
|
||||
private ApplicationConditionEvaluation(
|
||||
Map<String, ContextConditionEvaluation> contexts) {
|
||||
this.contexts = contexts;
|
||||
}
|
||||
|
||||
public Map<String, ContextConditionEvaluation> getContexts() {
|
||||
return this.contexts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of an application context's condition evaluation, primarily intended
|
||||
* for serialization to JSON.
|
||||
*/
|
||||
@JsonPropertyOrder({ "positiveMatches", "negativeMatches", "exclusions",
|
||||
"unconditionalClasses" })
|
||||
@JsonInclude(Include.NON_EMPTY)
|
||||
public static class Report {
|
||||
public static final class ContextConditionEvaluation {
|
||||
|
||||
private final MultiValueMap<String, MessageAndCondition> positiveMatches;
|
||||
|
||||
@ -77,9 +114,11 @@ public class ConditionsReportEndpoint {
|
||||
|
||||
private final Set<String> unconditionalClasses;
|
||||
|
||||
private final Report parent;
|
||||
private final String parentId;
|
||||
|
||||
public Report(ConditionEvaluationReport report) {
|
||||
public ContextConditionEvaluation(ConfigurableApplicationContext context) {
|
||||
ConditionEvaluationReport report = ConditionEvaluationReport
|
||||
.get(context.getBeanFactory());
|
||||
this.positiveMatches = new LinkedMultiValueMap<>();
|
||||
this.negativeMatches = new LinkedHashMap<>();
|
||||
this.exclusions = report.getExclusions();
|
||||
@ -93,8 +132,8 @@ public class ConditionsReportEndpoint {
|
||||
add(this.negativeMatches, entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
boolean hasParent = report.getParent() != null;
|
||||
this.parent = (hasParent ? new Report(report.getParent()) : null);
|
||||
this.parentId = context.getParent() == null ? null
|
||||
: context.getParent().getId();
|
||||
}
|
||||
|
||||
private void add(Map<String, MessageAndConditions> map, String source,
|
||||
@ -127,8 +166,8 @@ public class ConditionsReportEndpoint {
|
||||
return this.unconditionalClasses;
|
||||
}
|
||||
|
||||
public Report getParent() {
|
||||
return this.parent;
|
||||
public String getParentId() {
|
||||
return this.parentId;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -18,7 +18,6 @@ package org.springframework.boot.actuate.autoconfigure.condition;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
@ -35,19 +34,12 @@ import org.springframework.context.annotation.Configuration;
|
||||
@Configuration
|
||||
public class ConditionsReportEndpointAutoConfiguration {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
public ConditionsReportEndpointAutoConfiguration(
|
||||
ConfigurableApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
|
||||
@ConditionalOnEnabledEndpoint
|
||||
public ConditionsReportEndpoint conditionsReportEndpoint() {
|
||||
return new ConditionsReportEndpoint(
|
||||
ConditionEvaluationReport.get(this.context.getBeanFactory()));
|
||||
public ConditionsReportEndpoint conditionsReportEndpoint(
|
||||
ConfigurableApplicationContext context) {
|
||||
return new ConditionsReportEndpoint(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.flyway;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.flywaydb.core.Flyway;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
|
||||
@ -28,6 +26,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@ -46,8 +45,8 @@ public class FlywayEndpointAutoConfiguration {
|
||||
@ConditionalOnBean(Flyway.class)
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnEnabledEndpoint
|
||||
public FlywayEndpoint flywayEndpoint(Map<String, Flyway> flywayBeans) {
|
||||
return new FlywayEndpoint(flywayBeans);
|
||||
public FlywayEndpoint flywayEndpoint(ApplicationContext context) {
|
||||
return new FlywayEndpoint(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.liquibase;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import liquibase.integration.spring.SpringLiquibase;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
|
||||
@ -28,6 +26,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@ -46,9 +45,8 @@ public class LiquibaseEndpointAutoConfiguration {
|
||||
@ConditionalOnBean(SpringLiquibase.class)
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnEnabledEndpoint
|
||||
public LiquibaseEndpoint liquibaseEndpoint(
|
||||
Map<String, SpringLiquibase> liquibaseBeans) {
|
||||
return new LiquibaseEndpoint(liquibaseBeans);
|
||||
public LiquibaseEndpoint liquibaseEndpoint(ApplicationContext context) {
|
||||
return new LiquibaseEndpoint(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -23,7 +23,7 @@ import javax.annotation.PostConstruct;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpoint.Report;
|
||||
import org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpoint.ContextConditionEvaluation;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
@ -49,8 +49,10 @@ public class ConditionsReportEndpointTests {
|
||||
public void invoke() {
|
||||
new ApplicationContextRunner().withUserConfiguration(Config.class)
|
||||
.run((context) -> {
|
||||
Report report = context.getBean(ConditionsReportEndpoint.class)
|
||||
.getEvaluationReport();
|
||||
ContextConditionEvaluation report = context
|
||||
.getBean(ConditionsReportEndpoint.class)
|
||||
.applicationConditionEvaluation().getContexts()
|
||||
.get(context.getId());
|
||||
assertThat(report.getPositiveMatches()).isEmpty();
|
||||
assertThat(report.getNegativeMatches()).containsKey("a");
|
||||
assertThat(report.getUnconditionalClasses()).contains("b");
|
||||
@ -79,9 +81,8 @@ public class ConditionsReportEndpointTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConditionsReportEndpoint endpoint(
|
||||
ConditionEvaluationReport report) {
|
||||
return new ConditionsReportEndpoint(report);
|
||||
public ConditionsReportEndpoint endpoint() {
|
||||
return new ConditionsReportEndpoint(this.context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -21,7 +21,7 @@ import java.util.Map;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesDescriptor;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ApplicationConfigurationProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
@ -73,10 +73,11 @@ public class ConfigurationPropertiesReportEndpointAutoConfigurationTests {
|
||||
.hasSingleBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties properties = endpoint
|
||||
.configurationProperties();
|
||||
Map<String, Object> nestedProperties = properties.getBeans()
|
||||
.get("testProperties").getProperties();
|
||||
Map<String, Object> nestedProperties = properties.getContexts()
|
||||
.get(context.getId()).getBeans().get("testProperties")
|
||||
.getProperties();
|
||||
assertThat(nestedProperties).isNotNull();
|
||||
assertThat(nestedProperties.get("dbPassword")).isEqualTo(dbPassword);
|
||||
assertThat(nestedProperties.get("myTestProperty")).isEqualTo(myTestProperty);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -46,12 +46,16 @@ import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
|
||||
import org.springframework.restdocs.operation.preprocess.ContentModifyingOperationPreprocessor;
|
||||
import org.springframework.restdocs.operation.preprocess.OperationPreprocessor;
|
||||
import org.springframework.restdocs.payload.FieldDescriptor;
|
||||
import org.springframework.restdocs.payload.JsonFieldType;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
|
||||
/**
|
||||
* Abstract base class for tests that generate endpoint documentation using Spring REST
|
||||
* Docs.
|
||||
@ -79,6 +83,10 @@ public abstract class AbstractEndpointDocumentationTests {
|
||||
.build();
|
||||
}
|
||||
|
||||
protected WebApplicationContext getApplicationContext() {
|
||||
return this.applicationContext;
|
||||
}
|
||||
|
||||
protected String describeEnumValues(Class<? extends Enum<?>> enumType) {
|
||||
return StringUtils
|
||||
.collectionToCommaDelimitedString(Stream.of(enumType.getEnumConstants())
|
||||
@ -86,23 +94,35 @@ public abstract class AbstractEndpointDocumentationTests {
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
protected OperationPreprocessor limit(String key) {
|
||||
return limit(key, (candidate) -> true);
|
||||
protected OperationPreprocessor limit(String... keys) {
|
||||
return limit((candidate) -> true, keys);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> OperationPreprocessor limit(String key, Predicate<T> filter) {
|
||||
protected <T> OperationPreprocessor limit(Predicate<T> filter, String... keys) {
|
||||
return new ContentModifyingOperationPreprocessor((content, mediaType) -> {
|
||||
ObjectMapper objectMapper = new ObjectMapper()
|
||||
.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
try {
|
||||
Map<String, Object> payload = objectMapper.readValue(content, Map.class);
|
||||
Object entry = payload.get(key);
|
||||
if (entry instanceof Map) {
|
||||
payload.put(key, select((Map<String, Object>) entry, filter));
|
||||
Object target = payload;
|
||||
Map<Object, Object> parent = null;
|
||||
for (String key : keys) {
|
||||
if (target instanceof Map) {
|
||||
parent = (Map<Object, Object>) target;
|
||||
target = parent.get(key);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
if (target instanceof Map) {
|
||||
parent.put(keys[keys.length - 1],
|
||||
select((Map<String, Object>) target, filter));
|
||||
}
|
||||
else {
|
||||
payload.put(key, select((List<Object>) entry, filter));
|
||||
parent.put(keys[keys.length - 1],
|
||||
select((List<Object>) target, filter));
|
||||
}
|
||||
return objectMapper.writeValueAsBytes(payload);
|
||||
}
|
||||
@ -112,6 +132,12 @@ public abstract class AbstractEndpointDocumentationTests {
|
||||
});
|
||||
}
|
||||
|
||||
protected FieldDescriptor parentIdField() {
|
||||
return fieldWithPath("contexts.*.parentId")
|
||||
.description("Id of the parent application context, if any.").optional()
|
||||
.type(JsonFieldType.STRING);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Map<String, Object> select(Map<String, Object> candidates,
|
||||
Predicate<T> filter) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -30,7 +30,6 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.restdocs.payload.FieldDescriptor;
|
||||
import org.springframework.restdocs.payload.JsonFieldType;
|
||||
import org.springframework.restdocs.payload.ResponseFieldsSnippet;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@ -38,7 +37,6 @@ import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.docu
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@ -61,17 +59,16 @@ public class BeansEndpointDocumentationTests extends AbstractEndpointDocumentati
|
||||
.optional(),
|
||||
fieldWithPath("dependencies").description("Names of any dependencies."));
|
||||
ResponseFieldsSnippet responseFields = responseFields(
|
||||
fieldWithPath("contextId").description("ID of the application context."),
|
||||
fieldWithPath("beans.*")
|
||||
fieldWithPath("contexts")
|
||||
.description("Application contexts keyed by id."),
|
||||
parentIdField(),
|
||||
fieldWithPath("contexts.*.beans")
|
||||
.description("Beans in the application context keyed by name."))
|
||||
.andWithPrefix("beans.*.", beanFields)
|
||||
.and(subsectionWithPath("parent")
|
||||
.description("Beans in the parent application "
|
||||
+ "context, if any.")
|
||||
.type(JsonFieldType.OBJECT).optional());
|
||||
.andWithPrefix("contexts.*.beans.*.", beanFields);
|
||||
this.mockMvc.perform(get("/actuator/beans")).andExpect(status().isOk())
|
||||
.andDo(document("beans",
|
||||
preprocessResponse(limit("beans", this::isIndependentBean)),
|
||||
preprocessResponse(limit(this::isIndependentBean, "contexts",
|
||||
getApplicationContext().getId(), "beans")),
|
||||
responseFields));
|
||||
}
|
||||
|
||||
|
@ -17,21 +17,23 @@
|
||||
package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpoint;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
|
||||
import org.springframework.restdocs.payload.FieldDescriptor;
|
||||
import org.springframework.restdocs.payload.JsonFieldType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
@ -70,37 +72,46 @@ public class ConditionsReportEndpointDocumentationTests
|
||||
|
||||
@Test
|
||||
public void conditions() throws Exception {
|
||||
List<FieldDescriptor> positiveMatchFields = Arrays.asList(
|
||||
fieldWithPath("").description(
|
||||
"Classes and methods with conditions that were " + "matched."),
|
||||
fieldWithPath(".*.[].condition").description("Name of the condition."),
|
||||
fieldWithPath(".*.[].message")
|
||||
.description("Details of why the condition was matched."));
|
||||
List<FieldDescriptor> negativeMatchFields = Arrays.asList(
|
||||
fieldWithPath("").description("Classes and methods with conditions that "
|
||||
+ "were not matched."),
|
||||
fieldWithPath(".*.notMatched")
|
||||
.description("Conditions that were matched."),
|
||||
fieldWithPath(".*.notMatched.[].condition")
|
||||
.description("Name of the condition."),
|
||||
fieldWithPath(".*.notMatched.[].message").description(
|
||||
"Details of why the condition was" + " not matched."),
|
||||
fieldWithPath(".*.matched").description("Conditions that were matched."),
|
||||
fieldWithPath(".*.matched.[].condition")
|
||||
.description("Name of the condition.").type(JsonFieldType.STRING)
|
||||
.optional(),
|
||||
fieldWithPath(".*.matched.[].message")
|
||||
.description("Details of why the condition was matched.")
|
||||
.type(JsonFieldType.STRING).optional());
|
||||
FieldDescriptor unconditionalClassesField = fieldWithPath(
|
||||
"contexts.*.unconditionalClasses").description(
|
||||
"Names of unconditional auto-configuration classes if any.");
|
||||
this.mockMvc.perform(get("/actuator/conditions")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("conditions",
|
||||
preprocessResponse(limit("positiveMatches"),
|
||||
limit("negativeMatches")),
|
||||
responseFields(
|
||||
fieldWithPath("positiveMatches").description(
|
||||
"Classes and methods with conditions that were matched."),
|
||||
fieldWithPath("positiveMatches.*.[].condition")
|
||||
.description("Name of the condition."),
|
||||
fieldWithPath("positiveMatches.*.[].message").description(
|
||||
"Details of why the condition was matched."),
|
||||
fieldWithPath("negativeMatches").description(
|
||||
"Classes and methods with conditions that were not matched."),
|
||||
fieldWithPath("negativeMatches.*.notMatched")
|
||||
.description("Conditions that were matched."),
|
||||
fieldWithPath("negativeMatches.*.notMatched.[].condition")
|
||||
.description("Name of the condition."),
|
||||
fieldWithPath("negativeMatches.*.notMatched.[].message")
|
||||
.description(
|
||||
"Details of why the condition was not matched."),
|
||||
fieldWithPath("negativeMatches.*.matched")
|
||||
.description("Conditions that were matched."),
|
||||
fieldWithPath("negativeMatches.*.matched.[].condition")
|
||||
.description("Name of the condition.")
|
||||
.type(JsonFieldType.STRING).optional(),
|
||||
fieldWithPath("negativeMatches.*.matched.[].message")
|
||||
.description(
|
||||
"Details of why the condition was matched.")
|
||||
.type(JsonFieldType.STRING).optional(),
|
||||
fieldWithPath("unconditionalClasses").description(
|
||||
"Names of unconditional auto-configuration classes, if any."))));
|
||||
preprocessResponse(
|
||||
limit("contexts", getApplicationContext().getId(),
|
||||
"positiveMatches"),
|
||||
limit("contexts", getApplicationContext().getId(),
|
||||
"negativeMatches")),
|
||||
responseFields(fieldWithPath("contexts")
|
||||
.description("Application contexts keyed by id."))
|
||||
.andWithPrefix("contexts.*.positiveMatches",
|
||||
positiveMatchFields)
|
||||
.andWithPrefix("contexts.*.negativeMatches",
|
||||
negativeMatchFields)
|
||||
.and(unconditionalClassesField,
|
||||
parentIdField())));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ -109,12 +120,12 @@ public class ConditionsReportEndpointDocumentationTests
|
||||
|
||||
@Bean
|
||||
public ConditionsReportEndpoint autoConfigurationReportEndpoint(
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
ConfigurableApplicationContext context) {
|
||||
ConditionEvaluationReport conditionEvaluationReport = ConditionEvaluationReport
|
||||
.get(beanFactory);
|
||||
.get(context.getBeanFactory());
|
||||
conditionEvaluationReport.recordEvaluationCandidates(
|
||||
Arrays.asList(PropertyPlaceholderAutoConfiguration.class.getName()));
|
||||
return new ConditionsReportEndpoint(conditionEvaluationReport);
|
||||
return new ConditionsReportEndpoint(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -23,7 +23,6 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
|
||||
import org.springframework.restdocs.payload.JsonFieldType;
|
||||
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
@ -45,21 +44,19 @@ public class ConfigurationPropertiesReportEndpointDocumentationTests
|
||||
public void configProps() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/configprops")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("configprops",
|
||||
preprocessResponse(limit("beans")),
|
||||
preprocessResponse(limit("contexts",
|
||||
getApplicationContext().getId(), "beans")),
|
||||
responseFields(
|
||||
fieldWithPath("contextId")
|
||||
.description("ID of the application context."),
|
||||
fieldWithPath("beans.*").description(
|
||||
fieldWithPath("contexts")
|
||||
.description("Application contexts keyed by id."),
|
||||
fieldWithPath("contexts.*.beans.*").description(
|
||||
"`@ConfigurationProperties` beans keyed by bean name."),
|
||||
fieldWithPath("beans.*.prefix").description(
|
||||
fieldWithPath("contexts.*.beans.*.prefix").description(
|
||||
"Prefix applied to the names of the bean's properties."),
|
||||
subsectionWithPath("beans.*.properties").description(
|
||||
"Properties of the bean as name-value pairs."),
|
||||
subsectionWithPath("parent")
|
||||
subsectionWithPath("contexts.*.beans.*.properties")
|
||||
.description(
|
||||
"`@ConfigurationProperties` beans in the parent "
|
||||
+ "context, if any.")
|
||||
.optional().type(JsonFieldType.OBJECT))));
|
||||
"Properties of the bean as name-value pairs."),
|
||||
parentIdField())));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -18,9 +18,7 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentatio
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.flywaydb.core.api.MigrationState;
|
||||
import org.flywaydb.core.api.MigrationType;
|
||||
import org.junit.Test;
|
||||
@ -29,6 +27,7 @@ import org.springframework.boot.actuate.flyway.FlywayEndpoint;
|
||||
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@ -52,11 +51,16 @@ public class FlywayEndpointDocumentationTests extends AbstractEndpointDocumentat
|
||||
public void flyway() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/flyway")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("flyway",
|
||||
responseFields(fieldWithPath("*.migrations").description(
|
||||
responseFields(
|
||||
fieldWithPath("contexts")
|
||||
.description("Application contexts keyed by id"),
|
||||
fieldWithPath("contexts.*.flywayBeans.*.migrations").description(
|
||||
"Migrations performed by the Flyway instance, keyed by"
|
||||
+ " bean name.")).andWithPrefix(
|
||||
"*.migrations.[].",
|
||||
migrationFieldDescriptors())));
|
||||
+ " Flyway bean name."))
|
||||
.andWithPrefix(
|
||||
"contexts.*.flywayBeans.*.migrations.[].",
|
||||
migrationFieldDescriptors())
|
||||
.and(parentIdField())));
|
||||
}
|
||||
|
||||
private List<FieldDescriptor> migrationFieldDescriptors() {
|
||||
@ -100,8 +104,8 @@ public class FlywayEndpointDocumentationTests extends AbstractEndpointDocumentat
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public FlywayEndpoint endpoint(Map<String, Flyway> flyways) {
|
||||
return new FlywayEndpoint(flyways);
|
||||
public FlywayEndpoint endpoint(ApplicationContext context) {
|
||||
return new FlywayEndpoint(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -18,15 +18,14 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentatio
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import liquibase.changelog.ChangeSet.ExecType;
|
||||
import liquibase.integration.spring.SpringLiquibase;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.liquibase.LiquibaseEndpoint;
|
||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@ -48,12 +47,20 @@ public class LiquibaseEndpointDocumentationTests
|
||||
|
||||
@Test
|
||||
public void liquibase() throws Exception {
|
||||
FieldDescriptor changeSetsField = fieldWithPath(
|
||||
"contexts.*.liquibaseBeans.*.changeSets")
|
||||
.description("Change sets made by the Liquibase beans, keyed by "
|
||||
+ "bean name.");
|
||||
this.mockMvc.perform(get("/actuator/liquibase")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("liquibase",
|
||||
responseFields(fieldWithPath("*.changeSets").description(
|
||||
"Change sets made by the Liquibase beans, keyed by "
|
||||
+ "bean name.")).andWithPrefix("*.changeSets[].",
|
||||
getChangeSetFieldDescriptors())));
|
||||
responseFields(
|
||||
fieldWithPath("contexts")
|
||||
.description("Application contexts keyed by id"),
|
||||
changeSetsField)
|
||||
.andWithPrefix(
|
||||
"contexts.*.liquibaseBeans.*.changeSets[].",
|
||||
getChangeSetFieldDescriptors())
|
||||
.and(parentIdField())));
|
||||
}
|
||||
|
||||
private List<FieldDescriptor> getChangeSetFieldDescriptors() {
|
||||
@ -86,8 +93,8 @@ public class LiquibaseEndpointDocumentationTests
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public LiquibaseEndpoint endpoint(Map<String, SpringLiquibase> liquibases) {
|
||||
return new LiquibaseEndpoint(liquibases);
|
||||
public LiquibaseEndpoint endpoint(ApplicationContext context) {
|
||||
return new LiquibaseEndpoint(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -53,49 +53,73 @@ public class BeansEndpoint {
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public ApplicationContextDescriptor beans() {
|
||||
return ApplicationContextDescriptor.describing(this.context);
|
||||
public ApplicationBeans beans() {
|
||||
Map<String, ContextBeans> contexts = new HashMap<>();
|
||||
ConfigurableApplicationContext context = this.context;
|
||||
while (context != null) {
|
||||
contexts.put(context.getId(), ContextBeans.describing(context));
|
||||
context = getConfigurableParent(context);
|
||||
}
|
||||
return new ApplicationBeans(contexts);
|
||||
}
|
||||
|
||||
private static ConfigurableApplicationContext getConfigurableParent(
|
||||
ConfigurableApplicationContext context) {
|
||||
ApplicationContext parent = context.getParent();
|
||||
if (parent instanceof ConfigurableApplicationContext) {
|
||||
return (ConfigurableApplicationContext) parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of an application's beans, primarily intended for serialization to
|
||||
* JSON.
|
||||
*/
|
||||
public static final class ApplicationBeans {
|
||||
|
||||
private final Map<String, ContextBeans> contexts;
|
||||
|
||||
private ApplicationBeans(Map<String, ContextBeans> contexts) {
|
||||
this.contexts = contexts;
|
||||
}
|
||||
|
||||
public Map<String, ContextBeans> getContexts() {
|
||||
return this.contexts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of an application context, primarily intended for serialization to
|
||||
* JSON.
|
||||
*/
|
||||
public static final class ApplicationContextDescriptor {
|
||||
|
||||
private final String contextId;
|
||||
public static final class ContextBeans {
|
||||
|
||||
private final Map<String, BeanDescriptor> beans;
|
||||
|
||||
private final ApplicationContextDescriptor parent;
|
||||
private final String parentId;
|
||||
|
||||
private ApplicationContextDescriptor(String contextId,
|
||||
Map<String, BeanDescriptor> beans, ApplicationContextDescriptor parent) {
|
||||
this.contextId = contextId;
|
||||
private ContextBeans(Map<String, BeanDescriptor> beans, String parentId) {
|
||||
this.beans = beans;
|
||||
this.parent = parent;
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public String getContextId() {
|
||||
return this.contextId;
|
||||
}
|
||||
|
||||
public ApplicationContextDescriptor getParent() {
|
||||
return this.parent;
|
||||
public String getParentId() {
|
||||
return this.parentId;
|
||||
}
|
||||
|
||||
public Map<String, BeanDescriptor> getBeans() {
|
||||
return this.beans;
|
||||
}
|
||||
|
||||
private static ApplicationContextDescriptor describing(
|
||||
ConfigurableApplicationContext context) {
|
||||
private static ContextBeans describing(ConfigurableApplicationContext context) {
|
||||
if (context == null) {
|
||||
return null;
|
||||
}
|
||||
return new ApplicationContextDescriptor(context.getId(),
|
||||
describeBeans(context.getBeanFactory()),
|
||||
describing(getConfigurableParent(context)));
|
||||
ConfigurableApplicationContext parent = getConfigurableParent(context);
|
||||
return new ContextBeans(describeBeans(context.getBeanFactory()),
|
||||
parent == null ? null : parent.getId());
|
||||
}
|
||||
|
||||
private static Map<String, BeanDescriptor> describeBeans(
|
||||
@ -123,15 +147,6 @@ public class BeansEndpoint {
|
||||
&& (!bd.isLazyInit() || bf.containsSingleton(beanName)));
|
||||
}
|
||||
|
||||
private static ConfigurableApplicationContext getConfigurableParent(
|
||||
ConfigurableApplicationContext context) {
|
||||
ApplicationContext parent = context.getParent();
|
||||
if (parent instanceof ConfigurableApplicationContext) {
|
||||
return (ConfigurableApplicationContext) parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -88,21 +88,25 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public ConfigurationPropertiesDescriptor configurationProperties() {
|
||||
public ApplicationConfigurationProperties configurationProperties() {
|
||||
return extract(this.context);
|
||||
}
|
||||
|
||||
private ConfigurationPropertiesDescriptor extract(ApplicationContext context) {
|
||||
private ApplicationConfigurationProperties extract(ApplicationContext context) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
configureObjectMapper(mapper);
|
||||
return describeConfigurationProperties(context, mapper);
|
||||
Map<String, ContextConfigurationProperties> contextProperties = new HashMap<>();
|
||||
ApplicationContext target = context;
|
||||
while (target != null) {
|
||||
contextProperties.put(target.getId(),
|
||||
describeConfigurationProperties(target, mapper));
|
||||
target = target.getParent();
|
||||
}
|
||||
return new ApplicationConfigurationProperties(contextProperties);
|
||||
}
|
||||
|
||||
private ConfigurationPropertiesDescriptor describeConfigurationProperties(
|
||||
private ContextConfigurationProperties describeConfigurationProperties(
|
||||
ApplicationContext context, ObjectMapper mapper) {
|
||||
if (context == null) {
|
||||
return null;
|
||||
}
|
||||
ConfigurationBeanFactoryMetaData beanFactoryMetaData = getBeanFactoryMetaData(
|
||||
context);
|
||||
Map<String, Object> beans = getConfigurationPropertiesBeans(context,
|
||||
@ -115,8 +119,8 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
beanDescriptors.put(beanName, new ConfigurationPropertiesBeanDescriptor(
|
||||
prefix, sanitize(prefix, safeSerialize(mapper, bean, prefix))));
|
||||
}
|
||||
return new ConfigurationPropertiesDescriptor(context.getId(), beanDescriptors,
|
||||
describeConfigurationProperties(context.getParent(), mapper));
|
||||
return new ContextConfigurationProperties(beanDescriptors,
|
||||
context.getParent() == null ? null : context.getParent().getId());
|
||||
}
|
||||
|
||||
private ConfigurationBeanFactoryMetaData getBeanFactoryMetaData(
|
||||
@ -389,36 +393,48 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of an application's {@link ConfigurationProperties} beans. Primarily
|
||||
* intended for serialization to JSON.
|
||||
*/
|
||||
public static final class ApplicationConfigurationProperties {
|
||||
|
||||
private final Map<String, ContextConfigurationProperties> contexts;
|
||||
|
||||
private ApplicationConfigurationProperties(
|
||||
Map<String, ContextConfigurationProperties> contexts) {
|
||||
this.contexts = contexts;
|
||||
}
|
||||
|
||||
public Map<String, ContextConfigurationProperties> getContexts() {
|
||||
return this.contexts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of an application context's {@link ConfigurationProperties} beans.
|
||||
* Primarily intended for serialization to JSON.
|
||||
*/
|
||||
public static final class ConfigurationPropertiesDescriptor {
|
||||
|
||||
private final String contextId;
|
||||
public static final class ContextConfigurationProperties {
|
||||
|
||||
private final Map<String, ConfigurationPropertiesBeanDescriptor> beans;
|
||||
|
||||
private final ConfigurationPropertiesDescriptor parent;
|
||||
private final String parentId;
|
||||
|
||||
private ConfigurationPropertiesDescriptor(String contextId,
|
||||
private ContextConfigurationProperties(
|
||||
Map<String, ConfigurationPropertiesBeanDescriptor> beans,
|
||||
ConfigurationPropertiesDescriptor parent) {
|
||||
this.contextId = contextId;
|
||||
String parentId) {
|
||||
this.beans = beans;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public String getContextId() {
|
||||
return this.contextId;
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public Map<String, ConfigurationPropertiesBeanDescriptor> getBeans() {
|
||||
return this.beans;
|
||||
}
|
||||
|
||||
public ConfigurationPropertiesDescriptor getParent() {
|
||||
return this.parent;
|
||||
public String getParentId() {
|
||||
return this.parentId;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ import org.flywaydb.core.api.MigrationType;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* {@link Endpoint} to expose flyway info.
|
||||
@ -43,34 +43,85 @@ import org.springframework.util.Assert;
|
||||
@Endpoint(id = "flyway")
|
||||
public class FlywayEndpoint {
|
||||
|
||||
private final Map<String, Flyway> flywayBeans;
|
||||
private final ApplicationContext context;
|
||||
|
||||
public FlywayEndpoint(Map<String, Flyway> flywayBeans) {
|
||||
Assert.notEmpty(flywayBeans, "FlywayBeans must be specified");
|
||||
this.flywayBeans = flywayBeans;
|
||||
public FlywayEndpoint(ApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public Map<String, FlywayReport> flywayReports() {
|
||||
Map<String, FlywayReport> reports = new HashMap<>();
|
||||
this.flywayBeans.forEach((name, flyway) -> reports.put(name,
|
||||
new FlywayReport(flyway.info().all())));
|
||||
return reports;
|
||||
public ApplicationFlywayBeans flywayBeans() {
|
||||
ApplicationContext target = this.context;
|
||||
Map<String, ContextFlywayBeans> contextFlywayBeans = new HashMap<>();
|
||||
while (target != null) {
|
||||
Map<String, FlywayDescriptor> flywayBeans = new HashMap<>();
|
||||
target.getBeansOfType(Flyway.class).forEach((name, flyway) -> flywayBeans
|
||||
.put(name, new FlywayDescriptor(flyway.info().all())));
|
||||
ApplicationContext parent = target.getParent();
|
||||
contextFlywayBeans.put(target.getId(), new ContextFlywayBeans(flywayBeans,
|
||||
parent == null ? null : parent.getId()));
|
||||
target = parent;
|
||||
}
|
||||
return new ApplicationFlywayBeans(contextFlywayBeans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report for one {@link Flyway} instance.
|
||||
* Description of an application's {@link Flyway} beans, primarily intended for
|
||||
* serialization to JSON.
|
||||
*/
|
||||
public static class FlywayReport {
|
||||
public static final class ApplicationFlywayBeans {
|
||||
|
||||
private final Map<String, ContextFlywayBeans> contexts;
|
||||
|
||||
private ApplicationFlywayBeans(Map<String, ContextFlywayBeans> contexts) {
|
||||
this.contexts = contexts;
|
||||
}
|
||||
|
||||
public Map<String, ContextFlywayBeans> getContexts() {
|
||||
return this.contexts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of an application context's {@link Flyway} beans, primarily intended
|
||||
* for serialization to JSON.
|
||||
*/
|
||||
public static final class ContextFlywayBeans {
|
||||
|
||||
private final Map<String, FlywayDescriptor> flywayBeans;
|
||||
|
||||
private final String parentId;
|
||||
|
||||
private ContextFlywayBeans(Map<String, FlywayDescriptor> flywayBeans,
|
||||
String parentId) {
|
||||
this.flywayBeans = flywayBeans;
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public Map<String, FlywayDescriptor> getFlywayBeans() {
|
||||
return this.flywayBeans;
|
||||
}
|
||||
|
||||
public String getParentId() {
|
||||
return this.parentId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of a {@link Flyway} bean, primarly intended for serialization to JSON.
|
||||
*/
|
||||
public static class FlywayDescriptor {
|
||||
|
||||
private final List<FlywayMigration> migrations;
|
||||
|
||||
public FlywayReport(MigrationInfo[] migrations) {
|
||||
private FlywayDescriptor(MigrationInfo[] migrations) {
|
||||
this.migrations = Stream.of(migrations).map(FlywayMigration::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public FlywayReport(List<FlywayMigration> migrations) {
|
||||
public FlywayDescriptor(List<FlywayMigration> migrations) {
|
||||
this.migrations = migrations;
|
||||
}
|
||||
|
||||
@ -83,7 +134,7 @@ public class FlywayEndpoint {
|
||||
/**
|
||||
* Details of a migration performed by Flyway.
|
||||
*/
|
||||
public static class FlywayMigration {
|
||||
public static final class FlywayMigration {
|
||||
|
||||
private final MigrationType type;
|
||||
|
||||
@ -105,7 +156,7 @@ public class FlywayEndpoint {
|
||||
|
||||
private final Integer executionTime;
|
||||
|
||||
public FlywayMigration(MigrationInfo info) {
|
||||
private FlywayMigration(MigrationInfo info) {
|
||||
this.type = info.getType();
|
||||
this.checksum = info.getChecksum();
|
||||
this.version = nullSafeToString(info.getVersion());
|
||||
|
@ -36,6 +36,7 @@ import liquibase.integration.spring.SpringLiquibase;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@ -48,24 +49,33 @@ import org.springframework.util.StringUtils;
|
||||
@Endpoint(id = "liquibase")
|
||||
public class LiquibaseEndpoint {
|
||||
|
||||
private final Map<String, SpringLiquibase> liquibaseBeans;
|
||||
private final ApplicationContext context;
|
||||
|
||||
public LiquibaseEndpoint(Map<String, SpringLiquibase> liquibaseBeans) {
|
||||
Assert.notEmpty(liquibaseBeans, "LiquibaseBeans must be specified");
|
||||
this.liquibaseBeans = liquibaseBeans;
|
||||
public LiquibaseEndpoint(ApplicationContext context) {
|
||||
Assert.notNull(context, "Context must be specified");
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public Map<String, LiquibaseReport> liquibaseReports() {
|
||||
Map<String, LiquibaseReport> reports = new HashMap<>();
|
||||
DatabaseFactory factory = DatabaseFactory.getInstance();
|
||||
StandardChangeLogHistoryService service = new StandardChangeLogHistoryService();
|
||||
this.liquibaseBeans.forEach((name, liquibase) -> reports.put(name,
|
||||
createReport(liquibase, service, factory)));
|
||||
return reports;
|
||||
public ApplicationLiquibaseBeans liquibaseBeans() {
|
||||
ApplicationContext target = this.context;
|
||||
Map<String, ContextLiquibaseBeans> contextBeans = new HashMap<>();
|
||||
while (target != null) {
|
||||
Map<String, LiquibaseBean> liquibaseBeans = new HashMap<>();
|
||||
DatabaseFactory factory = DatabaseFactory.getInstance();
|
||||
StandardChangeLogHistoryService service = new StandardChangeLogHistoryService();
|
||||
this.context.getBeansOfType(SpringLiquibase.class)
|
||||
.forEach((name, liquibase) -> liquibaseBeans.put(name,
|
||||
createReport(liquibase, service, factory)));
|
||||
ApplicationContext parent = target.getParent();
|
||||
contextBeans.put(target.getId(), new ContextLiquibaseBeans(liquibaseBeans,
|
||||
parent == null ? null : parent.getId()));
|
||||
target = parent;
|
||||
}
|
||||
return new ApplicationLiquibaseBeans(contextBeans);
|
||||
}
|
||||
|
||||
private LiquibaseReport createReport(SpringLiquibase liquibase,
|
||||
private LiquibaseBean createReport(SpringLiquibase liquibase,
|
||||
ChangeLogHistoryService service, DatabaseFactory factory) {
|
||||
try {
|
||||
DataSource dataSource = liquibase.getDataSource();
|
||||
@ -77,7 +87,7 @@ public class LiquibaseEndpoint {
|
||||
database.setDefaultSchemaName(defaultSchema);
|
||||
}
|
||||
service.setDatabase(database);
|
||||
return new LiquibaseReport(service.getRanChangeSets().stream()
|
||||
return new LiquibaseBean(service.getRanChangeSets().stream()
|
||||
.map(ChangeSet::new).collect(Collectors.toList()));
|
||||
}
|
||||
finally {
|
||||
@ -90,13 +100,58 @@ public class LiquibaseEndpoint {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report for a single {@link SpringLiquibase} instance.
|
||||
* Description of an application's {@link SpringLiquibase} beans, primarily intended
|
||||
* for serialization to JSON.
|
||||
*/
|
||||
public static class LiquibaseReport {
|
||||
public static final class ApplicationLiquibaseBeans {
|
||||
|
||||
private final Map<String, ContextLiquibaseBeans> contexts;
|
||||
|
||||
private ApplicationLiquibaseBeans(Map<String, ContextLiquibaseBeans> contexts) {
|
||||
this.contexts = contexts;
|
||||
}
|
||||
|
||||
public Map<String, ContextLiquibaseBeans> getContexts() {
|
||||
return this.contexts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of an application context's {@link SpringLiquibase} beans, primarily
|
||||
* intended for serialization to JSON.
|
||||
*/
|
||||
public static final class ContextLiquibaseBeans {
|
||||
|
||||
private final Map<String, LiquibaseBean> liquibaseBeans;
|
||||
|
||||
private final String parentId;
|
||||
|
||||
private ContextLiquibaseBeans(Map<String, LiquibaseBean> liquibaseBeans,
|
||||
String parentId) {
|
||||
this.liquibaseBeans = liquibaseBeans;
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public Map<String, LiquibaseBean> getLiquibaseBeans() {
|
||||
return this.liquibaseBeans;
|
||||
}
|
||||
|
||||
public String getParentId() {
|
||||
return this.parentId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of a {@link SpringLiquibase} bean, primarly intended for serialization
|
||||
* to JSON.
|
||||
*/
|
||||
public static final class LiquibaseBean {
|
||||
|
||||
private final List<ChangeSet> changeSets;
|
||||
|
||||
public LiquibaseReport(List<ChangeSet> changeSets) {
|
||||
public LiquibaseBean(List<ChangeSet> changeSets) {
|
||||
this.changeSets = changeSets;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -25,8 +25,9 @@ import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.actuate.beans.BeansEndpoint.ApplicationContextDescriptor;
|
||||
import org.springframework.boot.actuate.beans.BeansEndpoint.ApplicationBeans;
|
||||
import org.springframework.boot.actuate.beans.BeansEndpoint.BeanDescriptor;
|
||||
import org.springframework.boot.actuate.beans.BeansEndpoint.ContextBeans;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -48,11 +49,10 @@ public class BeansEndpointTests {
|
||||
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(EndpointConfiguration.class);
|
||||
contextRunner.run((context) -> {
|
||||
ApplicationContextDescriptor result = context.getBean(BeansEndpoint.class)
|
||||
.beans();
|
||||
assertThat(result.getParent()).isNull();
|
||||
assertThat(result.getContextId()).isEqualTo(context.getId());
|
||||
Map<String, BeanDescriptor> beans = result.getBeans();
|
||||
ApplicationBeans result = context.getBean(BeansEndpoint.class).beans();
|
||||
ContextBeans descriptor = result.getContexts().get(context.getId());
|
||||
assertThat(descriptor.getParentId()).isNull();
|
||||
Map<String, BeanDescriptor> beans = descriptor.getBeans();
|
||||
assertThat(beans.size())
|
||||
.isLessThanOrEqualTo(context.getBeanDefinitionCount());
|
||||
assertThat(beans).containsKey("endpoint");
|
||||
@ -70,9 +70,9 @@ public class BeansEndpointTests {
|
||||
.filter((name) -> BeanDefinition.ROLE_INFRASTRUCTURE == factory
|
||||
.getBeanDefinition(name).getRole())
|
||||
.collect(Collectors.toList());
|
||||
ApplicationContextDescriptor result = context.getBean(BeansEndpoint.class)
|
||||
.beans();
|
||||
Map<String, BeanDescriptor> beans = result.getBeans();
|
||||
ApplicationBeans result = context.getBean(BeansEndpoint.class).beans();
|
||||
ContextBeans contextDescriptor = result.getContexts().get(context.getId());
|
||||
Map<String, BeanDescriptor> beans = contextDescriptor.getBeans();
|
||||
for (String infrastructureBean : infrastructureBeans) {
|
||||
assertThat(beans).doesNotContainKey(infrastructureBean);
|
||||
}
|
||||
@ -85,10 +85,10 @@ public class BeansEndpointTests {
|
||||
.withUserConfiguration(EndpointConfiguration.class,
|
||||
LazyBeanConfiguration.class);
|
||||
contextRunner.run((context) -> {
|
||||
ApplicationContextDescriptor result = context.getBean(BeansEndpoint.class)
|
||||
.beans();
|
||||
ApplicationBeans result = context.getBean(BeansEndpoint.class).beans();
|
||||
ContextBeans contextDescriptor = result.getContexts().get(context.getId());
|
||||
assertThat(context).hasBean("lazyBean");
|
||||
assertThat(result.getBeans()).doesNotContainKey("lazyBean");
|
||||
assertThat(contextDescriptor.getBeans()).doesNotContainKey("lazyBean");
|
||||
});
|
||||
}
|
||||
|
||||
@ -100,10 +100,11 @@ public class BeansEndpointTests {
|
||||
new ApplicationContextRunner()
|
||||
.withUserConfiguration(EndpointConfiguration.class).withParent(parent)
|
||||
.run(child -> {
|
||||
BeansEndpoint endpoint = child.getBean(BeansEndpoint.class);
|
||||
ApplicationContextDescriptor result = endpoint.beans();
|
||||
assertThat(result.getParent().getBeans()).containsKey("bean");
|
||||
assertThat(result.getBeans()).containsKey("endpoint");
|
||||
ApplicationBeans result = child.getBean(BeansEndpoint.class).beans();
|
||||
assertThat(result.getContexts().get(parent.getId()).getBeans())
|
||||
.containsKey("bean");
|
||||
assertThat(result.getContexts().get(child.getId()).getBeans())
|
||||
.containsKey("endpoint");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -18,8 +18,9 @@ package org.springframework.boot.actuate.context.properties;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ApplicationConfigurationProperties;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesBeanDescriptor;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesDescriptor;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ContextConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
@ -44,9 +45,13 @@ public class ConfigurationPropertiesReportEndpointMethodAnnotationsTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
ConfigurationPropertiesBeanDescriptor other = properties.getBeans()
|
||||
assertThat(applicationProperties.getContexts())
|
||||
.containsOnlyKeys(context.getId());
|
||||
ContextConfigurationProperties contextProperties = applicationProperties
|
||||
.getContexts().get(context.getId());
|
||||
ConfigurationPropertiesBeanDescriptor other = contextProperties.getBeans()
|
||||
.get("other");
|
||||
assertThat(other).isNotNull();
|
||||
assertThat(other.getPrefix()).isEqualTo("other");
|
||||
@ -63,9 +68,14 @@ public class ConfigurationPropertiesReportEndpointMethodAnnotationsTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
ConfigurationPropertiesBeanDescriptor bar = properties.getBeans().get("bar");
|
||||
assertThat(applicationProperties.getContexts())
|
||||
.containsOnlyKeys(context.getId());
|
||||
ContextConfigurationProperties contextProperties = applicationProperties
|
||||
.getContexts().get(context.getId());
|
||||
ConfigurationPropertiesBeanDescriptor bar = contextProperties.getBeans()
|
||||
.get("bar");
|
||||
assertThat(bar).isNotNull();
|
||||
assertThat(bar.getPrefix()).isEqualTo("other");
|
||||
assertThat(bar.getProperties()).isNotNull();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -18,7 +18,7 @@ package org.springframework.boot.actuate.context.properties;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesDescriptor;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ApplicationConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
@ -45,12 +45,15 @@ public class ConfigurationPropertiesReportEndpointParentTests {
|
||||
.withParent(parent).run(child -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = child
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor result = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
assertThat(result.getBeans().keySet())
|
||||
.containsExactlyInAnyOrder("someProperties");
|
||||
assertThat((result.getParent().getBeans().keySet()))
|
||||
.containsExactly("testProperties");
|
||||
assertThat(applicationProperties.getContexts())
|
||||
.containsOnlyKeys(child.getId(), parent.getId());
|
||||
assertThat(applicationProperties.getContexts().get(child.getId())
|
||||
.getBeans().keySet()).containsExactly("someProperties");
|
||||
assertThat((applicationProperties.getContexts()
|
||||
.get(parent.getId()).getBeans().keySet()))
|
||||
.containsExactly("testProperties");
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -65,12 +68,14 @@ public class ConfigurationPropertiesReportEndpointParentTests {
|
||||
.withParent(parent).run(child -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = child
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor result = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
assertThat(result.getBeans().keySet())
|
||||
.containsExactlyInAnyOrder("otherProperties");
|
||||
assertThat((result.getParent().getBeans().keySet()))
|
||||
.containsExactly("testProperties");
|
||||
assertThat(applicationProperties.getContexts().get(child.getId())
|
||||
.getBeans().keySet())
|
||||
.containsExactlyInAnyOrder("otherProperties");
|
||||
assertThat((applicationProperties.getContexts()
|
||||
.get(parent.getId()).getBeans().keySet()))
|
||||
.containsExactly("testProperties");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -20,8 +20,8 @@ import javax.sql.DataSource;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ApplicationConfigurationProperties;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesBeanDescriptor;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesDescriptor;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
@ -52,10 +52,11 @@ public class ConfigurationPropertiesReportEndpointProxyTests {
|
||||
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(Config.class, SqlExecutor.class);
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesDescriptor report = context
|
||||
ApplicationConfigurationProperties applicationProperties = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class)
|
||||
.configurationProperties();
|
||||
assertThat(report.getBeans().values().stream()
|
||||
assertThat(applicationProperties.getContexts().get(context.getId()).getBeans()
|
||||
.values().stream()
|
||||
.map(ConfigurationPropertiesBeanDescriptor::getPrefix)
|
||||
.filter("executor.sql"::equals).findFirst()).isNotEmpty();
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -26,8 +26,8 @@ import com.zaxxer.hikari.HikariDataSource;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ApplicationConfigurationProperties;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesBeanDescriptor;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesDescriptor;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
@ -55,9 +55,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
ConfigurationPropertiesBeanDescriptor foo = properties.getBeans().get("foo");
|
||||
ConfigurationPropertiesBeanDescriptor foo = applicationProperties
|
||||
.getContexts().get(context.getId()).getBeans().get("foo");
|
||||
assertThat(foo).isNotNull();
|
||||
assertThat(foo.getPrefix()).isEqualTo("foo");
|
||||
Map<String, Object> map = foo.getProperties();
|
||||
@ -76,9 +77,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
ConfigurationPropertiesBeanDescriptor foo = properties.getBeans().get("foo");
|
||||
ConfigurationPropertiesBeanDescriptor foo = applicationProperties
|
||||
.getContexts().get(context.getId()).getBeans().get("foo");
|
||||
assertThat(foo).isNotNull();
|
||||
Map<String, Object> map = foo.getProperties();
|
||||
assertThat(map).isNotNull();
|
||||
@ -97,9 +99,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
ConfigurationPropertiesBeanDescriptor foo = properties.getBeans().get("foo");
|
||||
ConfigurationPropertiesBeanDescriptor foo = applicationProperties
|
||||
.getContexts().get(context.getId()).getBeans().get("foo");
|
||||
assertThat(foo.getPrefix()).isEqualTo("foo");
|
||||
Map<String, Object> map = foo.getProperties();
|
||||
assertThat(map).isNotNull();
|
||||
@ -119,10 +122,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
ConfigurationPropertiesBeanDescriptor cycle = properties.getBeans()
|
||||
.get("cycle");
|
||||
ConfigurationPropertiesBeanDescriptor cycle = applicationProperties
|
||||
.getContexts().get(context.getId()).getBeans().get("cycle");
|
||||
assertThat(cycle.getPrefix()).isEqualTo("cycle");
|
||||
Map<String, Object> map = cycle.getProperties();
|
||||
assertThat(map).isNotNull();
|
||||
@ -140,10 +143,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
ConfigurationPropertiesBeanDescriptor fooProperties = properties.getBeans()
|
||||
.get("foo");
|
||||
ConfigurationPropertiesBeanDescriptor fooProperties = applicationProperties
|
||||
.getContexts().get(context.getId()).getBeans().get("foo");
|
||||
assertThat(fooProperties).isNotNull();
|
||||
assertThat(fooProperties.getPrefix()).isEqualTo("foo");
|
||||
Map<String, Object> map = fooProperties.getProperties();
|
||||
@ -161,9 +164,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
ConfigurationPropertiesBeanDescriptor foo = properties.getBeans().get("foo");
|
||||
ConfigurationPropertiesBeanDescriptor foo = applicationProperties
|
||||
.getContexts().get(context.getId()).getBeans().get("foo");
|
||||
assertThat(foo).isNotNull();
|
||||
assertThat(foo.getPrefix()).isEqualTo("foo");
|
||||
Map<String, Object> map = foo.getProperties();
|
||||
@ -182,9 +186,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
ConfigurationPropertiesBeanDescriptor foo = properties.getBeans().get("foo");
|
||||
ConfigurationPropertiesBeanDescriptor foo = applicationProperties
|
||||
.getContexts().get(context.getId()).getBeans().get("foo");
|
||||
assertThat(foo).isNotNull();
|
||||
assertThat(foo.getPrefix()).isEqualTo("foo");
|
||||
Map<String, Object> map = foo.getProperties();
|
||||
@ -202,9 +207,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
ConfigurationPropertiesBeanDescriptor foo = properties.getBeans().get("foo");
|
||||
ConfigurationPropertiesBeanDescriptor foo = applicationProperties
|
||||
.getContexts().get(context.getId()).getBeans().get("foo");
|
||||
assertThat(foo).isNotNull();
|
||||
assertThat(foo.getPrefix()).isEqualTo("foo");
|
||||
Map<String, Object> map = foo.getProperties();
|
||||
@ -223,10 +229,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
assertThat(properties.getBeans()).containsKeys("foo");
|
||||
ConfigurationPropertiesBeanDescriptor foo = properties.getBeans().get("foo");
|
||||
ConfigurationPropertiesBeanDescriptor foo = applicationProperties
|
||||
.getContexts().get(context.getId()).getBeans().get("foo");
|
||||
assertThat(foo.getPrefix()).isEqualTo("foo");
|
||||
Map<String, Object> propertiesMap = foo.getProperties();
|
||||
assertThat(propertiesMap).containsOnlyKeys("bar", "name", "map", "list");
|
||||
@ -244,9 +250,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint
|
||||
.configurationProperties();
|
||||
ConfigurationPropertiesBeanDescriptor hikariDataSource = properties.getBeans()
|
||||
ConfigurationPropertiesBeanDescriptor hikariDataSource = applicationProperties
|
||||
.getContexts().get(context.getId()).getBeans()
|
||||
.get("hikariDataSource");
|
||||
Map<String, Object> nestedProperties = hikariDataSource.getProperties();
|
||||
assertThat(nestedProperties).doesNotContainKey("error");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -27,7 +27,7 @@ import java.util.function.BiConsumer;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesBeanDescriptor;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesDescriptor;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ContextConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
@ -49,7 +49,6 @@ public class ConfigurationPropertiesReportEndpointTests {
|
||||
@Test
|
||||
public void configurationPropertiesAreReturned() {
|
||||
load((context, properties) -> {
|
||||
assertThat(properties.getContextId()).isEqualTo(context.getId());
|
||||
assertThat(properties.getBeans().size()).isGreaterThan(0);
|
||||
ConfigurationPropertiesBeanDescriptor nestedProperties = properties.getBeans()
|
||||
.get("testProperties");
|
||||
@ -161,17 +160,17 @@ public class ConfigurationPropertiesReportEndpointTests {
|
||||
}
|
||||
|
||||
private void load(
|
||||
BiConsumer<ApplicationContext, ConfigurationPropertiesDescriptor> properties) {
|
||||
BiConsumer<ApplicationContext, ContextConfigurationProperties> properties) {
|
||||
load(Collections.emptyList(), properties);
|
||||
}
|
||||
|
||||
private void load(String keyToSanitize,
|
||||
BiConsumer<ApplicationContext, ConfigurationPropertiesDescriptor> properties) {
|
||||
BiConsumer<ApplicationContext, ContextConfigurationProperties> properties) {
|
||||
load(Collections.singletonList(keyToSanitize), properties);
|
||||
}
|
||||
|
||||
private void load(List<String> keysToSanitize,
|
||||
BiConsumer<ApplicationContext, ConfigurationPropertiesDescriptor> properties) {
|
||||
BiConsumer<ApplicationContext, ContextConfigurationProperties> properties) {
|
||||
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(Config.class);
|
||||
contextRunner.run((context) -> {
|
||||
@ -181,7 +180,8 @@ public class ConfigurationPropertiesReportEndpointTests {
|
||||
endpoint.setKeysToSanitize(
|
||||
keysToSanitize.toArray(new String[keysToSanitize.size()]));
|
||||
}
|
||||
properties.accept(context, endpoint.configurationProperties());
|
||||
properties.accept(context, endpoint.configurationProperties().getContexts()
|
||||
.get(context.getId()));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -16,14 +16,12 @@
|
||||
|
||||
package org.springframework.boot.actuate.flyway;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@ -43,8 +41,8 @@ public class FlywayEndpointTests {
|
||||
public void flywayReportIsProduced() {
|
||||
new ApplicationContextRunner().withUserConfiguration(Config.class)
|
||||
.run((context) -> assertThat(
|
||||
context.getBean(FlywayEndpoint.class).flywayReports())
|
||||
.hasSize(1));
|
||||
context.getBean(FlywayEndpoint.class).flywayBeans().getContexts()
|
||||
.get(context.getId()).getFlywayBeans()).hasSize(1));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ -52,8 +50,8 @@ public class FlywayEndpointTests {
|
||||
public static class Config {
|
||||
|
||||
@Bean
|
||||
public FlywayEndpoint endpoint(Map<String, Flyway> flyways) {
|
||||
return new FlywayEndpoint(flyways);
|
||||
public FlywayEndpoint endpoint(ApplicationContext context) {
|
||||
return new FlywayEndpoint(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -16,15 +16,13 @@
|
||||
|
||||
package org.springframework.boot.actuate.liquibase;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import liquibase.integration.spring.SpringLiquibase;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@ -48,8 +46,9 @@ public class LiquibaseEndpointTests {
|
||||
public void liquibaseReportIsReturned() {
|
||||
this.contextRunner.withUserConfiguration(Config.class)
|
||||
.run((context) -> assertThat(
|
||||
context.getBean(LiquibaseEndpoint.class).liquibaseReports())
|
||||
.hasSize(1));
|
||||
context.getBean(LiquibaseEndpoint.class).liquibaseBeans()
|
||||
.getContexts().get(context.getId()).getLiquibaseBeans())
|
||||
.hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -58,16 +57,17 @@ public class LiquibaseEndpointTests {
|
||||
.withPropertyValues("spring.liquibase.default-schema=CUSTOMSCHEMA",
|
||||
"spring.datasource.schema=classpath:/db/create-custom-schema.sql")
|
||||
.run((context) -> assertThat(
|
||||
context.getBean(LiquibaseEndpoint.class).liquibaseReports())
|
||||
.hasSize(1));
|
||||
context.getBean(LiquibaseEndpoint.class).liquibaseBeans()
|
||||
.getContexts().get(context.getId()).getLiquibaseBeans())
|
||||
.hasSize(1));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class Config {
|
||||
|
||||
@Bean
|
||||
public LiquibaseEndpoint endpoint(Map<String, SpringLiquibase> liquibases) {
|
||||
return new LiquibaseEndpoint(liquibases);
|
||||
public LiquibaseEndpoint endpoint(ApplicationContext context) {
|
||||
return new LiquibaseEndpoint(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@ -28,6 +28,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@ -51,6 +52,9 @@ public class SampleActuatorApplicationTests {
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Test
|
||||
public void testHomeIsSecure() {
|
||||
@SuppressWarnings("rawtypes")
|
||||
@ -217,9 +221,7 @@ public class SampleActuatorApplicationTests {
|
||||
.withBasicAuth("user", getPassword())
|
||||
.getForEntity("/actuator/beans", Map.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).containsOnlyKeys("beans", "parent", "contextId");
|
||||
assertThat(((String) entity.getBody().get("contextId")))
|
||||
.startsWith("application");
|
||||
assertThat(entity.getBody()).containsOnlyKeys("contexts");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -231,7 +233,11 @@ public class SampleActuatorApplicationTests {
|
||||
.getForEntity("/actuator/configprops", Map.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
Map<String, Object> body = entity.getBody();
|
||||
assertThat((Map<String, Object>) body.get("beans"))
|
||||
Map<String, Object> contexts = (Map<String, Object>) body.get("contexts");
|
||||
Map<String, Object> context = (Map<String, Object>) contexts
|
||||
.get(this.applicationContext.getId());
|
||||
Map<String, Object> beans = (Map<String, Object>) context.get("beans");
|
||||
assertThat(beans)
|
||||
.containsKey("spring.datasource-" + DataSourceProperties.class.getName());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user