Exam Drill #20 · 2 Oct 2026 · 10 to fix · 52 drills

Twentieth attempt — passed again, and Testing went from 40% to 100%

50/60 = 83%, against a 76% pass mark. That's four marks clear, your second-best score, and two passes in a row. Testing (40% → 100%) and Security (50% → 100%) were the two weakest sections on #19, and neither lost a mark this time. You also finished in 39m 46s, even faster than #19.
The thing to look at is the repeats. Five of the ten misses were questions you had already got wrong on an earlier paper, and on four of them you ticked the same wrong option again. Those five marks are the difference between 83% and 92%.

83%
Pass mark 76% ✓
+1
Mark on #19 (49 → 50)
10
Misses — was 11
5
Of them already on this site
5 / 6
Of the last six papers passed
Progress · every attempt

Twenty papers, out of 60

Hover a bar for the date and score. The dashed line is 46/60, the lowest pass.

Passed (46+) Below the pass

The first fourteen papers averaged 40.3. The last six average 48.2. Only one of those six missed the pass, and #19 and #20 were both comfortably over it.

Official result · practice exam

83% — passed

76% required to pass · 60/60 answered · 50 correct · time used 39m 46s of 2h 10m
Testing 100%▲ 600 misses Spring Security 100%▲ 500 misses Spring MVC 86%▲ 61 miss / 7 Spring Boot 82%▲ 52 misses / 11 Spring Core 79%▼ 124 misses / 19 Data Management 75%▼ 173 misses / 12

How the sizes come out. MVC at 86% only works as 6/7. Boot at 82% is 9/11 or 14/17, Data at 75% is 9/12 or 6/8, and Core at 79% is 15/19 or 19/24. Two misses could be filed under more than one section: Q7 (@EnableTransactionManagement) and Q17 (closing the context in a WAR). The most likely split is the one shown, with Q7 under Data and Q17 under Boot. That leaves 11 questions between Testing and Security. Whatever the exact split, Core and Data together lost seven of the ten marks.

Where the next marks are

If you had…ScoreResult
Not repeated the five questions already reviewed on this site5592%
…and got the five new ones60100%
What actually happened5083% — passed

Half the misses needed no new knowledge, only remembering a review you'd already read. The five new misses share one shape too: each ticked option claims Spring can do something it can't. See Shape 2.

What moved between #19 and #20

Attempt #19Attempt #20Result
Score49/60 (82%)50/60 (83%)+1 · passed
Misses1110−1
Stopped short (no false tick)31−2 · lowest in six papers
Questions with a false tick89+1
Left blank00Held — eighth paper running
Testing + Security misses40−4
Core + Data + Boot misses69+3
Misses already on an earlier paper4 of 115 of 10+1
Time40m 53s39m 46s−1 min

"Take every true option" worked. #19 asked for it and the stopped-short count fell from three to one. The only one left was Q7, a question that has two true answers.

The routine fixed Testing and Security; Core and Data slipped

Section#18#19#20Minutes in #19's routine
Testing57%40%100%8
Spring Security100%50%100%3
Spring MVC80%80%86%3 (with Data)
Spring Boot85%77%82%5
Spring Core61%91%79%10 — the most
Data Management89%92%75%3 (with MVC)

Data had the least time and fell the most, which fits the pattern of the last four papers. Core is the exception: it had the most minutes and still fell. But look at what Core missed. Two of its four misses (Q14, Q51) are questions you have now got wrong two or three times. New drills alone don't fix those. Redoing the old drills does, which is why the repeats come first on this page.

Five of the ten were already on this site, four with the same wrong option

QTopicAlready on this siteThen → now
Q51What SpEL compiled mode can't compileAttempt #4 (18 Aug) and #19 Q24 yesterdayTicked "constructors" on #19 and #20. Third miss
Q14@PostConstruct / @PreDestroy order#9 Q57, word for word. The topic was also missed on #5, #6 and #8Ticked "@PostConstruct runs after afterPropertiesSet()" both times
Q15show-details + a health group#16 Q21, word for wordTicked "details only for the group's checks" both times
Q45JdbcTemplate return types#14 Q10, same optionsTicked JSONObject both times
Q7Enabling @Transactional#12 Q16, word for wordThen: two invented options. Now: no false tick, but one of the two true options left out. Better.

The practice bank repeats itself, and so do your answers. Reading a review once leaves a vague sense of "I've seen this". Under time pressure, that feeling points you back to the option you picked last time. The fix is to answer the question again, correctly, a few days later. The first drill block is those five questions as they appeared on the paper.

A correction to review #9

Review #9 said that on Q57 you ticked "always invoked regardless of the bean's scope". Reading that export again with the letter rule (see below), that option had a letter, so you didn't tick it. The option with no letter and "Incorrect" was "@PostConstruct runs after afterPropertiesSet()", which is the same false tick as today. So #9's review drilled the wrong option, and the mistake that needed fixing never got a drill. That's the review's fault, not yours. This page fixes it.

My drill progress on this page

Each time you finish a drill block (every question answered), it's recorded here in this browser. Reload the page to retake a block. Questions and options reshuffle every time. Aim for a full score on every block before the next paper, and redo the repeats block on a different day from the first try.

Drill blockQsLastBestRunsLast done
Loading…

All 10, at a glance

QTopicWhat went wrongThe answer
Q7Enabling @TransactionalStopped short — 2 were true · #12@EnableTransactionManagement · nothing needed under Boot
Q14@PostConstruct / @PreDestroy+ "after afterPropertiesSet" · same as #9@PreDestroy before destroy() · each called once
Q15Health group + show-details+ "only the group's checks" · same as #16Details shown to everyone, unauthenticated too
Q17Closing the context in a WAR+ "closes automatically when the JVM exits"ContextLoaderListener handles contextDestroyed
Q18Default HttpMessageConverters+ CsvHttpMessageConverterMappingJackson2… · Jaxb2RootElement…
Q26@Value("${user.home}")+ "must be defined in application.properties"The JVM system property's value
Q39JoinPoint+ "can call the method with different arguments"Usable in @Before · gives name + args
Q45JdbcTemplate return types+ JSONObject · same as #14User-defined types · simple types
Q49Declaring a repository+ "implement the Repository interface"Extend JpaRepository / Repository · @RepositoryDefinition
Q51SpEL compiled mode+ "constructors" · same as #19Assignment · custom resolvers · conversion service · selection/projection

A note on what you ticked

The exported results show an icon instead of a letter for any option that was correct or ticked. So a no-letter option marked "Incorrect" is a definite false tick. Nine of the ten misses have exactly one of those. Q7 has none, so it can only be under-selection: you ticked one of its two true options and stopped.

Jump to a section

⓪ The repeats + the shape of the new misses — 5 drills ① Spring Core — 4 misses (79%) · 13 drills ② Data Management — 3 misses (75%) · 10 drills ③ Spring Boot — 2 misses (82%) · 9 drills ④ Spring MVC — 1 miss (86%) · 5 drills Every hook on one screen Mixed drill — all sections, no headings · 10 drills

⓪ The repeats, and the shape of the new misses all 10 misses

Shape 1 · Q14, Q15, Q45, Q51 same wrong option as an earlier paper

Four questions, four identical wrong clicks

Each of these was explained on an earlier review page, and each got the same false tick again. That means the wrong option still feels right. Here's why each one is tempting, and the fact that rules it out:

QThe tempting optionWhy it feels rightWhat rules it out
Q51SpEL can't compile constructorsnew sounds like reflection, and "Constructor" starts with C like two of the real fourThe two Cs are Conversion service and Custom resolvers. new Foo() names its type, so it compiles
Q14@PostConstruct after afterPropertiesSet()"Post" sounds like "last"@PostConstruct is run by a BeanPostProcessor's before-init hook, which runs before the init methods
Q15Details only for the group's checksThe group is the newest thing in the YAMLshow-details sits on the endpoint, so it covers /actuator/health and every group
Q45JdbcTemplate returns JSONObjectREST apps return JSON all daySpring JDBC has no dependency on any JSON library. It returns Java values and your objects
Memory hook: If an option feels familiar, ask whether you've seen it as the right answer or as the one you ticked last time.
Shape 2 · Q17, Q18, Q26, Q39, Q49 Spring doing something it doesn't

Every new miss gave Spring a class, an ability or a rule it doesn't have

QWhat you tickedWhat's actually true
Q18A CsvHttpMessageConverterNo such class. Converters are named after a library (Jackson, JAXB, Gson)
Q39JoinPoint can call the method with new argumentsOnly ProceedingJoinPoint.proceed(args), and only in @Around
Q49Implement the Repository interfaceYou extend it with an interface. Spring writes the class
Q26user.home must be in application.propertiesSystem properties are always in the Environment
Q17The context closes automatically when the JVM exitsTrue for a fat jar. In a WAR the server owns the JVM, and it outlives the app

This is the "invented strictness" shape from #18 and #19, plus its mirror image, invented ability. The quickest test is to name the actual thing.

Memory hook: Before ticking, name the class, method or property that would do it. If you can't name one, don't tick it.

① Spring Core 4 misses · about 19 questions · 79%, down from 91%

Q14 · @PostConstruct / @PreDestroy ticked a false option same as #9 Q57

@PostConstruct runs first, and there's a mechanical reason why

You ticked "@PostConstruct methods are invoked after afterPropertiesSet()". You correctly rejected "always invoked, regardless of scope".
StepInitialisationWho calls it
1postProcessBeforeInitializationEvery BPP
1a@PostConstructCommonAnnotationBeanPostProcessor, inside step 1
2InitializingBean.afterPropertiesSet()The bean factory's invokeInitMethods
3@Bean(initMethod = "…")Same, straight after step 2
4postProcessAfterInitializationEvery BPP (AOP proxies are made here)

This ties to #19's BPP question. @PostConstruct isn't a special phase. It's a BeanPostProcessor doing its job in the before hook. The init methods only run after every before-hook has finished. So @PostConstruct can't come after afterPropertiesSet().

Destruction is the same order: @PreDestroy → DisposableBean.destroy() → destroyMethod. Each callback runs once. Prototypes get @PostConstruct but never @PreDestroy, because Spring doesn't keep track of them after handing them out.

Memory hook: Annotation → interface → custom method, in both directions. @PostConstruct lives inside the BPP before-hook, so it can't be last.
Q51 · SpEL compiled mode ticked a false option third miss · same tick as #19

The two Cs are Conversion and Custom, not Constructor

You ticked "Expressions relying on constructors", the same option as yesterday. You correctly took all four true options and rejected "operators".
Can't be compiled (A-C-C-S)Why the compiler can'tCompiles fine
Assignment — name = 'x'Changes state while evaluatingConstructors — new com.acme.Foo()
Conversion serviceThe target type is decided at runtimeOperators — price * qty
Custom resolvers / accessorsYour own code decides the lookup at runtimeMethod calls, property access, literals
Selection / projection — .?[] .![]Builds a new collection as it goes

The rule behind the list: the compiler turns an expression into bytecode once, so it needs every type fixed in advance. new com.acme.Foo() spells out its type. That's as fixed as a type gets.

For completeness: Spring 6's docs also list overloaded operators and array construction (new int[]{1,2}) as uncompilable. Plain operators and ordinary constructors still compile, and the exam uses the four above.

Memory hook: A-C-C-S. The Cs are Conversion and Custom. "Constructor" is the impostor C.
Q26 · @Value("${user.home}") an invented requirement

${…} searches the whole Environment, and system properties are always in it

You ticked "The value of user.home must be defined in application.properties". You correctly rejected "uninitialised", "exception" and "null".
Property source in the EnvironmentPlain SpringSpring Boot
JVM system properties (user.home, java.version, -Dx=y)AlwaysAlways
OS environment variablesAlwaysAlways
@PropertySource filesIf declaredIf declared
application.propertiesNoYes, loaded by Boot

application.properties is one source among several, and a low one. It isn't a gatekeeper that every property has to pass through. Even in plain Spring with no placeholder configurer, since Spring 4.3 the context resolves @Value placeholders against the Environment by default.

The SpEL way to write the same thing is @Value("#{systemProperties['user.home']}"). Notice the #{…} and the systemProperties map, compared with ${user.home}.

Memory hook: System properties and env vars are in every Environment from the start. application.properties only adds more.
Q39 · JoinPoint an invented ability

A JoinPoint can look at the call. Only a ProceedingJoinPoint can make it.

You ticked "JoinPoint can be used to call the underlying method with different arguments". You correctly took "passed to @Before" and "name + arguments", and rejected "must be last".
JoinPointProceedingJoinPoint
Used in@Before, @After, @AfterReturning, @AfterThrowing@Around only
Read the callgetSignature(), getArgs(), getTarget(), getThis()Same (it extends JoinPoint)
Run the methodNoproceed()
Run it with new argumentsNoproceed(Object[] args)
Position in the advice signatureMust be the first parameter

Why it has to be this way: by the time @Before advice finishes, Spring is going to call the method anyway. @AfterReturning runs after it's already been called. Only @Around sits in place of the call, so only it gets the ability to make the call. (@Before can stop the call by throwing an exception, but it can't change the arguments.)

Memory hook: Only the advice that wraps the call can make the call. @Around → ProceedingJoinPoint → proceed(newArgs).

② Data Management 3 misses · about 12 questions · 75%, down from 92%

Q7 · Enabling @Transactional stopped short #12 Q16

Both are true: the annotation in plain Spring, and nothing at all in Boot

No false tick, so you took one of the two true options and stopped. On #12 you ticked the two invented options, so this is real progress.

SetupWhat enables @Transactional
Plain Spring@EnableTransactionManagement on a @Configuration class, plus a PlatformTransactionManager bean
Spring BootNothing. TransactionAutoConfiguration applies @EnableTransactionManagement for you once a transaction manager exists (e.g. from spring-boot-starter-data-jpa or -jdbc)
@Configuration(enableTransactions=true) · @EnableDatabaseTransactionsNeither exists
Memory hook: "None of the above, if you use Boot" is a true answer whenever Boot does it for you. Tick it alongside the plain-Spring answer.
Q45 · JdbcTemplate return types ticked a false option same as #14 Q10

Java values and your own objects. Never a JSON or XML library type

You ticked JSONObject, the same as on #14. You correctly rejected Properties and XMLObject.
You get backMethod
A simple type: Integer, String, LocalDate…queryForObject(sql, Integer.class)
A list of simple typesqueryForList(sql, String.class)
One row as Map<String, Object>queryForMap(sql)
Many rows as List<Map<…>>queryForList(sql)
Your own typesquery(sql, RowMapper<T>) · ResultSetExtractor<T>
JSONObject · XMLObject · PropertiesNone. Spring JDBC doesn't depend on those libraries

If you really want JSON, map each row into your own type with a RowMapper, then let Jackson serialise that type in the web layer. Each layer does one job.

Memory hook: JdbcTemplate returns scalars, maps, and your own objects. JSON is the web layer's job.
Q49 · Declaring a Spring Data repository "implement" vs "extend"

You declare an interface. Spring writes the class.

You ticked "Implement the Repository interface". You correctly took all three true options.
ApproachValid?Methods you get for free
interface UserRepo extends JpaRepository<User, Long>YesCRUD + paging + sorting + JPA extras (flush, batch delete…)
interface UserRepo extends Repository<User, Long>YesNone. Only the query methods you declare
@RepositoryDefinition(domainClass = User.class, idClass = Long.class) on a plain interfaceYesNone. The annotation replaces the generic types
class UserRepo implements Repository<User, Long>NoYou'd be writing the class yourself, and that's the whole thing Spring Data does for you

Hand-written code is still possible, through a fragment: declare UserRepoCustom, write UserRepoCustomImpl, and have UserRepo extend both JpaRepository and UserRepoCustom. The repository itself stays an interface.

Memory hook: Repositories are interfaces you extend (or annotate). "Implement" means you write the class, and then it isn't Spring Data.

③ Spring Boot 2 misses · about 11 questions · 82%, up from 77%

Q15 · Health group + show-details ticked a false option same as #16 Q21

A group adds a URL. It doesn't narrow anything else.

You ticked "detailed health information only for the checks specified in the custom group", the same as on #16. You correctly took "details for all users, without authentication".
management:
  endpoint:
    health:
      show-details: always        # on the endpoint → /actuator/health AND every group
      group:
        custom:                   # any name you like
          include: diskSpace, ping  # → /actuator/health/custom
URLRunsDetails?
/actuator/healthEvery indicator: db, diskSpace, ping…Yes, for everyone
/actuator/health/customdiskSpace + ping onlyYes, inherited from the endpoint

A group can override with its own show-details, but this YAML doesn't. Nothing is hidden or overridden, and diskSpace and ping are built in, so nothing fails.

Two corrections to the exam's explanation. (1) It says when-authorized means "users with the ACTUATOR role". That was Boot 1.x. In Boot 2+ it means any authenticated user, or, if you set management.endpoint.health.roles, a user with one of those roles. (2) The probes property is management.endpoint.health.probes.enabled. management.health.probes.enabled is the old 2.3 name.

Memory hook: show-details on the endpoint covers the endpoint and all its groups. A group is a named subset with its own URL, nothing more, unless it sets its own options.
Q17 · Closing the context in a WAR ticked a false option

In a WAR, the server owns the JVM, so the server tells the app to close

You ticked "No action is required, Spring will automatically close the Application Context when the JVM exits". You correctly took ContextLoaderListener.
DeploymentWho owns the JVMHow the context closes
Fat jar, embedded serverYour appJVM shutdown hook, registered by SpringApplication
WAR on Tomcat / WildFly / etc.The application serverContextLoaderListener.contextDestroyed(), when the server stops the web app
Tests, CLI codeYour codecontext.close() or try-with-resources

Why "when the JVM exits" fails for a WAR: one server JVM runs many apps, and you can undeploy or redeploy a single app while the JVM keeps running for weeks. If the app waited for the JVM to exit, its connection pools and threads would leak on every redeploy. So SpringBootServletInitializer registers a ContextLoaderListener (a ServletContextListener) and closes the context in contextDestroyed. Boot also turns its own JVM shutdown hook off for WAR deployments.

Memory hook: Jar: the app owns the JVM → shutdown hook. WAR: the server owns the JVM → the server calls contextDestroyed.

④ Spring MVC 1 miss · 7 questions · 86%, up from 80%

Q18 · Default HttpMessageConverters an invented class

Converters are named after a library. There's no library called "Csv".

You ticked CsvHttpMessageConverter. You correctly took both true options and rejected XlsHttpMessageConverter.
RegisteredConverterHandles
AlwaysByteArrayHttpMessageConverter · StringHttpMessageConverter · ResourceHttpMessageConverter · AllEncompassingFormHttpMessageConverterbytes · text · files · forms
If Jackson is presentMappingJackson2HttpMessageConverterJSON
If Jackson XML is presentMappingJackson2XmlHttpMessageConverterXML
If JAXB is presentJaxb2RootElementHttpMessageConverterXML
If Gson / JSON-B is presentGsonHttpMessageConverter · JsonbHttpMessageConverterJSON
NeverCsvHttpMessageConverter · XlsHttpMessageConverterThese don't exist in Spring

If you need CSV, you write your own converter (extend AbstractHttpMessageConverter) and register it with WebMvcConfigurer.extendMessageConverters, or declare it as a bean in Boot.

Memory hook: Every built-in converter is named after a library or a basic type: Jackson, Jaxb2, Gson, Jsonb, String, ByteArray. No library, no converter.

Every hook on one screen

The ten facts, in one pass

Mixed drill — all sections, no headings

Ten questions with no topic label to prime you. For each option, name the class or method that would do it. If you can't, it's false.

The change to make before the next attempt (1) Redo the repeats block on a different day. Q14, Q15, Q45 and Q51 got the same wrong click twice. Reading wasn't enough, so answering again is the fix. (2) Name the thing before you tick it. All five new misses ticked a class, ability or rule that doesn't exist. (3) Give Data more time. It had the least time in #19's routine and fell 17 points. (4) Keep Testing and Security warm. They hit 100% because they got minutes. #17 → #18 showed how fast an ignored section drops. (5) Keep taking every true option. Stopped-short went from three to one. Q7's "nothing, under Boot" is the kind of second true answer to watch for.
A 36-minute routine before the next paper — all six sections, weighted 6 min — the repeats. Five paper questions. Do them today and again in two days. 10 min — Spring Core. Thirteen drills, then #19's nine. Core is still about a third of the paper. 7 min — Data. Ten drills, then the Data clinic. 4 min — Spring Boot. Nine drills: health groups, WAR lifecycle. 3 min — MVC. Five drills. 3 min — Testing + Security. #19's Testing block and Security block, to keep them at 100%. 3 min — the mixed drill. No headings, so nothing primes you.
Then check your progress panel. Every block at full marks before you sit #21.
I'm your teacher — ask me anything. Say "drill the repeats" for one page built from every question you've missed on more than one paper. After #20 that's at least nine questions, including the four from today. That page would now earn more than a new one would. Or "build the Spring Core clinic". Core is still the biggest section and the only one without its own clinic page.
← Dashboard ← Review #19 Review #9 (Q14 first time) Review #16 (Q15 first time) Data clinic Boot clinic