Describe @ConditionalOnWebApplication, @ConditionalOnResource, and @ConditionalOnExpression — what each checks and a use case.
answer
- OnWebApplication -> SERVLET / REACTIVE / ANY (+ OnNotWebApplication)
- OnResource -> classpath:/file: presence, AND-ed
- OnExpression -> SpEL true, compound logic
- all evaluate at refresh
- prefer most specific condition
basics
~20 s@ConditionalOnWebApplication matches when the app is a web app (servlet or reactive). @ConditionalOnResource matches when a classpath resource exists. @ConditionalOnExpression matches when a SpEL expression evaluates to true. Each gates beans/config on a different signal.
solid answer
~40 sThese three cover less common but useful signals. @ConditionalOnWebApplication matches when the context is a web application, and its type attribute lets you require SERVLET, REACTIVE, or ANY — with a paired @ConditionalOnNotWebApplication for the inverse; Boot uses it so web-only beans (filters, MVC config) don't load in a plain app. @ConditionalOnResource matches when a resource (e.g. classpath:schema.sql or file:) is present, using Spring's resource loading — handy for optional config files. @ConditionalOnExpression evaluates a SpEL expression against the Environment/context and matches on true, giving you compound or computed conditions that the simpler property/class conditions can't express, e.g. combining two properties. Like all conditions, they're evaluated at context refresh, and SpEL adds flexibility at the cost of readability and eager evaluation.
code
java · 18 lines@Configuration(proxyBeanMethods = false)
public class SignalConditions {
// Only in a servlet web app
@Bean
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
Filter requestLoggingFilter() { return new RequestLoggingFilter(); }
// Only if an optional resource is on the classpath
@Bean
@ConditionalOnResource(resources = "classpath:custom-mappings.xml")
MappingLoader mappingLoader() { return new MappingLoader(); }
// Compound flag logic via SpEL (defaults avoid missing-placeholder errors)
@Bean
@ConditionalOnExpression("${feature.a:false} and ${feature.b:false}")
ComboFeature comboFeature() { return new ComboFeature(); }
}go deeper
Know each one's trigger: web app, resource presence, SpEL true.
Explain the SERVLET/REACTIVE/ANY types and choosing OnExpression only for compound logic.
Discuss refresh-time evaluation limits, placeholder defaults, and preferring the most specific condition.
Reason about when SpEL bean references are unsafe and how these guard web-vs-non-web auto-config.
## @ConditionalOnWebApplication (and @ConditionalOnNotWebApplication) Matches when the running `ApplicationContext` is a **web application context**. - **`type` attribute**: `Type.SERVLET` (only servlet-based, `WebApplicationContext`), `Type.REACTIVE` (only `ReactiveWebApplicationContext`, i.e. WebFlux), or `Type.ANY` (default — either). - Its inverse is **`@ConditionalOnNotWebApplication`**, matching a non-web (e.g. batch/CLI) context. - **Why Boot uses it:** web-specific beans — `DispatcherServlet` config, `Filter`s, error pages, `WebMvcAutoConfiguration` — must not load in a plain `main`-method or batch app. It's the guard that keeps a non-web app from dragging in web infrastructure. - **Use case:** in your own auto-config, register a servlet `Filter` only under `@ConditionalOnWebApplication(type = Type.SERVLET)`. ## @ConditionalOnResource Matches when the specified **resource(s)** exist, resolved through Spring's `ResourceLoader`. - **`resources` attribute** takes Spring resource locations: `classpath:...`, `file:...`, plain paths. - Multiple resources are **AND**-ed (all must exist). - **Use case:** activate config only if an optional file is present — e.g. `@ConditionalOnResource(resources = "classpath:custom-mappings.xml")` to load extra mappings when a team drops the file in. - **Gotcha:** it's a presence check at refresh time; it does not read or validate the content. ## @ConditionalOnExpression Matches when a **SpEL (Spring Expression Language)** expression evaluates to `true`. - **Use case:** compound logic the simple conditions can't do, e.g. `@ConditionalOnExpression("${feature.a:false} and ${feature.b:false}")` (both flags on), or comparisons/OR combinations of properties. - Expressions can reference the `Environment` via `${...}` property placeholders and beans via `@beanName` (though referencing beans this early is risky — they may not exist yet). - **Gotchas:** - **Evaluated at refresh**, before most beans exist — keep expressions to properties, not bean state. - **Readability & type-safety** suffer versus `@ConditionalOnProperty`; use it only when you genuinely need combined/computed logic. - A missing placeholder without a default throws — always supply defaults like `${x:false}`. ## Common thread All are members of `org.springframework.boot.autoconfigure.condition`, all evaluate **once at context refresh**, and all can annotate a `@Bean` method or `@Configuration` class. Choose the **most specific** condition: prefer `@ConditionalOnProperty` for a single flag, reach for `@ConditionalOnExpression` only for compound logic, `@ConditionalOnResource` for file presence, and `@ConditionalOnWebApplication` for web-vs-not. ## When to use which - Web-only beans ⇒ `@ConditionalOnWebApplication(type=...)`. - Optional file-driven config ⇒ `@ConditionalOnResource`. - 'Two flags must both be on' / computed check ⇒ `@ConditionalOnExpression`.
- When would you pick @ConditionalOnExpression over @ConditionalOnProperty?When you need compound or computed logic a single property can't express — e.g. two flags that must both be true, an OR of properties, or a numeric comparison. For a single on/off flag, @ConditionalOnProperty is clearer and type-safer.
- What does the type attribute of @ConditionalOnWebApplication do?It narrows the match: SERVLET requires a servlet-based web context, REACTIVE requires a WebFlux reactive context, and ANY (default) matches either. This lets you register beans specific to one web stack.
saying these in an interview costs you the question
- Saying @ConditionalOnResource reads/validates file contents (it only checks presence)
- Claiming @ConditionalOnExpression can reliably inspect other beans' runtime state during evaluation
- Forgetting REACTIVE vs SERVLET distinction in @ConditionalOnWebApplication
- Using a placeholder in OnExpression without a default and expecting no error