49/60 = 82%, against a 76% pass mark. That is three marks clear, and +5 on #18.
Spring Core went 61% → 91%, the biggest single-section recovery the site has recorded, and it was
the section #18's routine gave the most minutes to. You also finished in 40m 53s, half the time of
#18.
What's left is small and familiar. Three questions where you ticked nothing false and stopped short
(the fifth paper running), two questions answered identically wrong to attempt #14, and a Testing section
that fell to 40%.
The first fourteen papers averaged 40.3. The last five average 47.8. Attempts #15 to #19 are a different level, not a lucky run. #18 is the only dip, and it came from a single section that the next routine fixed.
How the sizes come out. MVC 4/5 = 80%, Security 1/2 = 50% and Boot 10/13 = 76.9% are forced.
Testing at 40% only works as 2/5, which means three Testing misses, so Q8 (the
@TestPropertySource question) was filed under Testing, not Boot. Core and Data share the remaining 35
questions, and both 20/22 + 12/13 and 21/23 + 11/12 give 91% and 92%. Either way Core is still over a third of
the paper.
Security's 50% is one question out of two. It is noise in the percentage, but it's still a real fact
you got wrong, so it gets its own small block below.
You passed by three. The cushion you want on the real exam is bigger than that. It's already on this page:
| If you had… | Score | Result |
|---|---|---|
| Taken every true option on Q3, Q19, Q23 | 52 | 87% |
| …and not repeated #14's Q2 answer, and the SpEL list from #4 | 54 | 90% |
| What actually happened | 49 | 82% — passed |
Five of the eleven misses needed no new knowledge. Three were stopping short, and two were the same answer you gave on an earlier paper.
| Attempt #18 | Attempt #19 | Result | |
|---|---|---|---|
| Score | 44/60 (73%) | 49/60 (82%) | +5 · passed |
| Misses | 16 | 11 | −5 |
| Questions with a false tick | 13 | 8 | −5 |
| Stopped short (no false tick) | 3 | 3 | Unchanged — fifth paper running |
| Left blank | 0 | 0 | Held — seventh paper running |
| Spring Core misses | 9 | 2 | −7 |
| Testing + Security misses | 3 | 4 | +1 |
| Time | 1h 14m 45s | 40m 53s | −34 min, and +5 marks |
The routine worked exactly where it was weighted. #18's routine gave Core 12 minutes and Core gained seven marks. Testing got 5 minutes and Security 2, and those two are now the lowest percentages on the paper.
| Section | #17 | #18 | #19 | Minutes in #18's routine |
|---|---|---|---|---|
| Spring Core | 96% | 61% | 91% | 12 — the most |
| Data Management | 70% | 89% | 92% | 3 (with MVC) |
| Spring MVC | 71% | 80% | 80% | 3 (with Data) |
| Spring Boot | 89% | 85% | 77% | 5 |
| Spring Security | 100% | 100% | 50% | 2 |
| Testing | 75% | 57% | 40% | 5 |
Testing has fallen three papers in a row: 75 → 57 → 40. It is only five questions, but that's five questions at 40% when every other section sits at 77% or better. The Testing clinic exists. This page's Testing block is the longest one for that reason, and the routine at the bottom gives Testing more time than #18's did. Core keeps its 12 minutes because it's 22–23 questions of the paper, even at 91%.
| Q | Topic | Already on this site | Then → now |
|---|---|---|---|
| Q2 | When BeanPostProcessor runs | #14 Q29: word-for-word the same question | Ticked "only once" both times |
| Q19 | What goes in Actuator info | #14 Q35: word-for-word the same question, plus the Boot clinic | Stopped short of the four true options both times |
| Q24 | What SpEL compiled mode can't compile | Attempt #4 (18 Aug): same question, same six options | Missed then, missed now — this time with a false tick on "constructors" |
| Q3 | Fat jar statements | #3, #11 and #15 (review) — different wording, same facts | Fourth fat-jar miss |
Q2 and Q19 are the ones to sit with. Three weeks apart, the identical question got the identical wrong answer. The #14 review explained both. Reading an explanation once didn't change what you clicked. Answering the drill again a few days later is what does. That's why the progress panel below records your scores. Come back to this page before #20 and beat your own numbers.
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.
| Drill block | Qs | Last | Best | Runs | Last done |
|---|---|---|---|---|---|
| Loading… | |||||
| Q | Topic | What went wrong | The answer |
|---|---|---|---|
| Q2 | When BPP runs | + "only once" — same as #14 | Twice per bean, around the init callbacks |
| Q3 | Fat jar statements | Stopped short — 3 were true | Executable · built by default · code + all dependencies |
| Q8 | Highest-precedence property source | + OS environment variables | @TestPropertySource |
| Q14 | application.properties search order | + the reversed order | ./config/ → ./ → classpath:/config/ → classpath:/ |
| Q15 | JdbcTemplate inside a transaction | + "False" | True — one connection, bound to the thread |
| Q19 | Actuator info contents | Stopped short — 4 were true, same as #14 | Version · git hash · description · name |
| Q20 | @DataJpaTest auto-config | + JSR-303 bean validation | JdbcTemplate · TestEntityManager |
| Q23 | Which are HTTP methods | Stopped short — 3 were true | GET · OPTIONS · PUT |
| Q24 | SpEL compiled mode limits | + "constructors" | Assignment · custom resolvers · conversion service · selection/projection |
| Q34 | jsr250Enabled = true | + "All of the above" | @RolesAllowed only |
| Q50 | Spring integration tests | + "config file has to be provided" | Config can be inherited from a superclass |
Fifth paper in a row with this shape: #16 had three, #17 two, #18 three, and now three again. Every time, what you ticked was right, and you stopped before ticking everything that was true.
| Q | Options | True | What they were |
|---|---|---|---|
| Q3 | 4 | 3 | Fat jar is executable · Boot builds one by default · code + all dependencies |
| Q19 | 6 | 4 | Version · git commit hash · description · name (only the two passwords were false) |
| Q23 | 4 | 3 | GET · OPTIONS · PUT (only SUBMIT was false) |
Notice how many were true. 3 of 4, 4 of 6, 3 of 4. On this exam engine, a multi-answer question very often has only one false option. If you've rejected one option and the others all check out, that's normal. It isn't a sign you've ticked too many.
Q2 and Q19 are word-for-word #14's Q29 and Q35, three weeks ago, with the same answers. Q24 is attempt #4's SpEL question, six weeks ago. The practice bank repeats questions. Every miss on this page is likely to come back, so the drills here are worth more than new material.
Three papers running, Testing has dropped: 75 → 57 → 40. The three misses this time are all one idea: what
a Spring test does for you without being asked. Which property source wins, what @DataJpaTest
sets up, and what @ContextConfiguration needs.
@TestPropertySource beats everything on that listThe Boot property order, lowest → highest (the exam-relevant rows):
| # | Source |
|---|---|
| 1 | Default properties — SpringApplication.setDefaultProperties |
| 2 | @PropertySource on a @Configuration class |
| 3 | Config data — application.properties, then profile-specific, inside then outside the jar |
| 5 | OS environment variables ← what you ticked |
| 6 | Java system properties (-Dx=y) |
| 11 | Command-line arguments (--x=y) |
| 12 | properties attribute on @SpringBootTest |
| 13 | @TestPropertySource ← the answer |
| 14 | Devtools global settings (~/.config/spring-boot) |
Why it has to be this way: a test has to be able to override the machine it runs
on. If an environment variable on the CI box could beat @TestPropertySource, your test would pass on
your laptop and fail in CI.
@DataJpaTest auto-configures ticked a false optionIn the @DataJpaTest slice | Not in it |
|---|---|
An embedded database, replacing your DataSource | @Service, @Controller, @Component beans |
| Hibernate / JPA, entity scanning, Spring Data repositories | Web layer, MockMvc |
JdbcTemplate | Caching |
TestEntityManager | Bean Validation auto-configuration |
@Transactional, with rollback after each test | Security |
Why validation is tempting: Hibernate will validate entities on persist if a validator is on the classpath. But that is Hibernate's own behaviour, not something the test slice configures. The question asks what the slice auto-configures.
One correction to the exam's own explanation: it says Flyway and Liquibase are not
part of the slice. In Boot they are included in @AutoConfigureDataJpa, so migrations run
against the test database if the library is on the classpath. That isn't what this question tests, but don't learn
the wrong version from the explanation text.
@DataJpaTest = DB + JPA + repositories + the two templates
(JdbcTemplate, TestEntityManager) + rollback.@ContextConfiguration".
You correctly rejected "a new context per test class" and "you must call getBean()".This is #18's "invented strictness" shape again: "must be public", "must be @Configuration",
and now "has to be provided". @ContextConfiguration with no attributes falls back to a default:
With no classes or locations | Spring looks for… |
|---|---|
| Annotation config | A static nested @Configuration class inside the test class |
| XML config | classpath:com/example/MyTest-context.xml — named after the test class |
Superclass has @ContextConfiguration | It's inherited (inheritLocations = true by default) — the true answer |
@SpringBootTest | Searches upward for the @SpringBootConfiguration class |
application.properties ticked a false option/config sub-directory → working directory → config
package, which is close to lowest-first. The question said highest to lowest.| Priority | Location | Why |
|---|---|---|
| 1 (highest) | file:./config/ (and ./config/*/ since 2.4) | Outside the jar, in the config folder |
| 2 | file:./ | Outside the jar |
| 3 | classpath:/config/ | Inside the jar, config package |
| 4 (lowest) | classpath:/ | Inside the jar, root |
Two rules make the whole order: (1) outside the jar beats inside. Operations
must be able to override what developers packaged. (2) A config folder beats the plain root, in both
places.
config/ beats root. Then read the question's
direction twice: "highest to lowest" or "lowest to highest"?| Statement | |
|---|---|
| Fat jar is executable | TRUE — java -jar app.jar via JarLauncher |
| Spring Boot creates a fat jar by default | TRUE — the Boot Maven/Gradle plugin's repackage / bootJar |
| Contains your code and all dependencies | TRUE — BOOT-INF/classes/ + BOOT-INF/lib/ |
| Contains only your compiled code | FALSE — that's the original thin jar (kept as *.jar.original) |
Don't let the typos put you off. Option D read "Fat jar container the complied code". Badly written options are still true options. Judge the claim, not the spelling.
info stopped short same as #14 Q35Four of six were true: version, git commit hash, description, name. Only the two passwords were false. You stopped short on this exact question on #14 too.
| Contributor | Source | JSON key |
|---|---|---|
EnvironmentInfoContributor | Any info.* property (off by default since Boot 2.6: management.info.env.enabled=true) | app.name, app.version… |
GitInfoContributor | git.properties on the classpath | git |
BuildInfoContributor | META-INF/build-info.properties | build |
/info is public metadata: name, description, version, git. Never a secret.This is the recovery. Nine misses on #18, two on #19. Both of the two are repeats, and neither is deep. Keep Core in the routine anyway. It's the biggest section, and #17 → #18 showed how fast it drops when it's left out.
BeanPostProcessor runs ticked a false option same as #14 Q29| Step | For one bean |
|---|---|
| 1 | Constructor → instance exists |
| 2 | Dependency injection |
| 3 | *Aware setters |
| 4 | postProcessBeforeInitialization ← hook #1 |
| 5 | @PostConstruct → afterPropertiesSet → init-method |
| 6 | postProcessAfterInitialization ← hook #2, AOP proxies made here |
Where the wrong options come from. "After the context is created but before any bean
is created" describes a BeanFactoryPostProcessor. That runs once, on bean definitions.
"Only once" leaves out hook #2, and hook #2 is where proxies are made. Without it, @Transactional
couldn't work. "Three times, including destruction" mixes in DestructionAwareBeanPostProcessor, which is
a separate sub-interface.
| Not compilable (the documented list) | Compiles fine |
|---|---|
Assignment — name = 'x' | Operators — + - * / == < |
| Relying on the conversion service | Constructors — new com.acme.Foo() |
| Custom resolvers or accessors | Property access, method calls, literals |
Selection .?[…] / projection .![…] |
The pattern: the compiler can only turn an expression into bytecode if it knows the exact types in advance. Assignment changes state, the conversion service and custom resolvers are decided at runtime, and selection/projection build collections on the fly. A constructor call has a fixed type, so it compiles.
Modes: OFF (default) · IMMEDIATE (compile ASAP, a later failure throws) ·
MIXED (silently falls back to interpreted). An expression that can't be compiled just stays interpreted.
There's no error.
jsr250Enabled = true ticked a false option| Flag | Enables | Origin |
|---|---|---|
prePostEnabled = true | @PreAuthorize · @PostAuthorize · @PreFilter · @PostFilter | Spring, SpEL-based |
securedEnabled = true | @Secured | Spring, roles only |
jsr250Enabled = true | @RolesAllowed · @PermitAll · @DenyAll | Java standard (JSR-250) |
Telling them apart: JSR-250 is the Java standard, so its annotations live in
javax.annotation.security, not in a Spring package. @Secured is in Spring's own package
even though it looks just as plain.
Since Spring Security 5.6, @EnableMethodSecurity replaces
@EnableGlobalMethodSecurity and turns prePostEnabled on by default. The other two are
still opt-in.
JdbcTemplate inside a transaction ticked a false option| Moment | What happens |
|---|---|
| Transaction starts | DataSourceTransactionManager gets a connection, sets autoCommit=false, binds it to the thread (TransactionSynchronizationManager) |
Each JdbcTemplate call | DataSourceUtils.getConnection(ds) finds the bound connection and reuses it |
| Commit / rollback | The connection is committed or rolled back, unbound, and returned to the pool |
| No transaction | Each call borrows its own connection and auto-commits |
The consequence that gets examined: the binding is per thread. Start a new
thread inside a @Transactional method and its JdbcTemplate calls run outside the transaction.
No false tick, so you left out a real method. OPTIONS is the usual one people leave
out. It's what a browser sends for a CORS preflight.
| Method | Safe | Idempotent |
|---|---|---|
GET · HEAD · OPTIONS · TRACE | yes | yes |
PUT · DELETE | no | yes |
POST · PATCH | no | no |
SUBMIT · FETCH · SEND | ❌ not HTTP methods | |
@TestPropertySource (13) > @SpringBootTest(properties) (12) > command line (11) > system props (6) > OS env (5) > files (3)config/ beats root. Then check the direction the question asks for/info = name, description, version, git. Never secrets. info.* needs management.info.env.enabled=true since 2.6@DataJpaTest = DB + JPA + repositories + JdbcTemplate + TestEntityManager + rollback. No services, no validation, no caching@ContextConfiguration has defaults (nested static @Configuration), is inherited, and contexts are cachedjsr250 → @RolesAllowed · secured → @Secured · prePost → @PreAuthorizeJdbcTemplate call inside reuses itEleven questions with no topic label to prime you. Judge each option on its own, then tick every true one.