Mock Full 03 — Spring Professional (60 Questions)
Exam style: Spring Professional Develop (2V0-72.22) — full 60-question mixed-topic mock.
Time limit: ~130 minutes (about 2 minutes per question).
Instructions:
- Pick an option for each question, then use Check answer to reveal the explanation and score.
- Use Back and Next to move through the set; you can change your selection until you check.
- For every miss, read the explanation and add one memory sentence before moving on.
Topic coverage:
- Q1–10: Spring Core & DI
- Q11–18: Configuration, Profiles & Scopes
- Q19–28: Spring Boot, Auto-Configuration & Actuator
- Q29–36: Spring MVC, REST & Validation
- Q37–44: Data Access, JPA & Transactions
- Q45–50: Spring Security
- Q51–56: Testing
- Q57–60: AOP, Events, Async & Observability
Question 1
A legacy monolith is being migrated to Spring. The team debates whether to bootstrap with BeanFactory or ApplicationContext.
Which capability is available in ApplicationContext but NOT in the basic BeanFactory contract?
- A) Registering singleton and prototype bean definitions programmatically
- B) Publishing application events to registered listeners
- C) Resolving bean dependencies through constructor injection
- D) Looking up beans by name at runtime
Answer & explanation
Correct answer: B
ApplicationContext extends BeanFactory and adds enterprise-oriented features such as event publication, internationalization, resource loading patterns, and automatic BeanPostProcessor registration. BeanFactory supports core DI mechanics including lookup and dependency resolution, but it does not publish ApplicationEvent objects to ApplicationListener beans. On the exam, "enterprise features" almost always points to events, i18n, or AOP auto-registration through the context.
Why the other options are wrong:
- BeanFactory can register definitions and manage singleton/prototype scopes through BeanDefinition APIs.
- Constructor injection is a core IoC feature supported by both BeanFactory and ApplicationContext.
- getBean() style lookup is fundamental BeanFactory behavior, not an ApplicationContext-only feature.
Memory sentence: "ApplicationContext = BeanFactory plus events, i18n, and richer lifecycle integration."
Study: Book chapter
Question 2
PaymentService has two NotificationSender implementations on the classpath: EmailNotificationSender and SmsNotificationSender.
Which approach most cleanly injects the SMS implementation into PaymentService without renaming beans or removing the email bean?
- A) Annotate SmsNotificationSender with @Primary and inject NotificationSender without a qualifier
- B) Annotate the PaymentService constructor parameter with @Qualifier("smsNotificationSender")
- C) Mark EmailNotificationSender with @Lazy so Spring prefers the eager SMS bean
- D) Use @Resource on the field; Spring always chooses the bean whose name matches the field name
Answer & explanation
Correct answer: B
When multiple beans implement the same type, @Qualifier disambiguates by bean name (default name for @Component SmsNotificationSender is smsNotificationSender). @Primary solves the same problem globally but changes default resolution for every injection point, which is broader than needed. Constructor injection with @Qualifier is explicit, test-friendly, and a common exam trap versus @Primary overuse.
Why the other options are wrong:
- @Primary works but applies context-wide; the question asks for the cleanest targeted choice, which is @Qualifier on the injection point.
- @Lazy only delays initialization; it does not select among multiple candidates of the same type.
- @Resource uses name-based lookup and does not guarantee selection by field name unless configured correctly; it is not "always" SMS.
Memory sentence: "Multiple implementations of one type: @Qualifier at the injection point beats global @Primary."
Study: Book chapter
Question 3
Assuming component scanning picks up both classes, how many Clock beans exist and how is AuditTrail wired?
@Component
public class AuditTrail {
private final Clock clock;
public AuditTrail(Clock clock) { this.clock = clock; }
}
@Configuration
public class TimeConfig {
@Bean
public Clock systemClock() { return Clock.systemUTC(); }
}
- A) One Clock bean from TimeConfig; constructor injection satisfies AuditTrail
- B) Two Clock beans; startup fails with NoUniqueBeanDefinitionException
- C) Zero Clock beans; AuditTrail is created with clock = null
- D) One Clock bean created implicitly because @Component classes always get a Clock
Answer & explanation
Correct answer: A
A @Bean method in @Configuration registers an explicit singleton Clock. AuditTrail declares a constructor dependency on Clock; Spring autowires the single matching bean. No implicit Clock is created unless another @Bean or @Component implements or exposes Clock. The trap is assuming @Component magically creates dependencies.
Why the other options are wrong:
- A second Clock would require another @Bean or component implementing Clock; only systemClock() is defined.
- Spring does not silently null-out required constructor dependencies when a unique bean exists.
- @Component does not auto-provision dependencies; it only registers AuditTrail itself.
Memory sentence: "A single matching @Bean satisfies constructor injection for that type."
Study: Book chapter
Question 4
OrderFacade depends on PricingService, which depends on DiscountPolicy, which depends on OrderFacade for tenant context.
The application fails at startup with a circular dependency error. Both OrderFacade and PricingService use constructor injection. What is the Spring-recommended structural fix?
- A) Enable spring.main.allow-circular-references=true in application.properties
- B) Add @Lazy on one constructor parameter to break the cycle during creation
- C) Switch all three classes to field injection with @Autowired
- D) Refactor so the shared dependency is extracted or injected via an interface indirection such as ObjectProvider or event-driven lookup
Answer & explanation
Correct answer: D
Constructor injection cycles cannot be satisfied without redesign because each bean needs the other fully constructed. @Lazy on a constructor parameter can defer one proxy edge case but is a tactical workaround, not the recommended design fix. Extracting the shared concern, using ObjectProvider, or decoupling through events removes the structural cycle. Field/setter injection "works" but hides design problems and is discouraged.
Why the other options are wrong:
- allow-circular-references is a Boot escape hatch, not the recommended design solution on the exam.
- @Lazy may postpone one dependency but does not fix underlying bidirectional design; exam answers favor structural decoupling.
- Field injection avoids the constructor cycle error but violates recommended practice and still signals poor boundaries.
Memory sentence: "Constructor cycles need design decoupling, not hidden injection tricks."
Study: Book chapter
Question 5
No MetricsExporter bean is registered in the context. What happens when ReportService is created and publish() is called?
@Service
public class ReportService {
@Autowired(required = false)
private MetricsExporter metricsExporter;
public void publish() {
if (metricsExporter != null) {
metricsExporter.flush();
}
}
}
- A) Context refresh fails because @Autowired defaults to required=true
- B) ReportService is created; metricsExporter is null; publish() runs without calling flush()
- C) Spring creates a no-op MetricsExporter proxy automatically
- D) ReportService bean is skipped entirely and never instantiated
Answer & explanation
Correct answer: B
required=false makes injection optional. If no bean matches, Spring injects null for object types instead of failing startup. The publish() guard prevents NullPointerException. This pattern suits optional integrations. The trap is confusing field @Autowired default (required=true) with the explicit required=false shown here.
Why the other options are wrong:
- required=false explicitly disables the fail-fast behavior for missing beans.
- Spring does not fabricate no-op implementations for missing optional dependencies.
- The service is still a managed bean; optional missing dependencies do not suppress bean creation.
Memory sentence: "@Autowired(required=false) means missing bean becomes null, not startup failure."
Study: Book chapter
Question 6
Which statement best describes Inversion of Control in Spring?
- A) Developers explicitly invoke framework callbacks to create objects in main()
- B) The container constructs objects, wires dependencies, and manages lifecycle; application code receives ready collaborators
- C) Spring generates bytecode for every class so getters and setters are unnecessary
- D) IoC applies only to @Controller classes participating in web request handling
Answer & explanation
Correct answer: B
IoC means object creation and dependency wiring are controlled by the container rather than by application code calling new and manual setter chains. Spring manages lifecycle callbacks, scopes, and proxying where configured. It is not limited to web controllers and does not eliminate the need for collaboration boundaries expressed through constructors or methods.
Why the other options are wrong:
- IoC moves creation out of main/application code; the container drives instantiation.
- Spring may use proxies and bytecode enhancement for AOP, but IoC is about object assembly, not eliminating accessors.
- IoC governs any Spring-managed bean, including @Service, @Repository, and @Configuration classes.
Memory sentence: "IoC = container builds and wires; your code consumes collaborators."
Study: Book chapter
Question 7
Without any @Qualifier, which CacheProvider is injected into CatalogService?
public interface CacheProvider {}
@Component
@Primary
class RedisCacheProvider implements CacheProvider {}
@Component
class CaffeineCacheProvider implements CacheProvider {}
@Service
class CatalogService {
private final CacheProvider cache;
CatalogService(CacheProvider cache) { this.cache = cache; }
}
- A) CaffeineCacheProvider because it appears later in the component scan
- B) Startup fails unless one implementation is removed from the classpath
- C) A JDK dynamic proxy merging both providers
- D) RedisCacheProvider because it is marked @Primary
Answer & explanation
Correct answer: D
@Primary marks a preferred bean when multiple candidates match a single injection point. RedisCacheProvider wins without @Qualifier. If no @Primary existed, Spring would throw NoUniqueBeanDefinitionException. Order of scanning does not determine preference.
Why the other options are wrong:
- Component scan order is not a disambiguation mechanism.
- Multiple beans are valid when @Primary or @Qualifier resolves ambiguity.
- Spring does not merge multiple concrete implementations into one proxy for plain interface injection.
Memory sentence: "@Primary breaks ties when several beans match the same type."
Study: Book chapter
Question 8
A security team requires immutable service dependencies and clear unit-test construction. Which injection style should you prefer?
- A) Constructor injection of final fields
- B) Field injection with @Autowired
- C) Setter injection for every dependency
- D) Lookup-method injection for all collaborators
Answer & explanation
Correct answer: A
Constructor injection enables immutable fields (final), makes required dependencies explicit, and allows plain new Service(mockDep) tests without Spring. Field injection hides dependencies and complicates testing. Setter injection suits optional dependencies but not as the default for required collaborators.
Why the other options are wrong:
- Field injection cannot enforce immutability and is harder to test in isolation.
- Setter injection is for optional or reconfigurable dependencies, not the default for required immutable wiring.
- Lookup-method injection solves scoped/prototype delegation problems, not general service wiring.
Memory sentence: "Prefer constructor injection for required, immutable, testable dependencies."
Study: Book chapter
Question 9
A class is declared as @Component("billingGateway") in package com.acme.payments. What is its default bean name if the explicit name were removed?
- A) com.acme.payments.BillingGateway
- B) billingGateway with lower camel case derived from the class name BillingGateway
- C) BillingGateway preserving exact class case
- D) payments.BillingGateway based on package suffix
Answer & explanation
Correct answer: B
For @Component without an explicit value, the default bean name is the decapitalized simple class name: BillingGateway becomes billingGateway. Fully qualified class names are not default bean names. Explicit @Component("billingGateway") simply sets the name directly.
Why the other options are wrong:
- Fully qualified names are not the default bean naming scheme for stereotype annotations.
- Default decapitalization lowercases only the first character; BillingGateway is not preserved as-is.
- Package suffixes are not appended to default bean names.
Memory sentence: "Default @Component name = decapitalized simple class name."
Study: Book chapter
Question 10
Beans in com.acme.billing.core are not discovered. What is the smallest fix?
@SpringBootApplication
public class BillingApp {
public static void main(String[] args) {
SpringApplication.run(BillingApp.class, args);
}
}
// Domain code lives in com.acme.billing.core
// BillingApp lives in com.acme.billing
- A) Move every class from core into com.acme.billing
- B) Add @SpringBootApplication(scanBasePackages = "com.acme.billing") or a broader shared root package
- C) Replace @SpringBootApplication with @EnableAutoConfiguration only
- D) Add @ComponentScan on each individual bean class in the core package
Answer & explanation
Correct answer: B
@SpringBootApplication composes @ComponentScan that defaults to the declaring class package (com.acme.billing) and below. Sibling package com.acme.billing.core is not scanned. Expanding scanBasePackages to a parent such as com.acme.billing (if structured under a shared root) or com.acme fixes discovery without moving classes. @SpringBootApplication on the main class in a parent package is the idiomatic Boot layout.
Why the other options are wrong:
- Moving all classes is unnecessary when scanBasePackages can include the core package tree.
- @EnableAutoConfiguration alone does not enable component scanning for @Service/@Component classes.
- Per-class @ComponentScan is noisy; one centralized scan configuration is preferred.
Memory sentence: "@SpringBootApplication scans its package and subpackages only unless scanBasePackages overrides."
Study: Book chapter
Question 11
In a @Configuration class processed by full @Configuration CGLIB enhancement, how many ObjectMapper instances back the two @Bean methods?
@Configuration
public class AppConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper().findAndRegisterModules();
}
@Bean
public JsonWriter jsonWriter() {
return new JsonWriter(objectMapper());
}
}
- A) Two, because each @Bean method call creates a fresh instance
- B) Zero; @Bean methods are not invoked during context refresh
- C) One; the intercepted @Bean method call returns the singleton from the container
- D) One only if @Scope("prototype") is added to objectMapper()
Answer & explanation
Correct answer: C
In @Configuration classes, @Bean method interceptions route calls through the container so objectMapper() invoked from jsonWriter() returns the registered singleton rather than calling new again. Without @Configuration enhancement (plain @Bean in a non-config class), direct calls would create separate instances. This is a classic certification trap.
Why the other options are wrong:
- Duplicate instances happen with @Bean lite mode or plain @Component classes, not full @Configuration.
- @Bean methods are definitely invoked to register factory-produced beans.
- Prototype scope would create multiple ObjectMapper instances; default singleton scope shares one.
Memory sentence: "@Configuration @Bean method calls are proxied to reuse container-managed singletons."
Study: Book chapter
Question 12
A multi-module billing service binds dozens of nested tariff properties from application.yml with relaxed binding. Which mechanism is most appropriate?
- A) @ConfigurationProperties on a typed properties class enabled via @EnableConfigurationProperties
- B) Individual @Value("${billing.tariff.peak.rate}") fields scattered across services
- C) Environment.getProperty() manual parsing inside @PostConstruct methods only
- D) @PropertySource on the main class without a binding object
Answer & explanation
Correct answer: A
@ConfigurationProperties groups hierarchical configuration into one validated type, supports relaxed binding (billing.tariff.peak-rate maps to peakRate), and keeps services free of property key strings. @Value is fine for a few keys but scales poorly for nested structures. Manual Environment parsing duplicates framework functionality.
Why the other options are wrong:
- @Value per field becomes brittle for nested trees and obscures the configuration model.
- Environment alone lacks structured binding and validation integration at scale.
- @PropertySource loads a file but does not bind nested structures without @ConfigurationProperties or @Value.
Memory sentence: "Large structured config trees belong in @ConfigurationProperties, not scattered @Value."
Study: Book chapter
Question 13
A bean is annotated @Profile("!prod"). In which Environment is the bean registered?
- A) Only when the prod profile is active
- B) Never; negated profiles are invalid in Spring
- C) Whenever the active profiles do NOT include prod
- D) Only in the default profile with no explicit spring.profiles.active
Answer & explanation
Correct answer: C
Profile expressions support negation. @Profile("!prod") registers the bean when prod is not among active profiles, including dev, test, or multiple others. It is not limited to the default profile only; any non-prod activation qualifies.
Why the other options are wrong:
- That would be @Profile("prod"), not the negated form.
- Negated profiles are valid first-class profile expressions.
- Non-prod includes explicit dev/test profiles, not only the implicit default.
Memory sentence: "@Profile("!prod") means register when prod is not active."
Study: Book chapter
Question 14
CorrelationService is a singleton. How many distinct RequestIdGenerator instances does it hold over the application lifetime?
@Component
@Scope("prototype")
class RequestIdGenerator {
private final String id = UUID.randomUUID().toString();
String getId() { return id; }
}
@Service
class CorrelationService {
private final RequestIdGenerator generator;
CorrelationService(RequestIdGenerator g) { this.generator = g; }
}
- A) A new prototype instance on every method call into CorrelationService
- B) Exactly one prototype instance injected at CorrelationService creation time
- C) Zero; prototype beans cannot be injected into singletons
- D) One per HTTP request automatically without extra configuration
Answer & explanation
Correct answer: B
Injecting a prototype into a singleton resolves the prototype once when the singleton is created, then reuses that same reference. The singleton does not automatically receive a fresh prototype per method call or request. For per-request freshness with a singleton consumer, use ObjectProvider, scoped proxy, or lookup method injection.
Why the other options are wrong:
- Prototype freshness on each call requires ObjectProvider/getObject() or similar, not plain constructor injection.
- Injection is allowed but captures one instance at singleton creation time.
- Per-request behavior requires web scopes or scoped proxies, not default prototype injection alone.
Memory sentence: "Prototype into singleton = one prototype captured at singleton birth, not ongoing refresh."
Study: Book chapter
Question 15
A developer adds @Scope("request") to a bean in a non-web integration test using only @SpringBootTest with NONE web environment. What is the likely outcome?
- A) Spring silently falls back to singleton scope
- B) The bean is created once per test class
- C) The bean is created once per JVM
- D) Context initialization fails because request scope requires a web-aware context
Answer & explanation
Correct answer: D
Request and session scopes depend on web-aware lifecycle infrastructure (RequestContextListener, DispatcherServlet, etc.). In a non-web ApplicationContext, registering a request-scoped bean without a scoped proxy or test web environment commonly fails at startup. Spring does not transparently downgrade request scope to singleton.
Why the other options are wrong:
- Spring does not automatically remap request scope to singleton in non-web contexts.
- Per-test-class behavior is not how request scope works; it needs an active request.
- Request scope is not JVM-wide singleton semantics.
Memory sentence: "request/session scopes need a web-aware context or scoped-proxy strategy."
Study: Book chapter
Question 16
A bean implements both @PostConstruct cleanup setup and InitializingBean.afterPropertiesSet(). In what order are they invoked after property injection?
- A) @PostConstruct first, then afterPropertiesSet(), then custom init-method if declared
- B) afterPropertiesSet() first, then @PostConstruct
- C) Only the mechanism declared earliest in the class file runs
- D) They run concurrently on separate threads
Answer & explanation
Correct answer: A
Standard initialization order: constructor, dependency injection, @PostConstruct, InitializingBean.afterPropertiesSet(), custom init-method, then bean is ready. Knowing this sequence matters when both JSR-250 and Spring lifecycle interfaces are present.
Why the other options are wrong:
- InitializingBean runs after @PostConstruct, not before.
- Both callbacks run when both are present; file order is irrelevant.
- Initialization is synchronous on the creating thread.
Memory sentence: "Init order: inject, then @PostConstruct, then InitializingBean, then init-method."
Study: Book chapter
Question 17
When is shutdown() invoked on the ConnectionPool bean?
@Bean(destroyMethod = "shutdown")
public ConnectionPool connectionPool() {
return new ConnectionPool();
}
- A) Immediately after the @Bean method returns during context refresh
- B) Only if the JVM receives SIGTERM, never on graceful context close
- C) During container shutdown when the singleton is destroyed
- D) Before dependency injection into dependent beans
Answer & explanation
Correct answer: C
destroyMethod registers a custom destroy callback executed when the application context closes and singleton beans are disposed. It is not called right after factory method return. Spring also infers destroy methods named close or shutdown by default unless disabled.
Why the other options are wrong:
- Factory method return begins bean life; destroy runs at context shutdown.
- Graceful context close triggers destroy callbacks, not only OS signals.
- Destroy phase happens after the bean has served its lifecycle, not before injection.
Memory sentence: "destroyMethod runs on context close, not when the @Bean method finishes."
Study: Book chapter
Question 18
The same property ship.timeout is defined in application.properties, an OS environment variable SHIP_TIMEOUT, and a command-line argument --ship.timeout=90. Which value wins with default Spring Boot precedence?
- A) application.properties because files load last
- B) Command-line arguments override environment variables and property files
- C) OS environment variables always beat command-line arguments in Boot 3
- D) The lowest numeric value among sources is chosen automatically
Answer & explanation
Correct answer: B
Spring Boot externalized configuration follows a defined precedence chain where command-line arguments rank above OS environment variables, which rank above application.properties among defaults. Later higher-precedence sources override lower ones for the same property.
Why the other options are wrong:
- Property files are lower precedence than environment and command-line in the default chain.
- Environment variables beat files but not command-line arguments.
- Spring does not pick values by numeric comparison across sources.
Memory sentence: "Boot precedence highlight: command line beats environment beats application.properties."
Study: Book chapter
Question 19
Why might a team exclude these auto-configuration classes in a batch worker with no database?
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
})
public class BatchWorkerApp { }
- A) To prevent Boot from configuring DataSource and JPA infrastructure when no database is intended
- B) To disable component scanning for @Repository beans only
- C) To turn off actuator endpoints automatically
- D) Because @SpringBootApplication cannot compose @EnableAutoConfiguration otherwise
Answer & explanation
Correct answer: A
Auto-configuration backs off when classpath conditions fail, but if JDBC/JPA libraries are present for other reasons Boot may still configure a DataSource. Explicit exclude prevents unwanted infrastructure and failed DataSource creation when no DB URL exists. It does not disable scanning or actuator by itself.
Why the other options are wrong:
- Excluding auto-config does not selectively disable @Repository scanning.
- Actuator exposure is controlled by management endpoints properties, not these exclusions.
- @SpringBootApplication already includes @EnableAutoConfiguration; exclude refines it.
Memory sentence: "Use exclude on @SpringBootApplication to veto specific auto-config classes explicitly."
Study: Book chapter
Question 20
A custom MetricsRegistry @Bean is declared in user configuration. An auto-configuration class is annotated @ConditionalOnMissingBean(MetricsRegistry.class). What happens?
- A) Both beans are registered and @Primary resolves ambiguity
- B) Auto-configuration always wins because it loads first
- C) The user-defined MetricsRegistry prevents the auto-configured default from registering
- D) Context fails with duplicate bean definitions
Answer & explanation
Correct answer: C
@ConditionalOnMissingBean is a back-off rule: if the context already contains a MetricsRegistry bean (usually from user config), the auto-configured default is skipped. This is the extension point pattern across Boot starters.
Why the other options are wrong:
- Back-off avoids duplicate beans; it does not create two defaults.
- User beans commonly register in the same refresh phase; missing-bean condition evaluates against existing definitions.
- Duplicate failure would occur without the condition; the condition prevents it.
Memory sentence: "@ConditionalOnMissingBean = skip auto-config default when user bean exists."
Study: Book chapter
Question 21
In Spring Boot 3, where are auto-configuration classes primarily registered for discovery?
- A) META-INF/spring.factories only
- B) META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
- C) application.yml under spring.auto-config.imports
- D) META-INF/beans.xml
Answer & explanation
Correct answer: B
Boot 3 moved auto-configuration registration to META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. spring.factories remains for some legacy extension hooks but auto-config listing migrated. This distinction frequently appears on exams comparing Boot 2 and 3.
Why the other options are wrong:
- spring.factories was the Boot 2 location for EnableAutoConfiguration listing.
- Auto-config class lists are not declared in application.yml.
- beans.xml is legacy Spring XML configuration, not Boot auto-config discovery.
Memory sentence: "Boot 3 auto-config imports file lives under META-INF/spring/...AutoConfiguration.imports."
Study: Book chapter
Question 22
Compared to @SpringBootApplication on the same class, what is missing from this composition?
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages = "com.acme.api")
public class ApiApplication { }
- A) Nothing; it is functionally identical in all Boot versions
- B) Only @EnableAutoConfiguration is missing
- C) Only @ComponentScan is missing
- D) The meta-annotation also applies @EnableAutoConfigurationConfiguration alignment and default scan anchoring tied to the declaring class unless redefined
Answer & explanation
Correct answer: D
@SpringBootApplication combines @SpringBootConfiguration, @EnableAutoConfiguration, and @ComponentScan with default scan anchored on the declaring class package. The shown code customizes scan base but omits @SpringBootConfiguration semantics used for configuration class role in Boot apps. Exams test knowing the three composed concerns even when manually rebuilt.
Why the other options are wrong:
- Manual composition can differ in defaults like @SpringBootConfiguration and scan anchoring.
- EnableAutoConfiguration is present in the snippet.
- ComponentScan is explicitly present with custom packages.
Memory sentence: "@SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan."
Study: Book chapter
Question 23
With spring-boot-starter-actuator on the classpath and no custom exposure settings, which endpoint is exposed over HTTP by default in modern Spring Boot?
- A) Only /actuator/health (and /actuator/info in some versions with defaults)
- B) All endpoints including env, beans, and shutdown
- C) No actuator endpoints over HTTP until management.endpoints.web.exposure.include is set
- D) Only /actuator/prometheus
Answer & explanation
Correct answer: A
By default Boot exposes a minimal web subset for security. health is the canonical always-exposed endpoint; info may also be exposed depending on version defaults. env, beans, and shutdown require explicit exposure configuration.
Why the other options are wrong:
- Exposing everything by default would be a security risk; Boot limits HTTP exposure.
- Some endpoints are exposed without custom include properties.
- Prometheus export requires micrometer registry and explicit exposure configuration.
Memory sentence: "Default HTTP actuator exposure is minimal; health is the key remembered endpoint."
Study: Book chapter
Question 24
Both ApplicationRunner and CommandLineRunner beans are registered. How does Spring invoke them relative to each other during startup?
- A) Only CommandLineRunner executes; ApplicationRunner is deprecated
- B) They are never invoked after context refresh completes
- C) All ApplicationRunner beans run before CommandLineRunner beans, each group ordered by @Order or Ordered
- D) They run interleaved alphabetically by bean name only
Answer & explanation
Correct answer: C
After context refresh, Spring Boot calls ApplicationRunner callbacks, then CommandLineRunner callbacks. Within each type, @Order/Ordered controls sequencing. Both receive control after the context is ready but before the application is considered fully started.
Why the other options are wrong:
- ApplicationRunner is fully supported and runs in the first runner phase.
- Both runner types execute after refresh; that is their purpose.
- Ordering is by @Order within runner type, not alphabetical bean names.
Memory sentence: "Startup runners: ApplicationRunner phase first, then CommandLineRunner."
Study: Book chapter
Question 25
What is the main effect of this Boot property in a large web application?
spring:
main:
lazy-initialization: true
- A) Beans are created only when first requested, delaying startup work at the cost of later latency on first use
- B) All @Controller mappings are disabled until a warmup endpoint is called
- C) Auto-configuration is completely disabled
- D) Only @Repository beans become lazy; @Service beans stay eager
Answer & explanation
Correct answer: A
spring.main.lazy-initialization marks bean definitions lazy so the container creates them on first dependency resolution or explicit getBean, not at refresh time. This can speed apparent startup but shift work to first access. It applies broadly, not only to specific stereotypes.
Why the other options are wrong:
- Controllers remain registered; lazy init changes creation timing, not mapping registration itself.
- Auto-configuration still runs; beans it defines may be lazy-created.
- Lazy initialization is a global default behavior change, not stereotype-selective.
Memory sentence: "lazy-initialization=true trades faster refresh for first-touch bean creation delay."
Study: Book chapter
Question 26
An auto-configuration class carries @ConditionalOnClass(name = "org.flywaydb.core.Flyway"). The Flyway library is absent from the classpath. What happens?
- A) The auto-configuration still loads and fails at runtime on first migration
- B) Spring throws ClassNotFoundException during application class loading of the auto-config class
- C) The auto-configuration class is not applied because the class condition is false
- D) Spring downloads Flyway transitively at runtime
Answer & explanation
Correct answer: C
@ConditionalOnClass checks classpath presence using string names to avoid loading missing types. When Flyway is absent, the condition fails and the auto-configuration backs off without loading Flyway-dependent beans. This is how optional integrations stay off the classpath safely.
Why the other options are wrong:
- Back-off prevents creating Flyway beans when the library is missing.
- String-based class names avoid hard loading of absent types during condition evaluation.
- Spring does not resolve missing libraries at runtime automatically.
Memory sentence: "@ConditionalOnClass backs off entire auto-config when the named class is absent."
Study: Book chapter
Question 27
Developers add spring-boot-devtools to a local profile and notice the app restarts when classpath classes change.
Which statement about DevTools restart behavior is accurate?
dependencies {
developmentOnly 'org.springframework.boot:spring-boot-devtools'
}
- A) DevTools reloads only static resources; Java class changes always require a full JVM exit
- B) DevTools uses two classloaders so most classpath changes trigger a fast application context restart in development
- C) DevTools is active in production by default when the dependency is on the runtime classpath
- D) DevTools disables all auto-configuration to speed restarts
Answer & explanation
Correct answer: B
Spring Boot DevTools splits base and restart classloaders so code and resource changes trigger a quick context restart instead of a cold JVM boot. It is intended for development and should be optional or excluded from production packaging. It does not disable auto-configuration.
Why the other options are wrong:
- Java class changes are exactly what the restart classloader model is designed to pick up quickly.
- DevTools should not ship to production; use developmentOnly or optional scope.
- Auto-configuration still runs after a DevTools restart.
Memory sentence: "DevTools = fast context restart via dual classloaders in development."
Study: Book chapter
Question 28
Which HTTP paths become available under the default base path with this configuration?
management:
endpoints:
web:
exposure:
include: health,metrics,beans
- A) Only /health, /metrics, and /beans at the server root
- B) /actuator/health, /actuator/metrics, and /actuator/beans
- C) /management/health and related management paths
- D) All actuator endpoints regardless of the include list
Answer & explanation
Correct answer: B
Web exposure include whitelists actuator endpoints under the configurable base path, default /actuator. Thus health, metrics, and beans are served at /actuator/health, /actuator/metrics, and /actuator/beans. The include list restricts endpoints; it does not expose everything.
Why the other options are wrong:
- Actuator endpoints are not mounted at the server root by default.
- management is not the default base path segment.
- include is a whitelist, not an implicit expose-all setting.
Memory sentence: "Default actuator base path is /actuator plus endpoint id."
Study: Book chapter
Question 29
A client sends GET /api/v1/invoices/42 with Accept: application/xml. What is the typical outcome?
@RestController
@RequestMapping("/api/v1/invoices")
public class InvoiceController {
@GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public InvoiceDto get(@PathVariable Long id) { ... }
}
- A) 200 response with JSON body because produces restricts the handler to JSON
- B) 406 Not Acceptable if no converter can satisfy application/xml for this handler
- C) 200 with XML because @RestController ignores produces
- D) 404 Not Found because Accept header does not match
Answer & explanation
Correct answer: B
produces narrows content types a handler can generate. With only application/json and an Accept: application/xml request, content negotiation fails to find a compatible converter and Spring MVC responds with 406 Not Acceptable unless a broader produces or additional converter exists.
Why the other options are wrong:
- JSON is returned when negotiation selects JSON; xml Accept conflicts with json-only produces.
- @RestController respects produces on mapping methods.
- Mismatch in media type negotiation yields 406, not 404.
Memory sentence: "produces mismatch with Accept leads to 406, not silent format switching."
Study: Book chapter
Question 30
In the Spring MVC request flow, what is the primary responsibility of DispatcherServlet?
- A) Front controller that routes requests to handlers, applies converters, and renders responses through the MVC infrastructure
- B) Compile-time generation of @RequestMapping annotations
- C) Direct JDBC execution for @Repository controllers
- D) Manage JPA EntityManager lifecycle per request
Answer & explanation
Correct answer: A
DispatcherServlet is the front controller coordinating HandlerMapping, HandlerAdapter, argument resolvers, message converters, and view resolution (for REST, message converters write bodies). It does not execute SQL or manage JPA directly.
Why the other options are wrong:
- Mapping annotations are runtime metadata interpreted by HandlerMapping beans.
- Data access belongs to repositories and persistence layers, not DispatcherServlet.
- EntityManager lifecycle is handled by JPA provider and Spring transaction infrastructure.
Memory sentence: "DispatcherServlet orchestrates MVC request handling end to end."
Study: Book chapter
Question 31
A client calls GET /products/search?category=books&page=2. Which annotation binds category and page in a controller method?
- A) @PathVariable for both parameters
- B) @RequestHeader for both parameters
- C) @ModelAttribute only; query strings cannot bind to simple parameters
- D) @RequestParam for both parameters
Answer & explanation
Correct answer: D
Query string key-value pairs bind to method parameters with @RequestParam (category, page). @PathVariable binds URI template segments like /products/{id}. @RequestHeader reads HTTP headers.
Why the other options are wrong:
- @PathVariable maps URI template variables, not query parameters.
- Headers are not where category and page appear in this URL.
- Simple query parameters bind directly with @RequestParam without a form object.
Memory sentence: "Query string parameters use @RequestParam; URI segments use @PathVariable."
Study: Book chapter
Question 32
The client POSTs JSON with quantity=0. Validation is enabled with spring-boot-starter-validation. What happens before the method body executes?
public record CreateOrderRequest(
@NotBlank String sku,
@Min(1) int quantity
) {}
@PostMapping("/orders")
public ResponseEntity<OrderId> create(@Valid @RequestBody CreateOrderRequest body) {
...
}
- A) Method runs; quantity 0 is accepted because records skip validation
- B) 400 Bad Request via MethodArgumentNotValidException handled by default MVC exception handling
- C) 500 Internal Server Error from Hibernate
- D) 201 Created with a corrected quantity defaulted to 1
Answer & explanation
Correct answer: B
@Valid on @RequestBody triggers Bean Validation on the record fields. @Min(1) fails for quantity=0, causing MethodArgumentNotValidException typically translated to 400 by Spring MVC default exception handlers or a @ControllerAdvice.
Why the other options are wrong:
- Records are validated like other @RequestBody types when @Valid is present.
- Hibernate is unrelated to MVC request-body validation failures.
- Spring does not auto-correct invalid input to success responses.
Memory sentence: "@Valid @RequestBody failures surface as 400 MethodArgumentNotValidException."
Study: Book chapter
Question 33
Two @ControllerAdvice classes both define @ExceptionHandler for IllegalArgumentException. One is annotated @Order(Ordered.HIGHEST_PRECEDENCE) and the other has no order. Which handler runs first?
- A) The unordered advice always wins
- B) Both handlers run sequentially for the same exception
- C) The JVM chooses randomly to encourage loose coupling
- D) The @Order(Ordered.HIGHEST_PRECEDENCE) advice is consulted earlier in exception resolution
Answer & explanation
Correct answer: D
@ControllerAdvice beans participate in ordered exception resolution. Lower order values (higher precedence) are considered first when multiple handlers could apply. Only one handler typically resolves a given exception for a controller advice chain.
Why the other options are wrong:
- Order explicitly prioritizes advice; unordered defaults are lower precedence than HIGHEST_PRECEDENCE.
- A single exception is not handled repeatedly by multiple @ExceptionHandler methods for the same type in normal resolution.
- Resolution is deterministic based on order and proximity rules.
Memory sentence: "Lower @Order value on @ControllerAdvice means higher precedence for exception handling."
Study: Book chapter
Question 34
On successful deletion with no response body, which status and body does the client receive?
@DeleteMapping("/accounts/{id}")
public ResponseEntity<Void> closeAccount(@PathVariable Long id) {
accountService.close(id);
return ResponseEntity.noContent().build();
}
- A) 204 No Content with an empty body
- B) 200 OK with JSON {"status":"deleted"}
- C) 404 Not Found unless a body is provided
- D) 202 Accepted with Location header automatically added
Answer & explanation
Correct answer: A
ResponseEntity.noContent() sets HTTP 204 No Content, appropriate for successful DELETE with no representation body. This is idiomatic REST for delete success without payload.
Why the other options are wrong:
- No JSON body is produced by noContent().build().
- Successful delete returns 204 here, not 404.
- 202 Accepted is for asynchronous processing acceptance, not immediate successful delete.
Memory sentence: "Successful DELETE without payload: ResponseEntity.noContent() gives 204."
Study: Book chapter
Question 35
A REST client sends Accept: application/json, application/xml;q=0.9. The controller handler can produce both JSON and XML. Which determines the response format?
- A) Always JSON because @RestController implies JSON only
- B) The first declared @GetMapping method in the class
- C) Content negotiation using Accept header q-values and available HttpMessageConverter types
- D) The Content-Type request header exclusively
Answer & explanation
Correct answer: C
Spring MVC content negotiation selects an output media type compatible with Accept preferences and supported by registered converters (Jackson for JSON, JAXB/Jackson XML for XML). q-values express client preference. Content-Type primarily describes the request body, not response format selection.
Why the other options are wrong:
- @RestController uses message converters but can still produce multiple media types when configured.
- Method declaration order does not drive negotiation.
- Response format selection uses Accept and produces capabilities, not inbound Content-Type alone.
Memory sentence: "Response format comes from Accept negotiation plus converter support."
Study: Book chapter
Question 36
A form posts application/x-www-form-urlencoded fields to a @Controller method. Which annotation binds fields into a command object parameter?
- A) @RequestBody
- B) @RequestPart
- C) @ResponseBody
- D) @ModelAttribute
Answer & explanation
Correct answer: D
@ModelAttribute binds form fields and query parameters to object properties for non-JSON requests. @RequestBody is for message-converter bodies like JSON/XML. @RequestPart is for multipart parts.
Why the other options are wrong:
- @RequestBody expects converted message body (JSON/XML), not standard form encoding by default.
- @RequestPart targets multipart sections, not simple form posts.
- @ResponseBody serializes return values; it does not bind inbound form data.
Memory sentence: "HTML form and query binding to objects uses @ModelAttribute."
Study: Book chapter
Question 37
Why mark a read-only reporting method with @Transactional(readOnly = true)?
@Service
public class ReportService {
@Transactional(readOnly = true)
public List<Summary> summarize() {
return repo.findAll().stream().map(mapper::toSummary).toList();
}
}
- A) It is required or Spring Data repositories throw IllegalStateException
- B) It hints the transaction manager and JPA provider to avoid unnecessary dirty checks and flush, optimizing read paths
- C) It automatically adds database row-level shared locks for every select
- D) It routes queries to a writable replica datasource without extra configuration
Answer & explanation
Correct answer: B
readOnly=true is an optimization hint: Hibernate may skip dirty checking and flush, and some drivers optimize read-only transactions. It does not by itself route to replicas or add locks. Writes in a readOnly transaction may fail or behave inconsistently depending on provider.
Why the other options are wrong:
- Repositories do not universally require readOnly for queries.
- readOnly does not impose shared locks on all selects by default.
- Read replica routing requires explicit routing DataSource configuration.
Memory sentence: "readOnly=true optimizes read transactions; it is not magic replica routing."
Study: Book chapter
Question 38
Inside a single @Transactional method, a repository save() is called, then a query runs before the method ends. When are INSERT statements typically flushed to the database?
- A) Before the query if the persistence provider must synchronize persistence context state with the database to honor query visibility semantics
- B) Never until the JVM exits
- C) Only when @Modifying is present on the query
- D) Immediately at each save() call always, regardless of transaction boundaries
Answer & explanation
Correct answer: A
JPA may auto-flush before queries so in-memory changes are visible to query execution within the same persistence context. Flush timing depends on flush mode and provider; it is not deferred until JVM exit. save() does not always mean immediate SQL without flush.
Why the other options are wrong:
- Persistence context changes are flushed during transaction work, not at JVM shutdown.
- @Modifying affects update/delete queries, not basic flush-before-select behavior.
- Flush may batch writes; auto-flush before queries is common but not identical to per-save immediate commit.
Memory sentence: "JPA may auto-flush pending changes before running queries in the same transaction."
Study: Book chapter
Question 39
A Spring Data JPA repository declares @Modifying @Query("delete from Inventory i where i.expired = true"). What is required for correct execution?
- A) Only @Cacheable on the repository interface
- B) A surrounding @Transactional (or transactional service method) so the delete runs in a transaction and clearAutomatically semantics apply as configured
- C) @Async on the query method
- D) Manual EntityManager only; @Query delete is unsupported
Answer & explanation
Correct answer: B
@Modifying queries change database state and must run inside a transaction. Spring Data documentation requires @Transactional on the modifying method or calling service. clearAutomatically/flushing behavior also depends on transactional EntityManager state.
Why the other options are wrong:
- @Cacheable is unrelated to executing bulk DML queries.
- @Async does not replace transactional requirements for modifying queries.
- Spring Data fully supports @Modifying @Query delete operations.
Memory sentence: "@Modifying queries need an active transaction context."
Study: Book chapter
Question 40
The service runs in a single read-only transaction and sees 51 SQL statements for orders plus items. What is the best fix?
@Entity
public class Order {
@OneToMany(mappedBy = "order", fetch = FetchType.LAZY)
private List<LineItem> items;
}
// Service loads 50 orders then accesses order.getItems() for each
- A) Change all entities to FetchType.EAGER globally
- B) Add @Transactional(propagation = REQUIRES_NEW) on the accessor
- C) Use a fetch join or @EntityGraph in the query that loads orders
- D) Replace JPA with JDBC only
Answer & explanation
Correct answer: C
This is the classic N+1 select problem: one query for orders plus one per order for lazy items. Fetch join or @EntityGraph loads associations in the initial query within the transaction. Global EAGER causes other performance issues. REQUIRES_NEW does not batch-load associations.
Why the other options are wrong:
- Global EAGER often over-fetches and harms performance elsewhere.
- REQUIRES_NEW changes transaction boundaries, not association loading strategy.
- JPA is fine when fetching is tuned; JDBC is not the required exam answer.
Memory sentence: "N+1 fix in JPA: fetch join or @EntityGraph on the initial query."
Study: Book chapter
Question 41
Which derived query method signature correctly matches entities where lastName equals the parameter ignoring case?
- A) findByLastNameCaseInsensitive(String lastName)
- B) findByLastNameIgnoreCase(String lastName)
- C) findByLastNameLikeIgnoreCase(String lastName)
- D) findLastNameIgnoreCase(String lastName)
Answer & explanation
Correct answer: B
Spring Data JPA derived query keywords include IgnoreCase for case-insensitive equality on String properties. Correct order is findBy + Property + IgnoreCase. Like implies pattern matching, not simple equality.
Why the other options are wrong:
- CaseInsensitive is not the supported keyword; IgnoreCase is.
- LikeIgnoreCase targets pattern predicates, not plain equals ignoring case.
- findLastNameIgnoreCase omits the required By separator after find.
Memory sentence: "IgnoreCase is the Spring Data keyword for case-insensitive property matching."
Study: Book chapter
Question 42
publish() is called from a controller. Why might postEntry() run without a transactional boundary?
@Service
public class LedgerService {
@Transactional
private void postEntry() { ledgerRepo.save(entry); }
public void publish() { postEntry(); }
}
- A) @Transactional on private methods is ignored by Spring AOP proxy-based transaction management
- B) Private methods are always REQUIRES_NEW
- C) Controllers automatically suspend transactions
- D) ledgerRepo.save always starts its own required transaction so @Transactional is unnecessary
Answer & explanation
Correct answer: A
Spring applies @Transactional via proxies that intercept public methods on proxied beans. Self-invocation of private @Transactional methods bypasses the proxy, so no transaction advice runs. Fix by making the method public, moving transaction boundary to another bean, or using AspectJ weaving.
Why the other options are wrong:
- Private methods do not automatically become REQUIRES_NEW.
- Controllers do not inherently suspend service-layer transaction demarcation.
- Repository save participates in a transaction only if one exists or is configured with propagation; the private method issue remains.
Memory sentence: "@Transactional on private methods is not applied through standard Spring proxies."
Study: Book chapter
Question 43
A managed Shipment with two Parcel children is saved via repository.save(shipment). Later remove one parcel from the list and call save again. What happens to the removed parcel?
@Entity
public class Shipment {
@OneToMany(cascade = CascadeType.PERSIST, orphanRemoval = true)
private List<Parcel> parcels = new ArrayList<>();
}
- A) It remains in the database because cascade PERSIST does not handle deletes
- B) Only the Shipment row updates; Parcel rows are immutable
- C) orphanRemoval deletes the detached parcel row when the association is cleared and changes flush
- D) JPA throws UnsupportedOperationException for orphanRemoval with lists
Answer & explanation
Correct answer: C
orphanRemoval=true deletes child entities removed from the collection when the parent is managed and changes synchronize. CascadeType.PERSIST propagates persist to new children but orphanRemoval covers removal from the association. save triggers flush within the transaction.
Why the other options are wrong:
- orphanRemoval specifically addresses child removal from the collection.
- Parcel rows can be deleted through orphanRemoval semantics.
- orphanRemoval with @OneToMany lists is supported when properly managed.
Memory sentence: "orphanRemoval deletes children removed from the parent collection on flush."
Study: Book chapter
Question 44
When must you prefer saveAndFlush(entity) over save(entity) in Spring Data JPA?
- A) For every read-only query to improve caching
- B) Never; they are identical in all providers
- C) When subsequent logic in the same transaction must trigger SQL immediately so constraints or queries see persisted state
- D) Only when using MongoDB repositories
Answer & explanation
Correct answer: C
save may defer SQL until flush time. saveAndFlush forces immediate synchronization with the database within the current transaction, useful before dependent queries or constraint checks that require rows to exist now.
Why the other options are wrong:
- Read-only queries do not need save or flush.
- save can delay SQL; behaviors differ at flush timing.
- saveAndFlush is a JPA repository concern, not MongoDB.
Memory sentence: "saveAndFlush forces SQL now; save may wait until flush."
Study: Book chapter
Question 45
What does this SecurityFilterChain configuration enforce for GET /api/orders?
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/health").permitAll()
.anyRequest().authenticated())
.httpBasic(Customizer.withDefaults());
return http.build();
}
}
- A) Authentication is required; unauthenticated requests are rejected according to entry point rules
- B) All requests including /api/orders are anonymous because CSRF is disabled
- C) Only HTTPS is enforced; authentication is optional
- D) GET requests bypass security filters entirely
Answer & explanation
Correct answer: A
anyRequest().authenticated() requires an authenticated principal for /api/orders. permitAll applies only to matched paths like /actuator/health. Disabling CSRF does not disable authentication. HTTP method-specific bypass is not configured.
Why the other options are wrong:
- CSRF disable affects cross-site request forgery protection, not authentication requirements.
- HTTPS enforcement would use requiresChannel or external configuration, not shown here.
- Security filters still run; GET is not globally permitted.
Memory sentence: "permitAll matchers are exceptions; anyRequest().authenticated() secures the rest."
Study: Book chapter
Question 46
Passwords must be stored with adaptive hashing and automatic salt handling. Which encoder is the Spring Security default recommendation?
- A) NoOpPasswordEncoder for plaintext in all environments
- B) MD5PasswordEncoder for speed
- C) BCryptPasswordEncoder
- D) Base64 encoding without hashing
Answer & explanation
Correct answer: C
BCryptPasswordEncoder provides adaptive one-way hashing with salt, resisting rainbow table attacks. NoOp and MD5 are unsafe or deprecated patterns. Base64 is encoding, not secure password storage.
Why the other options are wrong:
- NoOpPasswordEncoder is for legacy testing only, never production default.
- MD5 is not recommended for password storage.
- Base64 is reversible encoding, not password hashing.
Memory sentence: "Store passwords with BCryptPasswordEncoder, not encoding or fast hashes."
Study: Book chapter
Question 47
Method security uses @PreAuthorize("hasRole('ADMIN')"). How should roles be stored in UserDetails authorities for this check to pass?
- A) Exactly "ADMIN" without prefix
- B) As "ROLE_ADMIN" because hasRole adds the ROLE_ prefix when comparing
- C) As "role.admin" lowercase dotted form
- D) Authorities are ignored; only the username matters
Answer & explanation
Correct answer: B
hasRole("ADMIN") expands to ROLE_ADMIN authority comparison. GrantedAuthority values should include ROLE_ADMIN (often via roles with default prefix). hasAuthority("ADMIN") would match literal ADMIN without adding ROLE_.
Why the other options are wrong:
- hasRole expects ROLE_ prefixed authorities internally.
- Dotted lowercase is not the default Spring Security role convention.
- Authorities drive authorization decisions.
Memory sentence: "hasRole("ADMIN") checks for authority ROLE_ADMIN."
Study: Book chapter
Question 48
This configuration targets a stateless JWT API. Why is CSRF disabled here?
http
.csrf(csrf -> csrf.disable())
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
- A) CSRF protection is irrelevant for sessionless APIs using token authentication without browser cookie session semantics
- B) CSRF must always be disabled or Spring Security fails to start
- C) JWT automatically includes CSRF tokens in every header
- D) CSRF only applies to POST and DELETE but never GET
Answer & explanation
Correct answer: A
CSRF protects cookie-based session applications from cross-site requests. Stateless token APIs that do not rely on browser-managed session cookies commonly disable CSRF because attackers cannot easily force custom Authorization headers. This is not universal for all apps.
Why the other options are wrong:
- Spring Security starts fine with CSRF enabled; disable is a deliberate API choice.
- JWT does not replace CSRF protection for cookie sessions automatically.
- CSRF can affect state-changing requests broadly in browser apps; disable rationale here is statelessness.
Memory sentence: "Stateless token APIs often disable CSRF; cookie sessions should keep CSRF enabled."
Study: Book chapter
Question 49
During form login, which component loads user credentials, roles, and account flags for authentication?
- A) UserDetailsService
- B) PasswordEncoder only
- C) HandlerMapping
- D) DispatcherServlet
Answer & explanation
Correct answer: A
UserDetailsService loads UserDetails by username for authentication managers to validate passwords and account state. PasswordEncoder verifies password hashes but does not load users. MVC servlet components are unrelated.
Why the other options are wrong:
- PasswordEncoder hashes and matches passwords; it does not fetch users.
- HandlerMapping routes web requests.
- DispatcherServlet is MVC front controller, not security user loading.
Memory sentence: "UserDetailsService loads users; PasswordEncoder verifies passwords."
Study: Book chapter
Question 50
Which annotation enables JSR-250 style @RolesAllowed at the service layer with Spring Security method security?
- A) @EnableWebSecurity only
- B) @Secured on methods without any enable annotation
- C) @EnableMethodSecurity (or legacy @EnableGlobalMethodSecurity) with securedEnabled/jsr250Enabled as needed
- D) @Transactional
Answer & explanation
Correct answer: C
@EnableMethodSecurity activates method-level security including @Secured, @PreAuthorize, and JSR-250 annotations when jsr250Enabled is configured. @EnableWebSecurity alone configures HTTP security filters, not method interception.
Why the other options are wrong:
- @EnableWebSecurity configures the filter chain, not method annotations alone.
- @Secured requires method security to be enabled to be enforced by Spring.
- @Transactional manages transactions, not authorization annotations.
Memory sentence: "Method security needs @EnableMethodSecurity plus the chosen annotation model."
Study: Book chapter
Question 51
Which beans are present in the test ApplicationContext?
@WebMvcTest(InvoiceController.class)
class InvoiceControllerTest {
@Autowired MockMvc mockMvc;
@MockBean InvoiceService invoiceService;
}
- A) The full application including JPA repositories and DataSource auto-config
- B) Only web-layer MVC infrastructure, Jackson, and InvoiceController with InvoiceService replaced by a mock
- C) No Spring context; only pure unit tests without MVC
- D) Only @Repository beans for slice isolation
Answer & explanation
Correct answer: B
@WebMvcTest loads a narrow MVC slice: controllers, MVC config, Jackson, exception handlers, etc., but not full data layer. @MockBean replaces missing collaborators like InvoiceService. This keeps controller tests fast and focused.
Why the other options are wrong:
- Full @SpringBootTest context includes data layer; @WebMvcTest excludes it.
- MockMvc and @Autowired prove a Spring test context exists.
- @DataJpaTest is the repository slice, not @WebMvcTest.
Memory sentence: "@WebMvcTest = MVC stack plus controller under test; collaborators mocked with @MockBean."
Study: Book chapter
Question 52
A @MockBean replaces an existing MyService bean in a @SpringBootTest. What does Spring do?
- A) Creates a second MyService; injection fails on ambiguity
- B) Ignores @MockBean unless @InjectMocks is also present
- C) Runs the test without Spring context
- D) Removes or overrides the original bean definition so dependents receive the Mockito mock
Answer & explanation
Correct answer: D
@MockBean registers a Mockito mock in the test context, replacing any same-type bean or creating one if missing. Dependent beans then receive the mock during injection. It integrates Mockito with Spring test contexts.
Why the other options are wrong:
- Replacement avoids duplicate ambiguity for the targeted bean.
- @MockBean works without @InjectMocks; the latter is for plain Mockito tests.
- @MockBean requires a Spring test context to register the mock bean.
Memory sentence: "@MockBean puts a Mockito mock into the Spring test ApplicationContext."
Study: Book chapter
Question 53
What is true about @DataJpaTest by default?
- A) It configures an in-memory database, JPA test slice, and rolls back transactions after each test method unless @Commit is used
- B) It starts the entire servlet container and all controllers
- C) It never uses @Transactional
- D) It requires Docker Testcontainers for every run
Answer & explanation
Correct answer: A
@DataJpaTest auto-configures JPA, an embedded DB when available, and @Transactional test rollback by default for isolation. It is not a full web or integration test slice and does not mandate Testcontainers.
Why the other options are wrong:
- Servlet container and controllers belong to @SpringBootTest or @WebMvcTest slices.
- Tests are @Transactional by default for rollback.
- Testcontainers are optional for real DB integration, not a default requirement.
Memory sentence: "@DataJpaTest = JPA slice, embedded DB, transactional rollback per test."
Study: Book chapter
Question 54
What does RANDOM_PORT configure for this integration test?
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ApiIT {
@Autowired TestRestTemplate rest;
}
- A) No web server; TestRestTemplate is not usable
- B) Fixed port 8080 only
- C) Embedded web server starts on a random available port; TestRestTemplate can call real HTTP endpoints
- D) Mocks DispatcherServlet without opening sockets
Answer & explanation
Correct answer: C
RANDOM_PORT starts the embedded servlet container on an ephemeral port, enabling full HTTP integration tests with TestRestTemplate or WebTestClient. DEFINED_PORT uses server.port; NONE skips web environment.
Why the other options are wrong:
- RANDOM_PORT definitely starts a web server.
- Port is random, not hard-coded to 8080.
- Real sockets are used for HTTP integration testing.
Memory sentence: "WebEnvironment.RANDOM_PORT boots embedded server on an ephemeral port."
Study: Book chapter
Question 55
You need extra test-only beans without polluting production @Configuration. Which approach is idiomatic?
- A) @Import on the main @SpringBootApplication class in src/main/java
- B) Define a static @TestConfiguration inner class or separate test configuration imported by the test
- C) Modify production beans with reflection in @BeforeEach
- D) Disable the Spring test context and use only @ExtendWith(MockitoExtension.class) for integration tests
Answer & explanation
Correct answer: B
@TestConfiguration is processed only when explicitly imported or discovered in tests, keeping test doubles out of main configuration. It can define @Bean methods for mocks, stubs, or fakes in integration tests.
Why the other options are wrong:
- Production main configuration should not import test-only beans.
- Reflection hacks are brittle and not idiomatic Spring testing.
- Integration tests need Spring context; MockitoExtension alone is for unit tests.
Memory sentence: "Test-only beans belong in @TestConfiguration imported by tests."
Study: Book chapter
Question 56
A developer uses @InjectMocks on a plain JUnit 5 test without Spring. Which statement is accurate?
- A) @InjectMocks creates and injects mocks into the class under test in pure Mockito tests without starting Spring
- B) @InjectMocks only works inside @SpringBootTest
- C) @InjectMocks replaces @MockBean in the Spring test context automatically
- D) @InjectMocks loads application.yml property bindings
Answer & explanation
Correct answer: A
@InjectMocks is a Mockito annotation that constructs the test subject and injects @Mock/@Spy collaborators without Spring. @MockBean is the Spring TestContext integration counterpart that registers beans in the context.
Why the other options are wrong:
- @InjectMocks is commonly used without Spring in unit tests.
- @MockBean is separate; @InjectMocks does not register Spring beans.
- Property binding is unrelated to Mockito injection.
Memory sentence: "@InjectMocks is Mockito-only; @MockBean is Spring test context integration."
Study: Book chapter
Question 57
Another bean calls transferService.transfer(). Why does internal() run without a transactional boundary?
@Service
public class TransferService {
public void transfer() { internal(); }
@Transactional
public void internal() { /* JDBC work */ }
}
- A) Self-invocation bypasses the proxy, so @Transactional on internal() is not applied when transfer() calls it directly inside the same class
- B) @Transactional applies only to @Repository classes
- C) internal() still runs in a transaction because transfer() was called through the proxy
- D) Spring always merges adjacent methods into one transactional boundary regardless of visibility
Answer & explanation
Correct answer: A
The external call enters transfer() through the proxy, but transfer() then calls internal() directly on this. That inner call does not go through the proxy, so the @Transactional advice on internal() never runs. Move the transactional method to another bean, inject self, or use AspectJ weaving.
Why the other options are wrong:
- @Transactional applies to any Spring-managed bean method, not only repositories.
- The proxy only wraps the method that was called from outside (transfer()); it does not retroactively advise internal() on a same-class call.
- Visibility or adjacency does not cause automatic transactional merging on self calls.
Memory sentence: "Self-invocation skips Spring AOP proxies, breaking @Transactional and other aspects."
Study: Book chapter
Question 58
A method is annotated @Async on a bean in a Boot application with @EnableAsync. Which executor runs it by default if none is customized?
- A) ForkJoinPool.commonPool() always
- B) A new Thread is created per call with no pool
- C) SimpleAsyncTaskExecutor or TaskExecutor bean depending on configuration; Boot provides async support but custom executor requires a TaskExecutor bean definition
- D) The HTTP request thread continues synchronously unless @Transactional is present
Answer & explanation
Correct answer: C
@EnableAsync enables proxy-based async execution. With no custom executor, Spring uses a default SimpleAsyncTaskExecutor (new thread per task in classic setup) unless a TaskExecutor bean is defined. Boot does not silently run @Async on the calling HTTP thread.
Why the other options are wrong:
- Default is not guaranteed to be commonPool for all @Async setups.
- SimpleAsyncTaskExecutor behavior is executor-based, not strictly one-off threads in all versions, but still not synchronous HTTP thread continuation.
- @Transactional does not control @Async dispatch semantics.
Memory sentence: "@Async needs @EnableAsync; customize async with a TaskExecutor bean."
Study: Book chapter
Question 59
ApplicationEventPublisher.publishEvent(new OrderPlacedEvent(orderId)) is called from a service. What is the default listener invocation semantics in Spring unless @Async is applied on the listener?
- A) Listeners run on a background thread immediately
- B) The event is persisted to the database before listeners run
- C) Listeners execute synchronously in the publishing thread after the publisher method reaches publishEvent
- D) Events are dropped unless @EventListener is on a @Controller
Answer & explanation
Correct answer: C
Default Spring application events are synchronous: listeners run in the caller thread unless the listener is @Async with async enabled. Events are in-memory by default, not auto-persisted, and @EventListener works on any bean.
Why the other options are wrong:
- Background invocation requires @Async or application-specific async configuration.
- Event publication does not imply database persistence automatically.
- @EventListener is supported on any managed bean, not only controllers.
Memory sentence: "Spring events are synchronous by default in the publishing thread."
Study: Book chapter
Question 60
A team exports application metrics to Prometheus and monitors JVM memory via Micrometer in Boot. Which integration point is most relevant?
- A) Only custom JSP tags
- B) Only Logback XML appenders without actuator
- C) Declaring @Metric on every controller method manually
- D) Actuator metrics endpoint and Micrometer registry auto-configuration exposing meters like jvm.memory.used
Answer & explanation
Correct answer: D
Spring Boot Actuator with Micrometer auto-configures a MeterRegistry, binds JVM and system metrics, and exposes them via /actuator/metrics and Prometheus registry when configured. This is the standard observability path over ad-hoc logging or manual per-method metrics.
Why the other options are wrong:
- JSP tags are unrelated to Micrometer metrics in modern Boot apps.
- Logging appenders complement but do not replace Micrometer metrics exposure.
- Manual per-method metrics are optional; Boot provides registry infrastructure automatically.
Memory sentence: "Boot observability: Micrometer registry plus actuator metrics and Prometheus export."
Study: Book chapter
End of Mock Full 03 — Spring Professional (60 Questions)