jim stafford
Configuration focus thus far has been
under fairly static conditions
applied directly to a single application
dynamically determined
modularized and not repeated
dynamic based on runtime environment at startup
libraries present
properties defined
resources found
etc.
Examples:
what database will be used when in development, integration, or production?
what security should be enabled in development versus production areas?
applications will ideally be broken into separate components
making components reusable for multiple applications is good practice
requires physically breaking them into separate modules
leaves us with repeated responsibility to configure reused components
there could be dozens of choices to make within a component configuration
application can be significantly simplified by an opinionated configuration supplied based on runtime environment
If you find yourself
needing configurations determined dynamically at runtime
solving a repeated problem and bundling that into a library shared by multiple applications
Master the concepts behind Spring Boot’s Auto-configuration capability
The student will learn to:
Enable/disable bean creation based on condition(s) at startup
Create Auto-configuration/Starter module(s) that establish necessary dependencies and conditionally supplies beans
Resolve conflicts between alternate configurations
Locate environment and condition details to debug Auto-configuration issues
At the conclusion of this lecture and related exercises, the student will be able to:
Enable a @Component, @Configuration class, or @Bean factory method based
on the result of a condition at startup
Create Spring Boot Auto-configuration/Starter module(s)
Bootstrap Auto-configuration classes into applications using a Spring Boot 3 org.springframework.boot.autoconfigure.AutoConfiguration.imports metadata file
Create a conditional component based on the presence of a property value
Create a conditional component based on a missing component
Create a conditional component based on the presence of a class
Define a processing dependency order for Auto-configuration classes
Access textual debug information relative to conditions using the debug property
Access web-based debug information relative to conditionals and properties using the Spring Boot Actuator
@Configuration classes used to bootstrap application using Java classes
modern alternative to legacy XML definitions that basically do the same thing — define and configure beans
can be the @SpringBootApplication class itself
appropriate for a small application
@SpringBootApplication
//==> wraps @EnableAutoConfiguration
//==> wraps @SpringBootConfiguration
// ==> wraps @Configuration
public class SelfConfiguredApp {
public static void main(String...args) {
SpringApplication.run(SelfConfiguredApp.class, args);
}
@Bean
public Hello hello() {
return new StdOutHello("Application @Bean says Hey");
}
}can be broken out into separate classes
appropriate for larger applications with distinct areas to be configured
@Configuration(proxyBeanMethods = false) (2)
public class AConfigurationClass {
@Bean (1)
public Hello hello() {
return new StdOutHello("...");
}
}
| 1 | bean scope defaults to "singleton" |
| 2 | nothing directly calling the @Bean factory method; establishing a CGLIB proxy is unnecessary |
@Configuration classes are commonly annotated with the proxyMethods=false attribute that tells Spring not to create extra proxy code to enforce normal, singleton return of the created instance to be shared by all callers since @Configuration class instances are only called by Spring.
The javadoc for the annotation attribute describes the extra and unnecessary work saved. |
can make configurations dependent on conditions found at startup
individual @Bean factory methods (or the @Component annotated class)
entire @Configuration classes
...
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class StarterConfiguredApp {
public static void main(String...args) {
SpringApplication.run(StarterConfiguredApp.class, args);
}
@Bean
@ConditionalOnProperty(prefix="hello", name="quiet", havingValue="true") (1)
public Hello quietHello() {
return new StdOutHello("(hello.quiet property condition set, Application @Bean says hi)");
}
}| 1 |
@ConditionalOnProperty annotation used to define a Hello bean based on the presence of the hello.quiet property having the value true |
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar --hello.quiet=true (1)
...
(hello.quiet property condition set, Application @Bean says hi) World (2)
| 1 | matching property supplied using command line |
| 2 | satisfies property condition in @SpringBootApplication |
The (parentheses) is trying to indicate a whisper.
hello.quiet=true property turns on this behavior. |
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar (1)
...
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in info.ejava.examples.app.config.auto.AppCommand required a bean of type 'info.ejava.examples.app.hello.Hello' that could not be found. (2)
Action:
Consider defining a bean of type 'info.ejava.examples.app.hello.Hello' in your configuration.
| 1 | property either not specified or not specified with targeted value |
| 2 | property condition within @SpringBootApplication not satisfied |
Configuration processing within Spring Boot is separated into two primary phases:
User-defined configuration classes
processed first
part of the application module
located through the use of a @ComponentScan (wrapped by @SpringBootApplication)
establish the base configuration for the application
fill in any fine-tuning details.
Auto-configuration classes
parsed second
outside the scope of the @ComponentScan
placed in separate modules, identified by metadata within those modules
enabled by application using @EnableAutoConfiguration (also wrapped by @SpringBootApplication)
provide defaults to fill in the reusable parts of the application
use User-defined configuration for details
technically no different from any other @Configuration class except
inspected after User-defined @Configuration class(es) processing complete
based on being named in a descriptor file within META-INF/
alternate identification and second pass processing allows the core application to
make key directional and detailed decisions
control conditions for the Auto-configuration class(es)
package info.ejava.examples.app.hello; (2)
...
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HelloProperties.class)
public class HelloAutoConfiguration {
@Bean (1)
public Hello hello(HelloProperties helloProperties) {
return new StdOutHello(helloProperties.getGreeting());
}
}| 1 | Example Auto-configuration class provides unconditional @Bean factory for Hello |
| 2 | this @Configuration package is outside the default scanning scope of @SpringBootApplication |
Auto-Configuration Packages are Separate from Application Auto-Configuration classes are designed to be outside the scope of the
|
Spring Boot 2.7 added the @AutoConfiguration annotation, which
extends @Configuration
permanently sets proxyBeanMethods to false
contains aliases for before/after configuration processing order
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
//@Configuration(proxyBeanMethods = false)
@AutoConfiguration
public class HelloAutoConfiguration {
It helps document the purpose of the @Configuration class and provides some ease of use features, but the @Configuration annotation can still be used.
this particular @Bean factory defines the @ConfigurationProperties class to
encapsulate the details of configuring Hello
supplies a default greeting
making it optional for the User-defined configuration to do anything
@ConfigurationProperties("hello")
@Data
@Validated
public class HelloProperties {
@NotBlank
private String greeting = "HelloProperties default greeting says Hola!"; (1)
}
| 1 | Value used if user-configuration does not specify a property value |
registered within META-INF/spring/ org.springframework.boot.autoconfigure.AutoConfiguration file of Auto-configuration class’s JAR
$ jar tf target/hello-starter-*-SNAPSHOT.jar | egrep -v '/$|maven|MANIFEST.MF'
META-INF/spring-configuration-metadata.json (2)
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (1)
info/ejava/examples/app/hello/HelloProperties.class
info/ejava/examples/app/hello/HelloAutoConfiguration.class
| 1 | "auto-configuration" dependency JAR supplies … AutoConfiguration.imports |
| 2 | @ConfigurationProperties class metadata generated by maven plugin for use by IDEs |
It is common best-practice to host Auto-configuration classes in a separate
module than the beans it configures. The Hello interface and Hello implementation(s)
comply with this convention and are housed in separate modules. |
List each fully qualified class name in … AutoConfiguration.imports file, one per line
# src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
info.ejava.examples.app.hello.HelloAutoConfiguration (1)
info.ejava.examples.app.hello.HelloResourceAutoConfiguration (2)
| 1 | Auto-configuration class registration |
| 2 | this class is part of a later example; multiple classes are listed one-per-line |
Prior to Spring Boot 2.7, the general purpose META-INF/spring.factories file was used to bootstrap auto-configuration classes.
This approach was deprecated in 2.7 and eliminated in Spring Boot 3.
If you are ever working with a legacy version of Spring Boot, you will have to use this approach.
list each class' fully qualified name, separated by commas, in spring.factories file
used property name equaling fully qualified classname of @EnableAutoConfiguration annotation
# src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
info.ejava.examples.app.hello.HelloAutoConfiguration, \ (1)
info.ejava.examples.app.hello.HelloResourceAutoConfiguration
| 1 | Auto-configuration class registration |
| The last line of the property cannot end with a comma or Spring Boot 2 will interpret entry as an empty class name |
pom.xml
src
`-- main
|-- java
| `-- info
| `-- ejava
| `-- examples
| `-- app
| `-- hello
| |-- HelloAutoConfiguration.java
| `-- HelloProperties.java
`-- resources
`-- META-INF
`-- spring
`-- org.springframework.boot.autoconfigure.AutoConfiguration.importsModules designed as starters can have varying designs with the following roles carried out:
Auto-configuration classes that conditionally wire the application.
An opinionated starter with dependencies that trigger the Auto-configuration rules

The module commonly termed a starter and will have dependencies on
spring-boot-starter, which has dependency on spring-boot-autoconfigure with auto-configuration class references waiting for conditions
the service interface
one or more service implementation(s) and their implementation dependencies
<groupId>info.ejava.examples.app</groupId>
<artifactId>hello-starter</artifactId>
<dependencies>
<dependency> (1)
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- commonly declares dependency on interface module -->
<dependency> (2)
<groupId>${project.groupId}</groupId>
<artifactId>hello-service-api</artifactId>
<version>${project.version}</version>
</dependency> (2)
<!-- hello implementation dependency -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>hello-service-stdout</artifactId>
<version>${project.version}</version>
</dependency>
| 1 | dependency on spring-boot-starter define classes pertinent to Auto-configuration |
| 2 | starter modules commonly define dependencies on interface and implementation modules |
remaining dependencies support the specific example module implementation
The application module declares dependency on the starter module containing or having a dependency on the Auto-configuration artifacts.
<!-- takes care of initializing Hello Service for us to inject -->
<dependency>
<groupId>${project.groupId}</groupId> (1)
<artifactId>hello-starter</artifactId>
<version>${project.version}</version> (1)
</dependency>
| 1 | For this example, the application and starter modules share the same groupId and version
and leverage a ${project} variable to simplify the expression.
That will likely not be the case with most starter module dependencies and will need to be spelled out. |
starter dependency brings in
Hello Service interface
targeted implementation(s)
some implementation dependencies
$ mvn dependency:tree
...
[INFO] +- info.ejava.examples.app:hello-starter:jar:6.1.0-SNAPSHOT:compile
[INFO] | +- info.ejava.examples.app:hello-service-api:jar:6.1.0-SNAPSHOT:compile
[INFO] | +- info.ejava.examples.app:hello-service-stdout:jar:6.1.0-SNAPSHOT:compile
[INFO] | +- org.projectlombok:lombok:jar:1.18.10:provided
[INFO] | \- org.springframework.boot:spring-boot-starter-validation:jar:3.3.2:compile
...example application contains component that requests the greeter implementation of type Hello to say hello to "World"
import lombok.RequiredArgsConstructor;
...
@Component
@RequiredArgsConstructor (1)
public class AppCommand implements CommandLineRunner {
private final Hello greeter; //<== component in App requires Hello injected
public void run(String... args) throws Exception {
greeter.sayHello("World");
}
}| 1 | lombok is being used to provide the constructor injection |
This starter dependency is bringing in a @Bean factory to construct an implementation of Hello, that can satisfy the injection dependency.
package info.ejava.examples.app.hello;
...
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HelloProperties.class)
public class HelloAutoConfiguration {
@Bean
public Hello hello(HelloProperties helloProperties) { (1)
return new StdOutHello(helloProperties.getGreeting());
}
}
| 1 | Example Auto-configuration configured by HelloProperties |
This bean will be unconditionally instantiated the way it is currently defined.
starter dependency brings in an Auto-configuration class that instantiates a StdOutHello implementation configured by a HelloProperties class
@ConfigurationProperties("hello")
@Data
@Validated
public class HelloProperties {
@NotBlank
private String greeting = "HelloProperties default greeting says Hola!"; (1)
}
| 1 | hello.greeting default defined in @ConfigurationProperties class of starter/autoconfigure module |
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar
...
HelloProperties default greeting says Hola! World
HelloAutoConfiguration.hello @Bean instantiated with HelloProperties greeting of "HelloProperties default greeting says Hola!"
This Hello instance was injected into AppCommand, which added "World" to result
Example of Reasonable Default This is an example of a component being Auto-configured with a reasonable default.
It did not simply crash, demanding a greeting be supplied. |
application can supply properties to express details of greeting
#appconfig-autoconfig-example application.properties
#uncomment to use this greeting
hello.greeting: application.properties Says - Hey
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar
...
application.properties Says - Hey World (1)
| 1 | auto-configured implementation using user-defined property |
same scenario as before is occurring
except instantiation of the HelloProperties finds hello.greeting property to override Java default
Example of Configuring Details This is an example of customizing the behavior of an Auto-configured component. |
We saw how we could make a @Bean factory in the User-defined application module conditional (on the value of a property).
@SpringBootApplication
public class StarterConfiguredApp {
...
@Bean
@ConditionalOnProperty(prefix = "hello", name = "quiet", havingValue = "true")
public Hello quietHello() {
return new StdOutHello("(hello.quiet property condition set, Application @Bean says hi)");
}
}have condition where our two @Bean factory methods cause ambiguity error
@Bean factory in User-defined application module conditional (on property value)
@Bean factory in Auto-configuration class brought in by starter module
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar --hello.quiet=true (1)
...
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in info.ejava.examples.app.config.auto.AppCommand
required a single bean, but 2 were found:
- quietHello: defined by method 'quietHello' in info.ejava.examples.app.config.auto.StarterConfiguredApp
- hello: defined by method 'hello' in class path resource [info/ejava/examples/app/hello/HelloAutoConfiguration.class]
This may be due to missing parameter name information
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
| 1 | Supplying the hello.quiet=true property value causes two @Bean factories to choose from |
Conditional
If User-definition did not supply a bean
can solve ambiguity by using @ConditionalOnMissingBean annotation
...
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HelloProperties.class)
public class HelloAutoConfiguration {
@Bean
@ConditionalOnMissingBean (1)
public Hello hello(HelloProperties helloProperties) {
return new StdOutHello(helloProperties.getGreeting());
}
}
| 1 | @ConditionOnMissingBean causes Auto-configured @Bean method to be inactive when Hello bean already exists |
@ConditionalOnMissingBean and sibling @ConditionalOnBean are special
meant to be used with Auto-configuration classes in the autoconfigure modules
Auto-configuration classes are processed after the User-defined classes
clear point to determine whether User-defined @Bean factory does or does not exist
any other use of these two annotations requires careful ordering and is not recommended
with @ConditionalOnMissingBean defined on Auto-configuration class and the property condition satisfied
we get bean injected from User-defined @Bean factory
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar --hello.quiet=true
...
(hello.quiet property condition set, Application @Bean says hi) World
with property condition not satisfied, we get bean injected from
Auto-configuration @Bean factory
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar
...
application.properties Says - Hey Worldcan define condition based on presence of resource on filesystem or classpath using @ConditionOnResource
can also order our Auto-configured classes using
...
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
@Configuration(proxyBeanMethods = false)
@ConditionalOnResource(resources = "file:./hello.properties") (1)
@AutoConfigureBefore(HelloAutoConfiguration.class) (2)
public class HelloResourceAutoConfiguration {
@Bean
public Hello resourceHello() {
return new StdOutHello("hello.properties exists says hello");
}
}| 1 | Auto-configured class satisfied only when file hello.properties present |
| 2 | This Auto-configuration class is processed prior to HelloAutoConfiguration |
We can use the @AutoConfiguration annotation
wraps some of our desired settings
import org.springframework.boot.autoconfigure.AutoConfiguration;
@AutoConfiguration(before = HelloAutoConfiguration.class)
//==> wraps @Configuration(proxyBeanMethods = false)
//==> wraps @AutoConfigureBefore(HelloAutoConfiguration.class)
@ConditionalOnClass(StdOutHello.class)
@ConditionalOnResource(resources = "file:./hello.properties")
public class HelloResourceAutoConfiguration {# src/main/resources/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
info.ejava.examples.app.hello.HelloAutoConfiguration
info.ejava.examples.app.hello.HelloResourceAutoConfigurationwith hello.properties present
@Bean factory from HelloAutoConfiguration skipped — bean already exists
bean created using HelloResourceAutoConfiguration @Bean factory — evaluated before HelloAutoConfiguration
$ touch hello.properties
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar
...
hello.properties exists says hello World
when property file is not present:
@Bean factory from HelloAutoConfiguration used since neither property nor resource-based conditions satisfied
$ rm hello.properties
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar
...
application.properties Says - Hey Worldfamiliar situation — ambiguous match
if we supply a hello.properties file and hello.quiet=true property value
$ touch hello.properties
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar --hello.quiet=true
...
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in info.ejava.examples.app.config.auto.AppCommand required a single bean,
but 2 were found:
- quietHello: defined by method 'quietHello' in info.ejava.examples.app.config.auto.StarterConfiguredApp
- resourceHello: defined by method 'resourceHello' in class path resource
[info/ejava/examples/app/hello/HelloResourceAutoConfiguration.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans,
or using @Qualifier to identify the bean that should be consumedthis time — to correct — we add the @Primary annotation to our highest priority @Bean factory
if there is a conflict — this one will be used
...
import org.springframework.context.annotation.Primary;
@AutoConfiguration(before = HelloAutoConfiguration.class)
@ConditionalOnResource(resources = "file:./hello.properties")
public class HelloResourceAutoConfiguration {
@Bean
@Primary //chosen when there is a conflict
public Hello resourceHello() {
return new StdOutHello("hello.properties exists says hello");
}
}avoided conflict error with one of the @Bean factories listed as @Primary
$ touch hello.properties
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar --hello.quiet=true (1)
...
hello.properties exists says hello World
| 1 | @Primary condition satisfied overrides application @Bean condition |
important difference between conditions applied to @Configuration class or methods
class conditional annotations prevent entire class from loading when not satisfied
@Bean factory conditional annotations allow class to load but prevent method from
being called when not satisfied
this works for missing classes too!
Spring Boot parses conditional class using ASM to detect and evaluate conditions before allowing class to be loaded into JVM
otherwise we would get ClassNotFoundException for the import of class we are trying
to base condition on
adding
@ConditionalOnClass
annotation to prevent @Configuration class from being loaded if implementation
class does not exist on classpath
...
import info.ejava.examples.app.hello.stdout.StdOutHello; (2)
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(StdOutHello.class) (2)
@EnableConfigurationProperties(HelloProperties.class)
public class HelloAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public Hello hello(HelloProperties helloProperties) {
return new StdOutHello(helloProperties.getGreeting()); (1)
}
}
| 1 | StdOutHello is the implementation instantiated by the @Bean factory method |
| 2 | HelloAutoConfiguration.class will not get loaded if StdOutHello.class does not exist |
@ConditionOnClass accepts either class or string expression of fully qualified classname
@ConditionalOnMissingClass accepts only string form of classname
| Spring Boot Autoconfigure module contains many examples of real Auto-configuration classes |
We can turn off certain Auto-configured classes using the
exclude attribute of the @EnableAutoConfiguration annotation
exclude attribute of the @SpringBootApplication annotation which wraps the @EnableAutoConfiguration annotation
@SpringBootApplication(exclude = {})
// ==> wraps @EnableAutoConfiguration(exclude={})
public class StarterConfiguredApp {
...
}many conditional User-defined and Auto-configurations going on
easy to get lost or make a mistake
two primary tools can expose details of conditional configuration decisions
Conditions Evaluation Report
Spring Boot Actuator
simplistic textual report of positive and negative condition evaluation matches
add a debug property to the configuration
--debug or -Ddebug to the command line
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar --debug | less
...
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches: (1)
-----------------
HelloAutoConfiguration matched:
- @ConditionalOnClass found required class 'info.ejava.examples.app.hello.stdout.StdOutHello' (OnClassCondition)
HelloAutoConfiguration#hello matched:
- @ConditionalOnMissingBean (types: info.ejava.examples.app.hello.Hello; SearchStrategy: all) did not find any beans (OnBeanCondition)
Negative matches: (2)
-----------------
HelloResourceAutoConfiguration:
Did not match:
- @ConditionalOnResource did not find resource 'file:./hello.properties' (OnResourceCondition)
Matched:
- @ConditionalOnClass found required class 'info.ejava.examples.app.hello.stdout.StdOutHello' (OnClassCondition)
StarterConfiguredApp#quietHello:
Did not match:
- @ConditionalOnProperty (hello.quiet=true) did not find property 'quiet' (OnPropertyCondition)
| 1 | Positive matches show which conditionals are activated and why |
| 2 | Negative matches show which conditionals are not activated and why |
The report shows us that
HelloAutoConfiguration class was enabled because StdOutHello class was present
hello @Bean factory method of HelloAutoConfiguration class was enabled because no other
beans were located
entire HelloResourceAutoConfiguration class was not loaded because file hello.properties
was not present
quietHello @Bean factory method of application class was not activated because
hello.quiet property was not found
can also look at conditionals while Web applications are running using the Spring Boot Actuator
requires example transitioned from a command to a Web application
can be done technically by simply changing our starter in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- <artifactId>spring-boot-starter</artifactId>-->
</dependency>
also need to add a dependency on the spring-boot-starter-actuator module
<!-- added to inspect env -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>Actuator, by default, will not expose any information without being configured to do so
can show a JSON version of the Conditions Evaluation Report by adding
management.endpoints.web.exposure.include equal to value “conditions”
performed here using command line
could be in a profile-specific properties file appropriate for exposing this information
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar \
--management.endpoints.web.exposure.include=conditions
report available at: http://localhost:8080/actuator/conditions
{
"contexts": {
"application": {
"positiveMatches": {
"HelloAutoConfiguration": [{
"condition": "OnClassCondition",
"message": "@ConditionalOnClass found required class 'info.ejava.examples.app.hello.stdout.StdOutHello'"
}],
"HelloAutoConfiguration#hello": [{
"condition": "OnBeanCondition",
"message": "@ConditionalOnBean (types: info.ejava.examples.app.hello.Hello; SearchStrategy: all) did not find any beans"
}],
...
,
"negativeMatches": {
"StarterConfiguredApp#quietHello": {
"notMatched": [{
"condition": "OnPropertyCondition",
"message": "@ConditionalOnProperty (hello.quiet=true) did not find property 'quiet'"
}],
"matched": []
},
"HelloResourceAutoConfiguration": {
"notMatched": [{
"condition": "OnResourceCondition",
"message": "@ConditionalOnResource did not find resource 'file:./hello.properties'"
}],
"matched": []
},
...also helpful to inspect the environment
determine value of properties
determine which source of properties is being used
add env to the exposure.include property to see information
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar \
--management.endpoints.web.exposure.include=conditions,envadds new endpoints to see property information
full /env endpoint
specific /env/{property} endpoint for a specific property name
links available at http://localhost:8080/actuator
{
_links: {
self: {
href: "http://localhost:8080/actuator",
templated: false
},
conditions: {
href: "http://localhost:8080/actuator/conditions",
templated: false
},
env: {
href: "http://localhost:8080/actuator/env",
templated: false
},
env-toMatch: {
href: "http://localhost:8080/actuator/env/{toMatch}",
templated: true
}
}
}available at http://localhost:8080/actuator/env
{
activeProfiles: [ ],
propertySources: [{
name: "server.ports",
properties: {
local.server.port: {
value: 8080
}
}
},
{
name: "commandLineArgs",
properties: {
management.endpoints.web.exposure.include: {
value: "conditions,env"
}
}
},
...source of specific property and its defined value
available below the /actuator/env URI
{
property: {
source: "applicationConfig: [classpath:/application.properties]",
value: "application.properties Says - Hey"
},
...can explore some of the other Actuator endpoints by
changing the include property to *
revisiting the main actuator endpoint
Actuator Documentation is available on the web
$ java -jar target/appconfig-autoconfig-*-SNAPSHOT-bootexec.jar \
--management.endpoints.web.exposure.include="*" (1)
| 1 | double quotes ("") being used to escape * special character on command line |
In this module we:
Defined conditions for @Configuration classes and @Bean factory methods that
are evaluated at runtime startup
Placed User-defined conditions, which are evaluated first, in with application module
Placed Auto-configuration classes in separate starter module to automatically
bootstrap applications with specific capabilities
Added conflict resolution and ordering to conditions to avoid ambiguous matches
Discovered how class conditions can help prevent entire @Configuration classes from
being loaded and disrupt the application because an optional class is missing
Learned how to debug conditions and visualize the runtime environment through use of
the debug property or by using the Actuator for web applications