Exam Drill #16 · 15 Sep 2026 · 11 to fix · 62 drills

Sixteenth attempt — passed again, and higher

49/60 = 82%, against a 76% pass mark. Your best score in sixteen papers, and +3 on #15. The last page asked for 48+, and you got 49. Spring Security 100%. Testing 73% → 89%. Finished in 51m 32s.
The margin is now three questions (46/60 is the lowest pass), up from one. So this page is about the two sections still under the pass mark, Spring Core (71%) and Spring Boot (75%), and the four misses that were already answered on this site.

82%
Pass mark 76% ✓
+3
Marks on #15 (46 → 49)
11
Misses — was 14
6
Of the 11 are Spring Core
Official result · practice exam

82% — congratulations, you passed

76% required to pass · 60/60 answered · 49 correct · time used 51m 32s of 2h 10m
Spring Security 100%▲ 500 misses / 2 Data Management 91%▼ 91 miss / 11 Spring MVC 89%▬ 01 miss / 9 Testing 89%▲ 161 miss / 9 Spring Boot 75%▲ 82 misses / 8 Spring Core 71%▼ 46 misses / 21

Section sizes: 21/11/9/9/2/8 reproduces all six official percentages (15/21 = 71.4% → 71%, 10/11 = 90.9% → 91%, 8/9 = 88.9% → 89%, 6/8 = 75%) and sums to 60. It also puts each miss in its obvious section.
Spring Core was 21 of the 60 questions, more than a third of the paper, and it's the lowest section. Data's 91% is one miss out of eleven, not a slide: last time it was six questions. Spring Boot's 75% is two misses out of eight, one question short of the pass mark.

What moved between #15 and #16

Attempt #15Attempt #16Result
Score46/60 (77%)49/60 (82%)Best of sixteen
Misses1411−3
Questions with a false tick118−3
Stopped short (no false tick)33Held
Left blank00Held
Margin over the pass mark1 question3 questions+2
Time52m 34s51m 32s78 minutes unused

All three marks came from false ticks. The sweeping-claim drill on #15 targeted exactly that. Across the eleven questions you missed there were 26 false options, and you rejected 17 of them. Only one question, Q58, had two false ticks.

Four of the eleven were already answered on this site

Same question, not just the same topic. These four marks need no new study. Q25 is the clearest case: you ticked the same false option there for the third time.

QTopicAlready on this siteThen → now
Q25proceed() "at most once"Review #5 Q21 · Review #13 Q51Same false tick, third time
Q22What SpEL # referencesPaper #2 Q50 · Review #14 Q49, with six drills"Environment properties" → "literal values"
Q4Condition on a property valueReview #1 · Review #12 Q11Ticked @ConditionalOnBean → rejected it, stopped short
Q6What HttpMessageConverter is forMVC round 3 Q15Three false ticks → one ("content negotiation")

Q22 is a different wrong option each time, which means the reasoning isn't sticking. So don't reason it out on the day, just remember the bank's answer: "starting with #" means #{…}, and the answer is Spring beans.

Q4 and Q6 are half-fixed. You now reject the distractors that cost you before. What's left is taking both true answers on Q4 and keeping "negotiation" apart from "conversion" on Q6.

The counterexample rule, used in one direction only

#15 said: a sweeping claim falls to one counterexample. That rule worked, and it's where your three marks came from. But on #16 two sweeping claims were true, and Q29 shows the rule being used as a verdict instead of a test.

QThe sweeping statementCounterexample?So it is
Q29"@WebMvcTest's context contains only web components"Name a @Service it loads. You can't, which is why you @MockBean themTrue, but you picked it as the incorrect one
Q29"It is essential to use @ExtendWith(SpringExtension.class)"@WebMvcTest is already meta-annotated with itFalse, and this was the answer
Q55"The constructor is the only method called during creation"No @PostConstruct, no initMethod in this code. NoneTrue
Q25"proceed() must be called up to 1 time only"A retry loop calls it three timesFalse, and you ticked it

Q29 had two sweeping options side by side. Only one of them had a counterexample. A sweeping word tells you to go looking. It doesn't tell you what you'll find. If you look and come up empty, the statement can be true.

A limit on Q55: no false option was ticked, so you left out at least one of the three true ones. The export can't show which. The "only" option is the likeliest, given Q29, but that's a guess.

Where the next marks are

BucketMarksWhat it costs you
The four repeats4No new material. Q4, Q6, Q22, Q25, all with drills already on this site
Injection by bean name2Q40, Q58 — one rule: the bean name is the key
Test the sweeping claim, don't reject it2Q29, Q55 — the two-way drill below
Take the rest once the false ones are gone3Q4, Q30, Q55 — you rejected every false option, then stopped
Never tick a name you can't place1BeanFactoryApplicationContext — the third glued fake in two papers

The rows overlap (Q4 is in two, Q55 in two), so don't add them up. Spring Core and Spring Boot are the only sections under 76%. Five Core marks sit in the first three rows. Aim for 52+ next time, which is 87%.

All 11, at a glance

QTopicWhat went wrongThe answer
Q4Gate a class on a property valueStopped short — 2 were true@ConditionalOnProperty · @ConditionalOnExpression
Q6What HttpMessageConverter is for+ "responsible for content negotiation"Content conversion in HTTP communication
Q21Health show-details + a group+ "details only for the group's checks"Details for all users, no authentication needed
Q22What SpEL # references+ "literal values"Spring beans
Q25AOP advice statements+ "proceed() at most once"@Around first param is ProceedingJoinPoint · throwing filters
Q29The incorrect @WebMvcTest statementPicked "contains only web components" (true)"@ExtendWith(SpringExtension) is essential"
Q30Finder method ending keywordStopped short — all 4 were trueIs · LessThan · GreaterThan · Null
Q36ApplicationContext implementations+ BeanFactoryApplicationContext — inventedClassPathXml… · FileSystemXml…
Q40@Autowired Map<String, T>+ "keys are canonical class names"Keys are bean names
Q55Bean creation in a @Bean configStopped short — 3 were trueConstructor called · @PostConstruct works · constructor is the only call
Q58Three Foo beans — valid injections+ both ambiguous injection points@Qualifier, or a field/parameter named like a bean

Jump to a section

⓪ The two-way counterexample drill — 11 statements ① Spring Core — 6 misses (71%) ② Spring Boot — 2 misses (75%) ③ Spring MVC — 1 miss (89%) ④ Testing — 1 miss (89%) ⑤ Data Management — 1 miss (91%) Mixed drill — all sections, no headings

⓪ The two-way counterexample drill both directions

Every statement comes from this paper, and about half of them are true. For each one, look for the counterexample. If you find one, answer False. If you look and there isn't one, answer True. Don't let the wording decide for you.

The rule, refined

A sweeping word is a reason to look, not an answer

StatementThe searchFound?Verdict
"proceed() at most once"Any advice that calls it twice?A retry loopFalse
"@WebMvcTest loads only web components"Any service or repository it loads?NoneTrue
"@ExtendWith(SpringExtension) is essential"Does it work without it?Yes, it's meta-annotatedFalse
"The constructor is the only method called"Any init callback in this code?NoneTrue
Memory hook: Found a counterexample → false. Looked and found none → it can be true. The word "only" decides nothing.

① Spring Core 6 misses · 21 questions · 71%

Q25 · AOP advice statements ticked a false option 3rd time · review #5 & #13

proceed() may be called any number of times — once, many times, or not at all

You ticked "proceed() must be called up to 1 time only", the same option you ticked on #5 and #13. You correctly rejected @AfterFinally, which doesn't exist.
@Around("@annotation(Retryable)")
public Object retry(ProceedingJoinPoint pjp) throws Throwable {
    for (int attempt = 1; ; attempt++) {
        try {
            return pjp.proceed();            // called up to 3 times
        } catch (TransientException e) {
            if (attempt == 3) throw e;
        }
    }
}

@Around("@annotation(Cached)")
public Object cache(ProceedingJoinPoint pjp) throws Throwable {
    Object hit = cache.get(pjp.getArgs());
    return hit != null ? hit : pjp.proceed(); // called zero times on a hit
}
OptionVerdictWhy
proceed() must be called up to 1 time onlyFalseRetry calls it many times; a cache hit calls it zero
@AfterFinally runs however the method exitsFalseNo such advice. That's @After
The first parameter of @Around must be ProceedingJoinPointTrueIt's how the advice calls the target
@AfterThrowing(throwing = …) narrows matching to that exception typeTrueThe Spring reference: the throwing clause restricts matching to executions that throw that type
Memory hook: proceed(): zero (cache), once (normal), many (retry). All legal. Around = ProceedingJoinPoint first.
Q22 · What SpEL # references ticked a false option 3rd time · paper #2 & review #14

The bank reads "starting with #" as #{…}, and its answer is Spring beans

You ticked "Literal values". On #14 you ticked "Properties in the application environment". Two different wrong options on the same stem.
You writeWhat it isWhich option it matches
#{@orderService.limit}SpEL, reaching into a beanSpring beans — the answer
${app.name}Property placeholder, no # at allEnvironment properties
#{'hello'} · #{42}Literals need no prefix; #{} adds nothingLiteral values
#{systemProperties['java.version']}Reached through a named object, not the #JVM properties

Why your reasoning keeps drifting: the stem is loose. #{42} is a legal expression, so "literal values" sounds plausible. Inside an expression, #id is a variable, like a method parameter in @Cacheable(key = "#id"). Review #14 covers both meanings. For this stem, stop reasoning and use the answer the bank gave twice: beans.

Memory hook: "SpEL starting with #" → #{@bean} → Spring beans. $ = properties. Literals need nothing.
Q40 · @Autowired Map<String, T> ticked a false option

The key is the bean name; the value is the bean

You ticked "key will be canonical class name". You correctly rejected "null" and "exception".
@Component("json") class JsonConverter implements MessageConverter { }
@Component("xml")  class XmlConverter  implements MessageConverter { }

@Autowired Map<String, MessageConverter> converters;
// { "json" -> JsonConverter@1a2b, "xml" -> XmlConverter@3c4d }

The test that settles it: define two @Bean methods returning the same class. Keyed by class name, one would overwrite the other. Bean names are unique in a context, so they're the only key that works.

Injection pointGetsSorted by @Order
List<T> · T[]Every bean of type TYes
Set<T>Every bean of type TNo
Map<String, T>Bean name → bean, for every TNo
T — one beanExactly one, or an exception—

@Primary only picks a winner for a single T. A collection or map still gets every candidate.

Memory hook: Map<String, T> = bean name → bean. Names are unique; class names aren't.
Q58 · Three Foo beans — which injections work ticked 2 false options

No qualifier? Spring falls back to the field or parameter name as a bean name

You ticked both false options: setFoo(Foo foo) and private Foo foo. The only question on this paper with two false ticks, and both fail for the same reason.
Injection pointName Spring triesMatches a bean?Result
@Autowired @Qualifier("foo3") Foo foo;— qualifier decidesfoo3Valid
@Autowired private Foo foo2;foo2foo2Valid
setFoo(@Qualifier("foo1") Foo foo)— qualifier decidesfoo1Valid
setFoo(Foo foo2)foo2 — the parameterfoo2Valid
setFoo(Foo foo)fooNoNoUniqueBeanDefinitionException
@Autowired private Foo foo;fooNoNoUniqueBeanDefinitionException

The order Spring tries, with several candidates: @Qualifier narrows the list → @Primary → highest @Priority → a field or parameter name that equals a bean name → otherwise, fail. The name it matches is the field or parameter, never the setter's method name. setFoo2(Foo foo) still fails.

Same rule as Q40: in both questions the bean name is what connects the injection point to the bean.

Memory hook: Several candidates → Qualifier, Primary, Priority, then the variable's name. foo ≠ foo1/foo2/foo3, so it fails.
Q36 · ApplicationContext implementations invented name

ClassPathXmlApplicationContext and FileSystemXmlApplicationContext — BeanFactoryApplicationContext doesn't exist

You ticked BeanFactoryApplicationContext. You correctly rejected YamlApplicationContext.

The glued-name tell again: BeanFactory + ApplicationContext. #15 had TransactionStatusAdvice and @AutoConfigureDataSource. That's three invented names in two papers, each made from real parts.

Real implementationLoads from
ClassPathXmlApplicationContextXML on the classpath
FileSystemXmlApplicationContextXML on the file system
AnnotationConfigApplicationContext@Configuration classes
GenericApplicationContext · GenericXmlApplicationContextFlexible; register beans programmatically
AnnotationConfigWebApplicationContext · XmlWebApplicationContextWeb apps
AnnotationConfigServletWebServerApplicationContextWhat Spring Boot creates for a servlet app

A slip in the bank's explanation: it lists WebApplicationContext as an implementation. It's an interface that extends ApplicationContext. The two web classes in the table implement it.

Memory hook: Real contexts name their source: ClassPathXml, FileSystemXml, AnnotationConfig. No Yaml, no BeanFactory in the name.
Q55 · Bean creation for a @Bean method stopped short

Three of five were true — and one of them is an "only" statement

No false option ticked, so you left out at least one of the three true ones. You correctly rejected "called every time the bean is requested" and "initialize() is called automatically".
OptionVerdictWhy
The constructor is called when the container creates the beanTruenew MyBean() runs inside myBean()
myBean() is called every time the bean is requestedFalseSingleton; the @Configuration CGLIB proxy returns the cached instance
initialize() is called automaticallyFalseNeeds @PostConstruct or @Bean(initMethod = "initialize")
Init logic can go in a @PostConstruct methodTrueRuns after dependency injection
The constructor is the only method called during creationTrueLook for an init callback in this code: none

The callback order, when there are several: constructor → dependency injection → @PostConstruct → afterPropertiesSet() → initMethod. And note the asymmetry: for @Bean, Spring infers a destroy method (a public close() or shutdown()) but never infers an init method. A method named initialize() is just a method.

Memory hook: Constructor → DI → @PostConstruct → afterPropertiesSet → initMethod. No callback declared, none called. Destroy is inferred; init never is.

② Spring Boot 2 misses · 8 questions · 75%

Q4 · Gate a class on a property value stopped short 3rd time · review #1 & #12

@ConditionalOnProperty and @ConditionalOnExpression — two answers

You rejected both false options, so you took only one of the two true ones. On #12 you ticked @ConditionalOnBean; this time you didn't.
// direct: made for exactly this
@ConditionalOnProperty(name = "enable.class.mycustomautoconfig", havingValue = "true")

// SpEL: a placeholder inside an expression, evaluated as a boolean
@ConditionalOnExpression("${enable.class.mycustomautoconfig:false}")
ConditionTests
@ConditionalOnPropertyA property's presence or value
@ConditionalOnExpressionAny SpEL expression, which can read properties
@ConditionalOnResourceA file or classpath resource exists
@ConditionalOnBeanA bean exists in the context

Two details: without havingValue, @ConditionalOnProperty matches any value except false. And a missing property doesn't match unless you set matchIfMissing = true.

Memory hook: Property value → OnProperty, or OnExpression with ${…}. Resource and Bean test something else.
Q21 · show-details: always + a health group ticked a false option

show-details is set on the endpoint, so it covers everything; a group only adds a URL

You ticked "detailed information only for the checks specified in the custom group". You correctly rejected "hides the other checks", "overrides diskSpace and ping" and "error if not defined".
management:
  endpoint:
    health:
      show-details: always        # applies to /actuator/health and every group
      group:
        custom:
          include: diskSpace, ping   # adds /actuator/health/custom
URLShowsDetails?
/actuator/healthEvery indicator: db, diskSpace, ping, …Yes, for everyone
/actuator/health/customdiskSpace + pingYes — the group inherits show-details

show-details values: never (default) · when-authorized · always. A slip in the bank's explanation: it says when-authorized means "users with the ACTUATOR role". In fact it means any authenticated user, unless you list roles in management.endpoint.health.roles. A group can override show-details for itself, but this one doesn't.

Memory hook: Groups add URLs; they don't hide, override or filter. show-details on the endpoint covers every group.

③ Spring MVC 1 miss · 89%

Q6 · What HttpMessageConverter is for ticked a false option MVC round 3 · Q15

It converts HTTP bodies ↔ Java objects. Negotiation is a different component

You ticked "an MVC infrastructure bean responsible for content negotiation". In round 3 you ticked three wrong options on this stem; now it's one. You rejected "representations into resources" and "internationalization".
StepQuestion it answersComponent
1. NegotiateWhich media type? (reads Accept)ContentNegotiationManager
2. ConvertTurn this object into JSON bytes, or bytes into an objectHttpMessageConverter
—Translate a message into FrenchMessageSource

Why it was tempting: the bank's correct option also uses the word, "used to negotiate content conversion". The false one says the converter is responsible for content negotiation. Read which noun the sentence ends on: conversion is right, negotiation is wrong.

Memory hook: Negotiation picks the type; the converter does the work. Converter = @RequestBody in, @ResponseBody out.

④ Testing 1 miss · 9 questions · 89%, up from 73%

Q29 · The incorrect statement about @WebMvcTest picked a true statement

The wrong one is "@ExtendWith(SpringExtension.class) is essential" — it's already built in

You picked "the ApplicationContext created by @WebMvcTest contains only web components", which is true. You correctly left "class-level" and "a single controller" alone.
StatementTrue?So is it the answer?
With JUnit 5 you must add @ExtendWith(SpringExtension.class)False — it's a meta-annotation of @WebMvcTestYes
@WebMvcTest is a class-level annotationTrueNo
It can target a single controllerTrue — @WebMvcTest(OrderController.class)No
Its context contains only web componentsTrue — that's what "slice" meansNo
@WebMvcTest(OrderController.class)       // no @ExtendWith needed
class OrderControllerTest {
    @Autowired MockMvc mvc;
    @MockBean  OrderService service;       // not loaded by the slice — supply it
}

What the slice loads: @Controller, @ControllerAdvice, @JsonComponent, Converter, Filter, WebMvcConfigurer, HandlerMethodArgumentResolver, plus MockMvc. It doesn't load @Service, @Repository or plain @Component beans. Every Boot test annotation (@SpringBootTest, @DataJpaTest, @JsonTest…) already carries the extension.

Memory hook: Boot test annotations bring their own SpringExtension. "Essential" is the false word here; "only web components" is the definition of a slice.

⑤ Data Management 1 miss · 11 questions · 91%

Q30 · Finder method ending keyword stopped short

All four were valid: Is, LessThan, GreaterThan, Null

No option was false, so you left out at least one. This is the all-true shape from #15, taken to its limit: nothing to reject at all.
Keyword (and alias)ExampleJPQL
Is · Equals · or nothingfindByNameIs(name)name = ?1
LessThan · IsLessThanfindByAgeLessThan(18)age < ?1
GreaterThan · IsGreaterThanfindByAgeGreaterThan(65)age > ?1
Null · IsNullfindByEmailNull()email IS NULL
Between · Like · StartingWith · Containing · In · True · BeforeAlso valid
BiggerThan · Above · MoreThanNot keywords

The pattern: most keywords have an Is form and a bare form, so Null is as valid as IsNull. On a "which are valid" question where every option looks like a real keyword, ticking all of them is allowed.

Memory hook: Is/Equals, LessThan, GreaterThan, IsNull/Null — each with or without "Is". All four is a legal answer.

The 11 facts, one line each

Drill these, don't read them

Mixed drill — all sections, no headings

Eleven questions with no topic label to prime you. For each sweeping option, look for the counterexample and let the search decide. Several of these have more than two right answers.

The change to make before the next attempt (1) Keep the routine. Two passes in a row, 60/60 answered both times, and the score is still climbing. (2) Finish the four repeats. Q25 and Q22 are both on their third miss. Five minutes on their drills above covers them, and they're the cheapest marks on the page. (3) Use the counterexample rule both ways. Look for the counterexample before deciding. If you find nothing, the sweeping claim can stand. Q29 cost a mark because "only" was treated as the verdict. (4) When every false option is gone, take the rest. Q4, Q30 and Q55 were all stopped short after you had already rejected every false option. (5) Aim for 52+. Spring Core is a third of the paper; 18 of 21 there is three marks on its own.
A 30-minute routine before the next paper 5 min — the two-way counterexample drill. Eleven statements, about half of them true. 15 min — Spring Core above. Twenty drills: AOP, SpEL, injection by name, contexts, lifecycle. 5 min — Spring Boot above. The other section under 76%. 5 min — the mixed drill. No headings, every section.
I'm your teacher — ask me anything. Say "drill the repeats" for a set built from every question you've now missed more than once across all sixteen papers, or "quiz me on the 11" for this attempt. Spring Core still has no clinic, and it was 21 of these 60 questions and 6 of the 11 misses. Say "build the Core clinic" and I'll make it from every Core miss in the series.
← Dashboard ← Review #15 Boot clinic Testing clinic MVC round 3