Browse Source
- Gather autoconfiguration conditional decisiions (true and false) - Provide an actuator endpoint as one means to read the report - Define @EnableAutConfigurationReport annotation to turn this feature on - Tidy up autoconfig report a bit and log it if --debug=truepull/118/merge
16 changed files with 838 additions and 50 deletions
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* http://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.endpoint; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.autoconfigure.report.AutoConfigurationReport; |
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
|
||||
/** |
||||
* Endpoint to serve up autoconfiguration report if actuator is on the classpath. |
||||
* |
||||
* @author Greg Turnquist |
||||
*/ |
||||
@ConfigurationProperties(name = "endpoints.autoconfigurationreport", ignoreUnknownFields = false) |
||||
public class AutoConfigurationReportEndpoint extends AbstractEndpoint<AutoConfigurationReport> { |
||||
|
||||
@Autowired |
||||
private AutoConfigurationReport autoConfigurationReport; |
||||
|
||||
public AutoConfigurationReportEndpoint() { |
||||
super("/autoconfigurationreport"); |
||||
} |
||||
|
||||
@Override |
||||
public AutoConfigurationReport invoke() { |
||||
return this.autoConfigurationReport; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* http://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.endpoint; |
||||
|
||||
import org.springframework.boot.autoconfigure.report.EnableAutoConfigurationReport; |
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* Tests for {@link AutoConfigurationReportEndpoint}. |
||||
* |
||||
* @author Greg Turnquist |
||||
*/ |
||||
public class AutoConfigurationReportEndpointTests extends AbstractEndpointTests<AutoConfigurationReportEndpoint> { |
||||
|
||||
public AutoConfigurationReportEndpointTests() { |
||||
super(Config.class, AutoConfigurationReportEndpoint.class, |
||||
"/autoconfigurationreport", true, "endpoints.autoconfigurationreport"); |
||||
} |
||||
|
||||
@Configuration |
||||
@EnableConfigurationProperties |
||||
@EnableAutoConfigurationReport |
||||
public static class Config { |
||||
|
||||
@Bean |
||||
public AutoConfigurationReportEndpoint endpoint() { |
||||
return new AutoConfigurationReportEndpoint(); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* http://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.autoconfigure.condition; |
||||
|
||||
/** |
||||
* Outcome for a match, including log message. |
||||
*/ |
||||
public class Outcome { |
||||
|
||||
private final boolean match; |
||||
private final String message; |
||||
|
||||
public Outcome(boolean match, String message) { |
||||
this.match = match; |
||||
this.message = message; |
||||
} |
||||
|
||||
public static Outcome match() { |
||||
return match(null); |
||||
} |
||||
|
||||
public static Outcome match(String message) { |
||||
return new Outcome(true, message); |
||||
} |
||||
|
||||
public static Outcome noMatch(String message) { |
||||
return new Outcome(false, message); |
||||
} |
||||
|
||||
public boolean isMatch() { |
||||
return this.match; |
||||
} |
||||
|
||||
public String getMessage() { |
||||
return this.message; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* http://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.autoconfigure.report; |
||||
|
||||
import org.springframework.boot.autoconfigure.condition.Outcome; |
||||
|
||||
/** |
||||
* Collects details about decision made during autoconfiguration (pass or fail) |
||||
* |
||||
* @author Greg Turnquist |
||||
*/ |
||||
public class AutoConfigurationDecision { |
||||
private final String message; |
||||
private final String classOrMethodName; |
||||
private final Outcome outcome; |
||||
|
||||
public AutoConfigurationDecision(String message, String classOrMethodName, Outcome outcome) { |
||||
this.message = message; |
||||
this.classOrMethodName = classOrMethodName; |
||||
this.outcome = outcome; |
||||
} |
||||
|
||||
public String getMessage() { |
||||
return message; |
||||
} |
||||
|
||||
public String getClassOrMethodName() { |
||||
return classOrMethodName; |
||||
} |
||||
|
||||
public Outcome getOutcome() { |
||||
return outcome; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "AutoConfigurationDecision{" + "message='" + message + '\'' |
||||
+ ", classOrMethodName='" + classOrMethodName + '\'' + ", outcome=" |
||||
+ outcome + '}'; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (this == o) |
||||
return true; |
||||
if (o == null || getClass() != o.getClass()) |
||||
return false; |
||||
|
||||
AutoConfigurationDecision decision = (AutoConfigurationDecision) o; |
||||
|
||||
if (message != null ? !message.equals(decision.message) |
||||
: decision.message != null) |
||||
return false; |
||||
if (outcome != null ? !outcome.equals(decision.outcome) |
||||
: decision.outcome != null) |
||||
return false; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
int result = message != null ? message.hashCode() : 0; |
||||
result = 31 * result + (outcome != null ? outcome.hashCode() : 0); |
||||
return result; |
||||
} |
||||
} |
||||
@ -0,0 +1,202 @@
@@ -0,0 +1,202 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* http://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.autoconfigure.report; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.util.ArrayList; |
||||
import java.util.HashSet; |
||||
import java.util.LinkedHashMap; |
||||
import java.util.LinkedHashSet; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.beans.BeansException; |
||||
import org.springframework.boot.autoconfigure.condition.Outcome; |
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.ApplicationContextAware; |
||||
import org.springframework.context.ApplicationListener; |
||||
import org.springframework.context.annotation.ConditionContext; |
||||
import org.springframework.context.event.ContextRefreshedEvent; |
||||
|
||||
/** |
||||
* Bean used to gather autoconfiguration decisions, and then generate a collection of info |
||||
* for beans that were created as well as situations where the conditional outcome was |
||||
* negative. |
||||
* |
||||
* @author Greg Turnquist |
||||
* @author Dave Syer |
||||
*/ |
||||
public class AutoConfigurationReport implements ApplicationContextAware, |
||||
ApplicationListener<ContextRefreshedEvent> { |
||||
|
||||
private static Log logger = LogFactory.getLog(AutoConfigurationReport.class); |
||||
|
||||
private Set<CreatedBeanInfo> beansCreated = new LinkedHashSet<CreatedBeanInfo>(); |
||||
private Map<String, List<AutoConfigurationDecision>> autoconfigurationDecisions = new LinkedHashMap<String, List<AutoConfigurationDecision>>(); |
||||
private Map<String, List<String>> positive = new LinkedHashMap<String, List<String>>(); |
||||
private Map<String, List<String>> negative = new LinkedHashMap<String, List<String>>(); |
||||
private ApplicationContext context; |
||||
private boolean initialized = false; |
||||
|
||||
public static void registerDecision(ConditionContext context, String message, |
||||
String classOrMethodName, Outcome outcome) { |
||||
if (context.getBeanFactory().containsBeanDefinition("autoConfigurationReport")) { |
||||
AutoConfigurationReport autoconfigurationReport = context.getBeanFactory() |
||||
.getBean(AutoConfigurationReport.class); |
||||
autoconfigurationReport.registerDecision(message, classOrMethodName, outcome); |
||||
} |
||||
} |
||||
|
||||
private void registerDecision(String message, String classOrMethodName, |
||||
Outcome outcome) { |
||||
AutoConfigurationDecision decision = new AutoConfigurationDecision(message, |
||||
classOrMethodName, outcome); |
||||
if (!this.autoconfigurationDecisions.containsKey(classOrMethodName)) { |
||||
this.autoconfigurationDecisions.put(classOrMethodName, |
||||
new ArrayList<AutoConfigurationDecision>()); |
||||
} |
||||
this.autoconfigurationDecisions.get(classOrMethodName).add(decision); |
||||
} |
||||
|
||||
public Set<CreatedBeanInfo> getBeansCreated() { |
||||
return this.beansCreated; |
||||
} |
||||
|
||||
public Map<String, List<String>> getNegativeDecisions() { |
||||
return this.negative; |
||||
} |
||||
|
||||
public Set<Class<?>> getBeanTypesCreated() { |
||||
Set<Class<?>> beanTypesCreated = new HashSet<Class<?>>(); |
||||
for (CreatedBeanInfo bootCreatedBeanInfo : this.getBeansCreated()) { |
||||
beanTypesCreated.add(bootCreatedBeanInfo.getBeanType()); |
||||
} |
||||
return beanTypesCreated; |
||||
} |
||||
|
||||
public Set<String> getBeanNamesCreated() { |
||||
Set<String> beanNamesCreated = new HashSet<String>(); |
||||
for (CreatedBeanInfo bootCreatedBeanInfo : this.getBeansCreated()) { |
||||
beanNamesCreated.add(bootCreatedBeanInfo.getName()); |
||||
} |
||||
return beanNamesCreated; |
||||
} |
||||
|
||||
@Override |
||||
public void setApplicationContext(ApplicationContext applicationContext) |
||||
throws BeansException { |
||||
this.context = applicationContext; |
||||
} |
||||
|
||||
@Override |
||||
public void onApplicationEvent(ContextRefreshedEvent event) { |
||||
initialize(); |
||||
} |
||||
|
||||
public void initialize() { |
||||
if (!this.initialized) { |
||||
synchronized (this) { |
||||
if (!this.initialized) { |
||||
this.initialized = true; |
||||
splitDecisionsIntoPositiveAndNegative(); |
||||
scanPositiveDecisionsForBeansBootCreated(); |
||||
if (this.context.getEnvironment().getProperty("debug", Boolean.class, |
||||
false)) { |
||||
logger.info("Created beans:"); |
||||
for (CreatedBeanInfo info : this.beansCreated) { |
||||
logger.info(info); |
||||
} |
||||
logger.info("Negative decisions:"); |
||||
for (String key : this.negative.keySet()) { |
||||
logger.info(key + ": " + this.negative.get(key)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Scan the list of {@link AutoConfigurationDecision}'s, and if all outcomes true, |
||||
* then put it on the positive list. Otherwise, put it on the negative list. |
||||
*/ |
||||
private synchronized void splitDecisionsIntoPositiveAndNegative() { |
||||
for (String key : this.autoconfigurationDecisions.keySet()) { |
||||
boolean match = true; |
||||
for (AutoConfigurationDecision decision : this.autoconfigurationDecisions |
||||
.get(key)) { |
||||
if (!decision.getOutcome().isMatch()) { |
||||
match = false; |
||||
} |
||||
} |
||||
if (match) { |
||||
if (!this.positive.containsKey(key)) { |
||||
this.positive.put(key, new ArrayList<String>()); |
||||
} |
||||
for (AutoConfigurationDecision decision : this.autoconfigurationDecisions |
||||
.get(key)) { |
||||
this.positive.get(key).add(decision.getMessage()); |
||||
} |
||||
} |
||||
else { |
||||
if (!this.negative.containsKey(key)) { |
||||
this.negative.put(key, new ArrayList<String>()); |
||||
} |
||||
for (AutoConfigurationDecision decision : this.autoconfigurationDecisions |
||||
.get(key)) { |
||||
this.negative.get(key).add(decision.getMessage()); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Scan all the decisions based on successful outcome, and try to find the |
||||
* corresponding beans Boot created. |
||||
*/ |
||||
private synchronized void scanPositiveDecisionsForBeansBootCreated() { |
||||
for (String key : this.positive.keySet()) { |
||||
for (AutoConfigurationDecision decision : this.autoconfigurationDecisions |
||||
.get(key)) { |
||||
for (String beanName : this.context.getBeanDefinitionNames()) { |
||||
Object bean = this.context.getBean(beanName); |
||||
if (decision.getMessage().contains(beanName) |
||||
&& decision.getMessage().contains("matched")) { |
||||
boolean anyMethodsAreBeans = false; |
||||
for (Method method : bean.getClass().getMethods()) { |
||||
if (this.context.containsBean(method.getName())) { |
||||
this.beansCreated.add(new CreatedBeanInfo(method |
||||
.getName(), method.getReturnType(), this.positive |
||||
.get(key))); |
||||
anyMethodsAreBeans = true; |
||||
} |
||||
} |
||||
|
||||
if (!anyMethodsAreBeans) { |
||||
this.beansCreated.add(new CreatedBeanInfo(beanName, bean, |
||||
this.positive.get(key))); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,82 @@
@@ -0,0 +1,82 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* http://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.autoconfigure.report; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* A collection of data about a bean created by Boot |
||||
* |
||||
* @author Greg Turnquist |
||||
*/ |
||||
public class BootCreatedBeanInfo { |
||||
|
||||
private final String beanName; |
||||
private final Class<?> beanType; |
||||
private final List<String> decisions; |
||||
|
||||
public BootCreatedBeanInfo(String beanName, Object bean, List<String> decisions) { |
||||
this.beanName = beanName; |
||||
this.beanType = bean.getClass(); |
||||
this.decisions = decisions; |
||||
} |
||||
|
||||
public BootCreatedBeanInfo(String beanName, Class<?> declaredBeanType, List<String> decisions) { |
||||
this.beanName = beanName; |
||||
this.beanType = declaredBeanType; |
||||
this.decisions = decisions; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "BootCreatedBeanInfo{" + "beanName='" + beanName + '\'' + ", beanType=" + beanType |
||||
+ ", decisions=" + decisions + '}'; |
||||
} |
||||
|
||||
public String getBeanName() { |
||||
return beanName; |
||||
} |
||||
|
||||
public Class<?> getBeanType() { |
||||
return beanType; |
||||
} |
||||
|
||||
public List<String> getDecisions() { |
||||
return decisions; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (this == o) |
||||
return true; |
||||
if (o == null || getClass() != o.getClass()) |
||||
return false; |
||||
|
||||
BootCreatedBeanInfo bootCreatedBeanInfo = (BootCreatedBeanInfo) o; |
||||
|
||||
if (beanName != null ? !beanName.equals(bootCreatedBeanInfo.beanName) |
||||
: bootCreatedBeanInfo.beanName != null) |
||||
return false; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return beanName != null ? beanName.hashCode() : 0; |
||||
} |
||||
} |
||||
@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* http://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.autoconfigure.report; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* A collection of data about a bean created by Boot |
||||
* |
||||
* @author Greg Turnquist |
||||
*/ |
||||
public class CreatedBeanInfo { |
||||
|
||||
private final String name; |
||||
private final Class<?> type; |
||||
private final List<String> decisions; |
||||
|
||||
public CreatedBeanInfo(String beanName, Object bean, List<String> decisions) { |
||||
this.name = beanName; |
||||
this.type = bean.getClass(); |
||||
this.decisions = decisions; |
||||
} |
||||
|
||||
public CreatedBeanInfo(String beanName, Class<?> declaredBeanType, |
||||
List<String> decisions) { |
||||
this.name = beanName; |
||||
this.type = declaredBeanType; |
||||
this.decisions = decisions; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "{" + "name='" + this.name + '\'' + ", type=" + this.type + ", decisions=" |
||||
+ this.decisions + '}'; |
||||
} |
||||
|
||||
public String getName() { |
||||
return this.name; |
||||
} |
||||
|
||||
public Class<?> getBeanType() { |
||||
return this.type; |
||||
} |
||||
|
||||
public List<String> getDecisions() { |
||||
return this.decisions; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (this == o) |
||||
return true; |
||||
if (o == null || getClass() != o.getClass()) |
||||
return false; |
||||
|
||||
CreatedBeanInfo bootCreatedBeanInfo = (CreatedBeanInfo) o; |
||||
|
||||
if (this.name != null ? !this.name.equals(bootCreatedBeanInfo.name) |
||||
: bootCreatedBeanInfo.name != null) |
||||
return false; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return this.name != null ? this.name.hashCode() : 0; |
||||
} |
||||
} |
||||
@ -0,0 +1,188 @@
@@ -0,0 +1,188 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* http://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.autoconfigure; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertTrue; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory; |
||||
import org.springframework.amqp.rabbit.core.RabbitAdmin; |
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate; |
||||
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration; |
||||
import org.springframework.boot.autoconfigure.jms.JmsTemplateAutoConfiguration; |
||||
import org.springframework.boot.autoconfigure.report.AutoConfigurationReport; |
||||
import org.springframework.boot.autoconfigure.report.CreatedBeanInfo; |
||||
import org.springframework.boot.autoconfigure.report.EnableAutoConfigurationReport; |
||||
import org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration; |
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; |
||||
import org.springframework.jms.core.JmsTemplate; |
||||
|
||||
/** |
||||
* Tests for {@link AutoConfigurationReport}. |
||||
* |
||||
* @author Greg Turnquist |
||||
*/ |
||||
public class AutoConfigurationReportTests { |
||||
|
||||
private AnnotationConfigApplicationContext context; |
||||
|
||||
@Test |
||||
public void simpleReportTestCase() { |
||||
this.context = new AnnotationConfigApplicationContext(); |
||||
this.context.register(TestConfiguration.class, |
||||
PropertyPlaceholderAutoConfiguration.class); |
||||
this.context.refresh(); |
||||
AutoConfigurationReport autoconfigSettings = this.context |
||||
.getBean(AutoConfigurationReport.class); |
||||
|
||||
Set<CreatedBeanInfo> beansBootCreated = autoconfigSettings.getBeansCreated(); |
||||
Set<String> beanNamesBootCreated = autoconfigSettings.getBeanNamesCreated(); |
||||
Set<Class<?>> beanTypesBootCreated = autoconfigSettings.getBeanTypesCreated(); |
||||
|
||||
assertEquals(1, beansBootCreated.size()); |
||||
assertEquals(1, beanNamesBootCreated.size()); |
||||
assertEquals(1, beanTypesBootCreated.size()); |
||||
|
||||
assertTrue(beanNamesBootCreated.contains("propertySourcesPlaceholderConfigurer")); |
||||
assertTrue(beanTypesBootCreated |
||||
.contains(PropertySourcesPlaceholderConfigurer.class)); |
||||
|
||||
boolean foundPropertySourcesPlaceHolderConfigurer = false; |
||||
int totalDecisions = 0; |
||||
for (CreatedBeanInfo item : beansBootCreated) { |
||||
for (String decision : item.getDecisions()) { |
||||
totalDecisions += 1; |
||||
if (decision.contains("propertySourcesPlaceholderConfigurer matched")) { |
||||
foundPropertySourcesPlaceHolderConfigurer = true; |
||||
} |
||||
} |
||||
} |
||||
assertEquals(1, totalDecisions); |
||||
assertTrue(foundPropertySourcesPlaceHolderConfigurer); |
||||
} |
||||
|
||||
@Test |
||||
public void rabbitReportTest() { |
||||
this.context = new AnnotationConfigApplicationContext(); |
||||
this.context.register(TestConfiguration.class, RabbitAutoConfiguration.class); |
||||
this.context.refresh(); |
||||
AutoConfigurationReport autoconfigSettings = this.context |
||||
.getBean(AutoConfigurationReport.class); |
||||
|
||||
Set<CreatedBeanInfo> beansBootCreated = autoconfigSettings.getBeansCreated(); |
||||
Set<String> beanNamesBootCreated = autoconfigSettings.getBeanNamesCreated(); |
||||
Set<Class<?>> beanTypesBootCreated = autoconfigSettings.getBeanTypesCreated(); |
||||
|
||||
assertEquals(3, beansBootCreated.size()); |
||||
assertEquals(3, beanNamesBootCreated.size()); |
||||
assertEquals(3, beanTypesBootCreated.size()); |
||||
|
||||
assertTrue(beanNamesBootCreated.contains("amqpAdmin")); |
||||
assertTrue(beanNamesBootCreated.contains("rabbitConnectionFactory")); |
||||
assertTrue(beanNamesBootCreated.contains("rabbitTemplate")); |
||||
|
||||
assertTrue(beanTypesBootCreated.contains(RabbitAdmin.class)); |
||||
assertTrue(beanTypesBootCreated.contains(ConnectionFactory.class)); |
||||
assertTrue(beanTypesBootCreated.contains(RabbitTemplate.class)); |
||||
|
||||
boolean foundRabbitConnectionFactory = false; |
||||
boolean foundAmqpAdminExpressionCondition = false; |
||||
boolean foundAmqpAdminBeanCondition = false; |
||||
boolean foundRabbitTemplateCondition = false; |
||||
int totalDecisions = 0; |
||||
for (CreatedBeanInfo item : beansBootCreated) { |
||||
for (String decision : item.getDecisions()) { |
||||
totalDecisions += 1; |
||||
if (decision.contains("RabbitConnectionFactoryCreator matched")) { |
||||
foundRabbitConnectionFactory = true; |
||||
} else if (decision.contains("OnExpressionCondition") |
||||
&& decision.contains("amqpAdmin matched due to SpEL expression")) { |
||||
foundAmqpAdminExpressionCondition = true; |
||||
} else if (decision.contains("OnBeanCondition") |
||||
&& decision.contains("amqpAdmin matched")) { |
||||
foundAmqpAdminBeanCondition = true; |
||||
} else if (decision.contains("rabbitTemplate matched")) { |
||||
foundRabbitTemplateCondition = true; |
||||
} |
||||
} |
||||
} |
||||
assertEquals(4, totalDecisions); |
||||
assertTrue(foundRabbitConnectionFactory); |
||||
assertTrue(foundAmqpAdminExpressionCondition); |
||||
assertTrue(foundAmqpAdminBeanCondition); |
||||
assertTrue(foundRabbitTemplateCondition); |
||||
} |
||||
|
||||
@Test |
||||
public void verifyItGathersNegativeMatches() { |
||||
this.context = new AnnotationConfigApplicationContext(); |
||||
this.context.register(TestConfiguration2.class, |
||||
JmsTemplateAutoConfiguration.class, MultipartAutoConfiguration.class); |
||||
this.context.refresh(); |
||||
AutoConfigurationReport autoconfigSettings = this.context |
||||
.getBean(AutoConfigurationReport.class); |
||||
|
||||
Map<String, List<String>> negatives = autoconfigSettings.getNegativeDecisions(); |
||||
|
||||
boolean foundMyOwnJmsTemplateAndBackedOff = false; |
||||
boolean didNotFindMultipartConfigElement = false; |
||||
int totalNegativeDecisions = 0; |
||||
for (String key : negatives.keySet()) { |
||||
for (String decision : negatives.get(key)) { |
||||
totalNegativeDecisions += 1; |
||||
if (decision |
||||
.contains("JmsTemplateAutoConfiguration#jmsTemplate did not match") |
||||
&& decision.contains("found the following [myOwnJmsTemplate]")) { |
||||
foundMyOwnJmsTemplateAndBackedOff = true; |
||||
} else if (decision.contains("MultipartAutoConfiguration did not match") |
||||
&& decision |
||||
.contains("list['javax.servlet.MultipartConfigElement']") |
||||
&& decision.contains("found no beans")) { |
||||
didNotFindMultipartConfigElement = true; |
||||
} |
||||
} |
||||
} |
||||
// varying situations might cause multi-conditional beans to evaluate in different orders
|
||||
assertTrue(totalNegativeDecisions >= 2); |
||||
assertTrue(foundMyOwnJmsTemplateAndBackedOff); |
||||
assertTrue(didNotFindMultipartConfigElement); |
||||
|
||||
} |
||||
|
||||
@Configuration |
||||
@EnableAutoConfigurationReport |
||||
public static class TestConfiguration { |
||||
} |
||||
|
||||
@Configuration |
||||
@EnableAutoConfigurationReport |
||||
public static class TestConfiguration2 { |
||||
@Bean |
||||
JmsTemplate myOwnJmsTemplate(javax.jms.ConnectionFactory connectionFactory) { |
||||
return new JmsTemplate(connectionFactory); |
||||
} |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue