Exam Review #8 · 25 Aug 2026, third sitting · 18 to fix

Eighth attempt — 70% again, but two sections are now perfect

42/60 for the second time today. The total didn't move, but underneath it, almost everything did. Testing hit 100%. Security stayed at 100% — the first time in eight attempts that any section has held a top score across two papers. Data Management went 57% → 75% hours after the topic clinic went up. Three of your six sections are now genuinely finished. What's left is small and specific: Spring MVC collapsed to 40%, and all three of its misses are the same single concept. Add the four fabricated names you ticked, and the route to 46 is unusually short — the ledger is below.

70%
This attempt (42/60)
100%
Testing & Security
76%
Pass mark (46/60)
+4
Questions to pass
Official result · practice exam

70% — you did not pass this time

76% required to pass · 60/60 answered · 42 correct · time used 28m 46s of 2h 10m
Spring Security 100%— held0 misses Testing 100%▲ 140 misses Data Management 75%▲ 183 misses Spring Boot 71%▲ 75 misses Spring Core 61%▼ 47 misses Spring MVC 40%▼ 353 misses

Read the top two rows first — they are new information. Until today, every section that reached a high score fell back within one paper: Security went 100 → 60 → 33, Boot went 92 → 40. This time Security held at 100% and Testing joined it. That is the first evidence that anything in this series sticks, and it happened after two consecutive reviews covered the same material. Data Management's +18 is the second piece of evidence — it came hours after the topic clinic, the one page that treats a section as a whole rather than as a list of one paper's mistakes.
The clock is now the outlier. 28m 46s of 2h 10m — 22% of your time, 101 minutes unused, 29 seconds per question. Across four papers you have gone 45 → 49 → 40 → 29 minutes. You are now answering more than four times faster than the exam allows, and six of today's eighteen misses were multiple ticks on one-answer questions.

Your path to 46 — where the four marks actually are

You asked how to reach the pass mark. This paper answers it unusually precisely, because the 18 misses are not spread evenly — they sit in three buckets, and two of them are cheap.

BucketMarksWhat it costs you to fix
Spring MVC — one concept
Q3, Q4, Q51 are all "what can a handler return, and who resolves it"
3 One table (below) plus Lesson 11. Roughly 20 minutes.
Fabricated names you ticked
@BeanConfiguration, @TryInvoke, ConnectionHealthIndicator, server.timeout
4 No study at all — one question asked per option. Zero minutes.
Facts you were already taught
IoC ≠ DI (Q30) and the JavaScript-in-SpEL trap (Q21) — both in review #7, four hours earlier
2 Re-read two checklist lines. Two minutes.
④ Genuinely new material (scopes, SpEL compilation, auto-config ordering, Specification API) 9 The real study. Worth doing — but you don't need it to pass.

Buckets ① + ② + ③ come to 9 marks, and you need 4. Nothing in those three buckets requires learning a new subject — one is a single MVC table, one is a habit, and one is re-reading something you read this morning. That is the whole gap, twice over.

Section scores, attempts #5 to #8

The last three columns are all 25 August — morning, afternoon, evening.

Section#5 · 19 Aug#6 · 25 am#7 · 25 pm#8 · 25 eveVerdict
Spring Security60%33%100%100%HELD — first time anything has
Testing88%70%86%100%Finished
Data Management36%75%57%75%Recovered after the topic clinic
Spring Boot92%40%64%71%Climbing back steadily
Spring Core71%57%65%61%Never above 71% in eight attempts
Spring MVC67%67%75%40%Best, then worst, in four hours
Overall70%58%70%70%Flat total, healthier shape
The total has been flat at 70% for three papers — and that hides real progress. In attempt #5 your 70% was built on one section at 92% and one at 36%. Today's 70% is built on two sections at 100%, one at 75%, one at 71%. The distribution has tightened everywhere except two places. You are no longer failing broadly; you are failing in Spring Core and Spring MVC specifically. That is a much better problem — it is the difference between needing to revise everything and needing to revise two things.

And the decay curve finally broke. Security is the proof: 100 → 60 → 33 when it was reviewed once, then 100 → 100 when it was reviewed twice in short succession. Repetition, not first exposure, is what makes it stick. Your eight reviews now hold 160 corrected facts.
Your four failure modes — 18 misses, and only 9 are knowledge

The four names you ticked that do not exist in Spring

Each of these was a free mark. Not one of them appears anywhere in the Spring, Spring Boot or Actuator source — they are constructed by gluing real words together, which is exactly why they read as plausible.

You tickedThe real thing
ConnectionHealthIndicator (Q15)DataSourceHealthIndicator, DiskSpaceHealthIndicator, RedisHealthIndicator
server.timeout (Q23)server.tomcat.connection-timeout — timeouts are always server-specific
@BeanConfiguration (Q37)@Configuration and @Bean are two separate annotations
@TryInvoke (Q49)@Autowired(required = false), @Nullable, Optional<T>

The habit, stated once: before ticking any option that names a class, annotation or property, ask "have I actually seen this?" If the answer is "it sounds right", that is a no. Real Spring names are shorter and more boring than the fakes — @BeanConfiguration is a compound of two annotations you know; server.timeout is the generic form of a property that only exists in specific forms.

The 18 questions you failed

Your answer is reconstructed from the exported result — if a line looks wrong, tell me and I'll fix it. Click the topic to jump to the full explanation.

QTopicWhat you answeredThe answer
Q1Spring Data Specification API"Requires Spring Boot" + "only works with Hibernate"It builds queries dynamically at runtime
Q3Valid controller return types"HttpServletRequest"void · String · ModelAndView
Q4DispatcherServlet responsibilitiesUnder-selected — missed one of the twoProduces the response · extends HttpServlet
Q5How Boot eases JPA setup"Provides drivers for all enterprise databases"Starter · auto-config · properties · beans · repositories
Q11SimpleJpaRepository per interface"False"True — it's the default implementation
Q12@EnableAutoConfiguration"Required on auto-config classes" + "enables component scanning"Turns on auto-config · is inside @SpringBootApplication
Q15Built-in health indicators"ConnectionHealthIndicator" — inventedDiskSpace · Elasticsearch
Q21What @Value accepts"JavaScript expressions" — same fake as #7's Q53${property} · #{SpEL} · literals · collections
Q23Customising the embedded server"server.timeout" — inventedWebServerFactoryCustomizer · server.port
Q24Where @Transactional works"On a private method"Class level · public methods only
Q29SpEL IMMEDIATE compilation modeTwo wrong descriptions tickedCompile ASAP; on failure throw, don't fall back
Q30"IoC is also known as DI""True" — taught in #3, #4 and #7False — DI is one technique for achieving IoC
Q36@AutoConfigureBefore, class missingThree wrong options tickedThe ordering hint is ignored; the config still loads
Q37Java-based configuration annotations"@BeanConfiguration" — invented@Bean · @Import · @DependsOn
Q43Using a custom scopeThree wrong options tickedIt must be registered with the BeanFactory
Q44Scopes outside a web app"Request scope"singleton · prototype only
Q49@Autowired method, unresolvable parameter"@TryInvoke" — inventedThrows · or make the parameter/method optional
Q51What a controller cannot return"A logical view name" and "void" — the two most standard returnsAn absolute path to the view

Jump to a section

① Spring MVC — 3 misses, one concept ② Spring Boot & auto-config — 5 ③ Scopes & injection — 3 ④ SpEL & @Value — 2 ⑤ Data & transactions — 3 ⑥ Vocabulary & Java config — 2

① Spring MVC 3 misses — all the same concept

40%, down from 75% four hours earlier — and this is the best news on the page. All three misses are the single question "what can a handler method return, and who turns that into a response?" One table fixes the whole section, and the section is 3 marks against a gap of 4.

The table that answers Q3, Q4 and Q51 at once

Return typeValid?What Spring does with it
Stringyesa logical view name → handed to the ViewResolver
ModelAndViewyesmodel and view name together
View (e.g. new JstlView(…), RedirectView)yesthe view object itself — bypasses the resolver
voidyesview name inferred from the URL, or you wrote the response yourself
Model / Mapyesmodel attributes; view name inferred as for void
a domain object + @ResponseBodyyesserialised by an HttpMessageConverter
ResponseEntity<T>yesbody + status + headers
an absolute path "/WEB-INF/views/home.jsp"NOthe resolver would prefix/suffix it and fail
HttpServletRequest / HttpServletResponseNOthese are parameters, injected in — never returned

The one sentence that carries the whole section: a controller returns what to render (a name, a view, or a model) or the response body itself (with @ResponseBody). It never returns the machinery — not the request, not the response, not a filesystem path.

Q3 · Valid controller return types

void, String, ModelAndViewHttpServletRequest is a parameter

Your answer: you ticked HttpServletRequest alongside the three correct ones. It's a real class you've seen in controller signatures — but on the left of the method, not the right.

Spring injects the servlet objects into your method so you can read from them; returning one would tell the framework nothing about what to render:

@GetMapping("/hello")
public String hello(HttpServletRequest request) {   // ← injected as a PARAMETER
    log.info(request.getRemoteAddr());
    return "helloView";                             // ← returned: a view NAME
}

The parameter side of the contract is worth knowing in its own right, because it's the mirror question: Spring can inject HttpServletRequest, HttpServletResponse, HttpSession, Model, Locale, Principal, and anything annotated @RequestParam/@PathVariable/@RequestBody/@RequestHeader.

Memory hook: Servlet objects go IN as parameters. What comes OUT is a view name, a view, a model, or a body.
Q4 · What the DispatcherServlet does

It produces the response and extends HttpServlet — it does not resolve views itself

Your answer: under-selectedyou took one of the two. You correctly rejected "resolves the view" (that's the ViewResolver) and the @EnableWebMvc claim, which is the hard part.

The DispatcherServlet is the front controller: it receives every request and coordinates the components that do the actual work. Knowing who does what is the whole question:

StepWho does it
Receive the requestDispatcherServlet (it extends HttpServlet)
Find the handler for the URLHandlerMapping
Invoke the handler methodHandlerAdapter
Turn a view name into a ViewViewResolvernot the DispatcherServlet
Render and send the responseDispatcherServlet, via the View

And the registration fact, which was the fourth option: @EnableWebMvc does not register a DispatcherServlet. It only switches on the MVC infrastructure beans (HandlerMapping, HandlerAdapter, ViewResolver). The servlet itself is registered by Spring Boot's auto-configuration (mapped to /), or by hand in web.xml / a WebApplicationInitializer in a non-Boot app.

Memory hook: DispatcherServlet coordinates and responds. HandlerMapping finds, ViewResolver resolves. @EnableWebMvc enables beans, it doesn't register the servlet.
Q51 · What a controller cannot return

An absolute path to the view — a logical name and void are both fine

Your answer: you ticked "a logical view name" and "void"the two most ordinary things a controller returns. The question asked which one cannot be returned, so this is a polarity slip on top of the concept.

The distinction is between a logical name and a physical path:

You returnResult
"home"resolver adds prefix + suffix → /WEB-INF/views/home.jsp
"/WEB-INF/views/home.jsp"resolver adds them anyway/WEB-INF/views/WEB-INF/views/home.jsp.jsp
new JstlView("/WEB-INF/views/home.jsp")a View object — skips the resolver entirely

That third row is the key insight, and it's why the question is fair: if you genuinely need to name a physical path, you wrap it in a View object, because View return values bypass resolution. A bare String is always treated as a logical name to be resolved — which is exactly what makes an absolute path break.

Note the pattern across all three MVC questions: two of them hinged on a word — "cannot" here, and "return type" versus "parameter" in Q3. At 29 seconds per question, those are the words that get skipped.

Memory hook: A String is always a logical NAME. Need a real path? Return a View object instead — that skips the resolver.

② Spring Boot & auto-configuration 5 misses

71%, climbing steadily from 40% two papers ago. Two of these five were fabricated names.

Q15 · Built-in Actuator health indicators invented name

DiskSpaceHealthIndicator and ElasticsearchHealthIndicator — there is no ConnectionHealthIndicator

Your answer: you ticked ConnectionHealthIndicator. You were right to reject ApplicationHealthIndicator, which is the same kind of fake.

Health indicators are named after the technology they check, and each is auto-configured when that technology is on the classpath:

IndicatorRegistered when
DiskSpaceHealthIndicatoralways — checks free space against a threshold
DataSourceHealthIndicatora DataSource exists
ElasticsearchHealthIndicatorthe Elasticsearch client is present
RedisHealthIndicator, MongoHealthIndicator, RabbitHealthIndicator, MailHealthIndicator, CassandraHealthIndicatorthat client is present
PingHealthIndicatoralways — trivially returns UP

The naming rule kills both fakes: "Connection" and "Application" name concepts, not technologies. Overall application health isn't an indicator at all — it's the aggregate that HealthEndpoint composes from every registered indicator, taking the worst status.

Two neighbouring facts: write your own by implementing HealthIndicator and annotating it @Component (the bean name minus the suffix becomes the key in the JSON); and management.endpoint.health.show-details defaults to never, so the individual indicators are invisible until you set it to always or when_authorized.

Memory hook: Indicators are named after a technology: DiskSpace, DataSource, Redis, Mongo, Elasticsearch. "Connection" and "Application" are not technologies.
Q23 · Customising the embedded server invented property

WebServerFactoryCustomizer and server.port — there is no generic server.timeout

Your answer: you ticked server.timeout. You correctly rejected the Jetty option, which is the subtler trap — swapping Tomcat for Jetty still gives you an embedded server.

Timeouts are always server-specific, because each container implements them differently:

SettingProperty
Portserver.port (generic)
Context pathserver.servlet.context-path (generic)
Connection timeoutserver.tomcat.connection-timeout · server.jetty.connection-idle-timeout · server.undertow.no-request-timeout
Max threadsserver.tomcat.threads.max

The generic server.connection-timeout did once exist and was removed in Spring Boot 2.3 precisely because it couldn't map cleanly onto every container. So the shape to remember is: settings every server shares are generic; settings only some servers have are namespaced by server name.

And the embedded-vs-external point from the third option: excluding spring-boot-starter-tomcat and adding spring-boot-starter-jetty switches which embedded server you use. To deploy to an external container you package as a WAR and extend SpringBootServletInitializer.

Memory hook: Generic: server.port, server.servlet.context-path. Anything about threads or timeouts is namespaced — server.tomcat.*, server.jetty.*.
Q12 · What @EnableAutoConfiguration does

Turns on auto-configuration, and lives inside @SpringBootApplication — that's all

Your answer: you ticked "must be used on any auto-configuration class" and "enables component scanning". Both attribute someone else's job to it.

Three annotations, three jobs, and the exam tests that you don't blur them:

AnnotationIts one job
@Configurationthis class declares @Bean methods
@EnableAutoConfigurationload auto-configuration classes conditionally from the classpath
@ComponentScanscan this package and below for stereotypes
@SpringBootApplication = all three

On the other distractor: an auto-configuration class is annotated @Configuration (or @AutoConfiguration in Boot 2.7+) and is registered in META-INF/spring.factories — or, from Boot 2.7, META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. It never carries @EnableAutoConfiguration itself; that annotation goes on your application, to say "go and find them".

Memory hook: @EnableAutoConfiguration is the consumer, not the marker. Auto-config classes are registered in a file, not annotated with it.
Q36 · @AutoConfigureBefore(name = "…") when the class is missing

The ordering hint is silently ignored and the configuration loads normally

Your answer: three wrong options ticked — skipped entirely, fails to load, and "use @DependsOn instead". All three assume a missing reference is an error. It isn't.

The clue is in the attribute: name = "com.example.PreviousConfig" is a String, not a class literal. Spring uses the string form precisely so that the class need not be present — referencing it as PreviousConfig.class would require it on the classpath to even compile.

AnnotationOrdersIf the reference is missing
@AutoConfigureBefore / @AutoConfigureAfterauto-configuration classessilently ignored — config still loads
@AutoConfigureOrder(n)auto-config classes, absolutelyn/a
@DependsOnbeansthrows NoSuchBeanDefinitionException

Why the design is like that: auto-configurations are contributed by JARs that may or may not be present. An ordering hint that exploded whenever an optional starter was absent would make every optional dependency mandatory. Ordering is a preference; the real gating is done by @ConditionalOnClass, @ConditionalOnMissingBean and friends.

Memory hook: @AutoConfigureBefore/After = ordering hints on classes, ignored if absent. @DependsOn = bean ordering, throws if absent.
Q5 · How Boot makes JPA setup easier

Five of the six were true — Boot ships no proprietary database drivers

Your answer: you ticked "provides drivers for all enterprise databases like Oracle or SQL Server". Those drivers are vendor-licensed; Boot can't redistribute them.

What the starter does give you — and note that the answer to "how does Boot help" is almost always "all of the above":

Boot providesVia
One dependency pulling the whole stackspring-boot-starter-data-jpa → Hibernate, Spring Data JPA, spring-orm, spring-jdbc, HikariCP
Auto-configurationDataSourceAutoConfiguration, HibernateJpaAutoConfiguration, JpaRepositoriesAutoConfiguration
Property-driven DataSource + HikariCPspring.datasource.*DataSourceProperties
The beans you'd otherwise hand-writeLocalContainerEntityManagerFactoryBean, JpaTransactionManager
Repository proxies@EnableJpaRepositories from the @SpringBootApplication package
JDBC driversno — you add H2, Postgres, MySQL, Oracle yourself

This is the same bean list as the Data Management clinic's manual-JPA question, seen from the other side: there, you wired those four beans by hand; here, Boot does it. Knowing both directions is what the exam is actually testing.

One behaviour worth carrying: Boot backs off, it does not merge. Declare your own DataSource bean and DataSourceAutoConfiguration steps aside entirely — the same @ConditionalOnMissingBean mechanism as the SecurityFilterChain case from review #7.

Memory hook: Boot gives you the starter, the auto-config, the properties, the beans and the repositories. It never gives you a database driver.

③ Scopes & injection 3 misses

Q43 · Using a custom scope

It must be registered with the BeanFactory before any bean can use it

Your answer: three wrong options ticked — "nothing extra is needed", "use a custom annotation", "only in Boot". The first is the tempting one: @Scope("customScope") looks complete, but the string has to resolve to something.

@Scope("customScope") is only a lookup by name. If nothing has registered that name, you get IllegalStateException: No Scope registered for scope name 'customScope' when the bean is first created. Two steps are required:

// 1. implement the Scope interface
public class TenantScope implements Scope {
    public Object get(String name, ObjectFactory<?> factory) { … }
    public Object remove(String name) { … }
    // …
}

// 2. register it — declaratively
@Bean
public static CustomScopeConfigurer scopes() {          // note: static
    CustomScopeConfigurer c = new CustomScopeConfigurer();
    c.addScope("tenant", new TenantScope());
    return c;
}

// 3. now this works
@Bean @Scope("tenant")
public TenantContext tenantContext() { return new TenantContext(); }
Registration routeWhen
CustomScopeConfigurer beandeclarative — the usual way
ConfigurableBeanFactory.registerScope(name, scope)programmatic

The static on that @Bean method matters: CustomScopeConfigurer is a BeanFactoryPostProcessor, so it must be instantiated before the enclosing @Configuration class is fully processed. Same reason PropertySourcesPlaceholderConfigurer is declared static.

Memory hook: @Scope("x") is a name lookup. Something must have registered "x" — CustomScopeConfigurer (static @Bean) or registerScope().
Q44 · Which scopes work outside a web application scopes · touched in #5

singleton and prototype — the other four need a web-aware context

Your answer: you ticked request scope. You correctly rejected session, so the boundary was half there.

Six built-in scopes, split cleanly in two:

ScopeWeb only?One instance per…
singleton (default)noIoC container
prototypenorequest to the container (a new one every time)
requestyesHTTP request
sessionyesHTTP session
applicationyesServletContext
websocketyesWebSocket session

The rule underneath: the four web scopes are keyed off something that only exists in a web container, so they need a WebApplicationContext. Using one in a plain context throws IllegalStateException at runtime — not at startup, which is what makes it a real-world bug.

Two facts that ride along and are asked constantly: prototype beans get no destruction callbacks (Spring forgets them after creation, so @PreDestroy never runs); and injecting a prototype into a singleton gives you one instance forever — use ObjectProvider<T>, @Lookup or a scoped proxy if you want a fresh one per call.

Memory hook: Two non-web scopes: singleton, prototype. The other four are keyed on something only a web container has.
Q49 · An @Autowired method with an unresolvable parameter invented name

It throws — unless you make the parameter, or the method, optional

Your answer: you ticked @TryInvoke. No such annotation exists in Spring — or, for that matter, anywhere in the Java ecosystem.

Three real outcomes, and the difference between two of them is where you put the optionality:

DeclarationBehaviour when one parameter can't be resolved
@Autowired (plain)throws NoSuchBeanDefinitionException; the method never runs
@Autowired(required = false) on the methodthe whole method is skipped — no exception, no partial call
@Nullable or Optional<T> on the parameterthe method is called, with null / Optional.empty() for the missing one
@Autowired(required = false)
public void configureSlack(SlackClient client) { … }        // skipped entirely if absent

@Autowired
public void configure(EmailClient email, @Nullable MetricsClient metrics) { … }
                                          // always called; metrics may be null

Method-level skips, parameter-level injects null. That is the whole distinction, and it's what the question was built around. For constructors the picture is slightly different: required = false isn't meaningful there, so use Optional<T> or @Nullable parameters for optional constructor dependencies.

Memory hook: required=false on the METHOD ⇒ skip the call. @Nullable/Optional on the PARAMETER ⇒ call it with null.

④ SpEL & @Value 2 misses

Q21 · What @Value accepts identical distractor in #7's Q53 — ticked both times

${property}, #{SpEL}, literals and collections — never JavaScript

Your answer: you ticked @Value("(() => 2 * 3)()"). This is the same fabricated option you ticked on Q53 four hours ago, and review #7 named it explicitly: "SpEL has no lambda or arrow-function syntax at all."

Three input forms, handled by three different subsystems — that's why the question is a good one:

FormExampleProcessed by
${…} property placeholder@Value("${app.name}")PropertySourcesPlaceholderConfigurer
#{…} SpEL@Value("#{3 * 2}")SpelExpressionParser
plain text@Value("John")injected as a literal String
collections@Value("${app.roles}") into List<String>comma-separated values are split automatically

Two details that turn up as follow-ups. A missing property throws at startup@Value("${nope}") fails the context; use ${key:default} for optional ones. And the two forms can be combined: @Value("#{environment['my.key'] ?: 'fallback'}") uses SpEL to read a property with an Elvis fallback.

Why this one is worth a moment's reflection. The same fake caught you twice in one day. Recognising the language a snippet is written in is a valid elimination — arrow functions are JavaScript, and no Java framework's expression language borrows them.

Memory hook: ${} = property · #{} = SpEL · bare text = literal. No lambdas, no arrow functions — that's JavaScript.
Q29 · SpEL IMMEDIATE compilation mode

Compile as soon as possible; on failure throw to the caller — no fallback

Your answer: two wrong descriptions ticked. Every option combined a timing clause with an error-handling clause, and you needed both halves right.

By default SpEL interprets expressions by walking the AST. The compiler generates real bytecode, which is much faster for repeated evaluation. Three modes decide when — and what happens when compilation isn't possible:

ModeCompilesIf compilation fails
OFF (default)never — always interpretedn/a
MIXEDafter several interpreted runssilently falls back to interpreted
IMMEDIATEas soon as possible — after the first interpreted evaluationthrows to the caller

Read the two clauses separately. "After some number of runs" ⇒ MIXED. "As soon as possible" ⇒ IMMEDIATE. Then check the error half: MIXED is the forgiving one, IMMEDIATE is the strict one. The names carry both meanings — immediate compilation, immediate failure.

SpelParserConfiguration config = new SpelParserConfiguration(
        SpelCompilerMode.IMMEDIATE, getClass().getClassLoader());
ExpressionParser parser = new SpelExpressionParser(config);

Not every expression is compilable — null-safe navigation, some projections and certain casts aren't. That's the whole reason the two modes differ: MIXED degrades quietly, IMMEDIATE tells you. Compilation only pays off for high-frequency evaluation (Spring Integration, Spring Batch); for a one-off @Value at startup the bytecode generation costs more than it saves.

Memory hook: OFF · MIXED (after several runs, falls back) · IMMEDIATE (straight away, throws). Immediate compile, immediate failure.

⑤ Data & transactions 3 misses

75%, up 18 points from this afternoon — the topic clinic did its job. These three are outside what that page covered, so they're genuinely new ground.

Q1 · The Spring Data JPA Specification API

It builds queries dynamically at runtime by composing predicates

Your answer: "requires Spring Boot" and "only works with Hibernate"two ticks on a one-answer question, and both are the same kind of claim: an artificial restriction that doesn't exist.

Specification<T> wraps the standard JPA Criteria API in something composable. Your repository extends JpaSpecificationExecutor<T> to gain findAll(Specification<T>):

public interface Specification<T> {
    Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}

Specification<User> spec = Specification.where(hasLastName("Smith"))
                                        .and(isActive());
List<User> users = userRepo.findAll(spec);          // query assembled at runtime

Why "dynamic" is the point: derived query methods and @Query are both fixed at compile time — one query per method. A search screen with eight optional filters would need 256 methods. Specifications let you build the WHERE clause from whichever filters the user actually supplied.

On the two distractors: it's part of Spring Data JPA, so it works in any Spring application with or without Boot; and it uses standard JPA Criteria, so any JPA-compliant provider works — Hibernate, EclipseLink, OpenJPA. The pattern to notice is that both wrong options invented a dependency. Also note pagination and sorting are not its job — that's Pageable and Sort, which you pass alongside a specification.

Memory hook: Specification = composable Criteria API = queries built at runtime. Not Boot-specific, not Hibernate-specific, not about paging.
Q11 · "Spring Data JPA creates a SimpleJpaRepository for each repository interface"

True — it's the default implementation behind every repository proxy

Your answer: False. The Data clinic covered SimpleJpaRepository from the transactional angle (readOnly = true at class level); this question asks the more basic fact that it exists at all.

What happens when you declare an empty interface:

StepWhat Spring Data does
1scans for interfaces extending Repository
2creates a JDK dynamic proxy for each one
3backs the proxy with an instance of SimpleJpaRepository
4routes each call: custom fragment → derived query / @Query → the base class

So save(), findById(), deleteAll() are literally SimpleJpaRepository's methods. That's what connects three separate exam facts: no @Repository is needed (the proxy is registered for you); every call is already transactional (the base class is @Transactional(readOnly = true) with write methods overriding); and repositoryBaseClass exists so you can swap this class for your own.

Memory hook: Interface → proxy → SimpleJpaRepository. That one class is why repositories need no annotation and are already transactional.
Q24 · Where @Transactional can be used proxy visibility · #4, #5, #7

Class level and public methods — private, protected and package-private are silently ignored

Your answer: you ticked "on top of the private method". You can physically write it there — it compiles — but in default proxy mode nothing happens.

This is the CGLIB visibility rule from review #7 with one extra restriction on top. Two separate limits are in play:

WhereProxy mode (default)AspectJ mode
class leveladvises all public methods (a default; method annotations override)all methods
public methodadvisedadvised
protected / package-privatenot advisedadvised
privatenot advisedadvised

Note the subtlety versus AOP in general. CGLIB can intercept protected and package-private methods — that was review #7's Q17. But @Transactional is narrower still, because AnnotationTransactionAttributeSource is configured public-methods-only. So the transaction rule is stricter than the proxy rule, and the two questions have different answers. That's exactly the kind of distinction the exam likes.

The silently is what makes this dangerous in practice: no error at startup, no warning — the method just runs without a transaction. Same category as self-invocation, which bypasses the proxy at every visibility. Lifting either restriction means switching to @EnableTransactionManagement(mode = AdviceMode.ASPECTJ) with real weaving.

Memory hook: @Transactional: class level or public methods only. CGLIB could do protected — the transaction attribute source refuses to.

⑥ Vocabulary & Java configuration 2 misses

Q30 · "IoC is also known as DI" taught in #3, #4 and #7 — missed again

False. DI is one technique for achieving IoC

Your answer: True. This is at least the fourth time this exact fact has appeared, and review #7 covered it four hours before this paper. It is one line in a checklist you already have.

The relationship is containment, not equivalence:

Inversion of ControlDependency Injection
What it isa broad principle — the framework, not your code, controls creation and flowone specific technique for realising it
Also includestemplate methods, event callbacks, service locators, contextualised lookupconstructor, setter and field injection
RelationshipDI ⊂ IoC — every DI is IoC; not every IoC is DI

Why it keeps catching you is worth naming: in everyday Spring usage the terms are used interchangeably, and even the Spring docs slide between them. The exam is testing the strict definition, so the phrase "is also known as" / "is another name for" is the trigger — whenever you see it joining IoC and DI, the answer is false.

And a suggestion, since this is the fourth appearance: the fix isn't more reading. Write the sentence "DI is a subset of IoC" somewhere you'll see it, and answer the drill below rather than re-reading this paragraph. Recognition is what's failing here, not comprehension.

Memory hook: IoC is the principle, DI is the implementation. "Another name for" ⇒ FALSE, every time.
Q37 · Annotations used in Java-based configuration invented name

@Bean, @Import, @DependsOn — there is no @BeanConfiguration

Your answer: you ticked @BeanConfiguration. A compound of two annotations you know well, which is exactly what makes it read as real.

The Java-config vocabulary, with what each one actually does:

AnnotationDoes
@Configurationmarks a class as a source of bean definitions (CGLIB-proxied, so inter-@Bean calls return the singleton)
@Beandeclares one bean from a method's return value
@Importpulls in another configuration class — how you modularise config
@DependsOnforces bean A to be initialised after bean B, where there's no injected dependency to express it
@ComponentScanfinds stereotype-annotated classes
@PropertySourceadds a properties file to the Environment

@DependsOn is the one worth a second look, since it's the least familiar: use it when the ordering matters but nothing is injected — a bean that registers a JDBC driver, or one that must initialise a cache before another reads it. Compare it with @AutoConfigureBefore from Q36 above: same idea, but that one orders configuration classes and ignores missing references, while @DependsOn orders beans and throws.

Memory hook: @Configuration + @Bean are two separate annotations, never one. @Import modularises; @DependsOn orders beans.

Your close-the-gap checklist — attempt #8

The 18 facts, one line each
Do this next — in this order (1) The MVC table above, then Lesson 11. Three marks, one concept, about twenty minutes. It is the largest single-topic gap left and it is smaller than the gap to a pass. (2) Adopt the one-question habit. Before ticking any option naming a class, annotation or property, ask "have I actually seen this?" Four marks on this paper, seven on the last. This costs no study time at all and is worth more than any topic you could revise. (3) Drill, don't read. Q21 and Q30 were both covered in review #7 — hours before this paper — and you missed both. Every review page has interactive drills; clicking through them is what converts reading into recall. (4) Spring Core is the long game. 61%, and never above 71% in eight attempts. It's the biggest section on the exam, so once you've passed the 46-mark threshold this is where the headroom is: Lesson 4 · Scopes and Lesson 5 · SpEL cover 5 of today's 7 Core misses. (5) Use the clock. 29 minutes of 130. You now have 101 minutes spare, and six of eighteen misses were multiple ticks on one-answer questions. There is no version of this exam where finishing in a fifth of the time helps.

What's actually changed — read this before the next attempt

Eight attempts in, three things are now settled. Security and Testing are done — 100% each, and Security held it across two papers, which nothing had ever done before. Data Management responds to the topic clinic — +18 the same day. Your under-selection problem is gone — 5 marks in attempt #5, 1 today.

What remains is two topics and one habit: Spring MVC (3 marks, one table), Spring Core (7 marks, the long game), and the fabricated-name check (4 marks, free). You do not need all of that. You need four.

I'm your teacher — ask me anything. The highest-value ask right now is "build me a Spring MVC clinic" — the same treatment the Data Management page got, for the section that's now your weakest. Or say "drill the fakes" for a round made entirely of real-vs-invented Spring names, "quiz me on the 18" for this attempt, or "drill Spring Core" for scopes, SpEL and injection together.
← Dashboard ← Review #7 Data Management clinic Lesson 11 · Spring MVC