Exam Review #10 · 28 Aug 2026 · 18 to fix

Tenth attempt — 70%, and eight of the eighteen were names that don't exist

42/60, down from 73%. But the composition of this paper is unlike any before it, and it points at something very specific. Spring Boot went 56% → 86% — the clinic worked within a day, the third time that has happened. Testing collapsed 100% → 33%, the largest single-section fall of the series. And underneath both: 8 of your 18 misses were ticking a class, annotation or method that does not exist in Spring. You need +4. That one habit is worth 8, and it costs no study time at all.

8
Marks lost to invented names
86%
Spring Boot (was 56%)
33%
Testing (was 100%)
+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 42m 39s of 2h 10m
Spring Boot 86%▲ 301 miss Data Management 82%▲ 12 misses Spring Core 73%▼ 26 misses Spring MVC 50%▼ 73 misses Testing 33%▼ 674 misses Spring Security 33%▼ 422 misses

Read the top row and the bottom two together. Spring Boot 56% → 86% — the Boot clinic went up yesterday and Boot jumped 30 points, with a single miss. That is now the third clinic to produce an immediate jump (Data 57→75, Boot 56→86). The mechanism is proven.
And Testing fell 67 points from a section that had held 100% twice running. But look at what the four Testing misses were: @NoRollback, LOCALE_PORT, @RunWith(SpringExtension.class) and "Spring mocks RMI". Three of the four are fabricated names — not decayed knowledge. Testing didn't collapse; the paper happened to test it with invented options and the habit caught you.
The clock held. 42m 39s, essentially identical to attempt #9's 42m 30s. The slowdown from 29 minutes has stuck across two papers. That was the right change — keep it, and push further.

The eleven names you ticked that do not exist in Spring

This is the finding of the paper. Eight separate questions — 44% of your misses — turned on an option naming a class, annotation, method or enum constant that simply is not part of Spring. Not one of them requires knowing the topic to eliminate.

You tickedQThe real thing
@NoRollbackQ5@Commit or @Rollback(false)
@NoRollback(true)Q5— same option twice, in two forms
@SecureSec.@Secured — one letter
@AuthorizeSec.@PreAuthorize / @PostAuthorize
LOCALE_PORTQ17MOCK, RANDOM_PORT, DEFINED_PORT, NONE
@ProxyMode("CGLIB")Q22@EnableAspectJAutoProxy(proxyTargetClass = true)
@SetProxyMode("CGLIB")Q22— same answer, second invented form
JDBCTransactionManagerQ38DataSourceTransactionManager
JDBCDataSourceTransactionManagerQ38— same answer, second invented form
@HttpResponseStatusQ43@ResponseStatus
DifferentOfQ46Not / IsNot
restrict()Q59antMatchers(), mvcMatchers(), regexMatchers()

Notice the pattern in the pairs. On Q5, Q22 and Q38 you ticked two invented options for the same question. That's the signature of scanning for something that looks plausible rather than asking whether it's real — and on all three, the genuine answer was sitting there unticked.

The running total is now stark. Attempt #7: 7 fakes. #8: 4. #9: 3. #10: 11, across 8 questions. It has been your largest recoverable bucket in four consecutive papers, and this time it is double the gap to a pass.

The clinics work — three for three

ClinicPublishedSection beforeNext paper
Data Management25 Aug57%75%▲ 18
Data Management (held)75%81% → 82%holding
Spring Boot27 Aug56%86%▲ 30

Spring Boot went from your worst section to your best in one day, with a single miss — and Actuator, which had cost you marks in four consecutive papers, cost you nothing on this one. Data Management has now held 75–82% across three papers since its clinic. The MVC clinic is the one you haven't drilled yet, and MVC is at 50%.

How to reach 76% — the ledger

You asked how to improve your answers to get to the pass mark. This paper gives the least ambiguous answer of the ten:

BucketMarksWhat it costs
Names that don't exist
Q5, Security fill-in, Q17, Q22, Q38, Q43, Q46, Q59
8 Zero study. One question per option: "have I actually seen this?"
Facts already on this site
Q38 (Data clinic §3), Q46 (Data clinic §8), Q37 + Q43 (MVC clinic), Q47 (#8)
5 Drill the three clinics. ~40 minutes, no new material.
Spring Core detail
Q1, Q14, Q24, Q44, Q48 — scanning, context, bean order, DI, profiles
5 Genuine study. Lessons 1–3.

Bucket ① alone is double the gap. There is no reading, no lesson and no new concept in it. On this paper, eliminating invented options and committing to the survivor would have scored you 50/60 = 83%.

Section scores, attempts #6 to #10

Section#6 · 25 am#7 · 25 pm#8 · 25 eve#9 · 26 Aug#10 · 28 AugVerdict
Spring Boot40%64%71%56%86%Clinic → best section
Data Management75%57%75%81%82%Holding since its clinic
Spring Core57%65%61%75%73%Stable around 73–75
Spring MVC67%75%40%57%50%Clinic written, not yet drilled
Testing70%86%100%100%33%Fell — but on fake names
Spring Security33%100%100%75%33%Volatile · only 2 misses
Overall58%70%70%73%70%Flat — but shifting
Read Testing and Security carefully before concluding anything. Both are small sections — Testing shows 33% off 4 misses, Security off 2. A couple of questions move those percentages enormously, so the drop looks more dramatic than it is. What matters is the content: of those six misses, five involved a fabricated name. That is a different problem from forgetting how testing works.

The overall picture after ten attempts. Your total has sat at 58–73% for two weeks while individual sections swing by 50 points. But the mechanism is now well understood and demonstrably works: a topic clinic lifts its section 18–30 points and it holds (Data: 75 → 81 → 82). Two of three clinics are done and their sections are your two best. Your ten reviews now hold 194 corrected facts.
Your failure modes — 18 misses
Q38 deserves singling out — you have now missed it three times "Which PlatformTransactionManager implementation handles a single JDBC DataSource?" It is in the Data Management clinic §3, it was a drill you got wrong on 26 Aug, and I walked you through the naming rule in conversation the same day — "managers are named after the resource they wrap; nothing in Spring is called JDBC*TransactionManager". Two days later you ticked JDBCTransactionManager and JDBCDataSourceTransactionManager. Reading an explanation is not the same as being able to retrieve it under time pressure — which is what the drills are for, and why this review pushes them so hard.

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. Purple = an invented name.

QTopicWhat you answeredThe answer
Q1Two configs, two @ComponentScansThree wrong options tickedBeans from both packages are registered
Q5Committing a test transaction"@NoRollback" + "@NoRollback(true)" — both invented@Commit · @Rollback(false)
Q14The ApplicationContext"It is the front servlet"Resolves external config · instantiates beans
Securing service-layer methods"@Secure, @Authorize" — both invented@Secured + @PreAuthorize, on methods
Q17@SpringBootTest webEnvironment"LOCALE_PORT" — inventedMOCK · RANDOM_PORT · DEFINED_PORT · NONE
Q22Forcing CGLIB proxies"@ProxyMode" + "@SetProxyMode" — both invented@EnableAspectJAutoProxy(proxyTargetClass = true)
Q24Bean creation order"on first access" + "reverse order"The dependency chain, not declaration order
Q27Micrometer Gauge"suitable for cumulative metrics" + "updates itself"A polled snapshot of a value you maintain
Q32Where Spring provides mock objects"RMI"Environment and JNDI
Q37@RequestMapping statementsUnder-selected — missed one of twoMaps all verbs by default · path takes an array
Q38JDBC transaction managerTwo invented "JDBC…" names — third timeDataSourceTransactionManager
Q43Mapping an exception to 404"@HttpResponseStatus" (invented) + "500"@ResponseStatus404
Q44Handling bean dependencies"@Required"@Autowired constructor · @Inject · depends-on
Q46Finder-method keywords"DifferentOf" — inventedLessThan · Is
Q47@SpringBootTest's meta-annotationBoth "@RunWith(…)" options@ExtendWith(SpringExtension.class)
Q48Maximum active profiles"2" and "3"No limit — "none of the above"
Q57Default template engine"JSP" + "JSON"Thymeleaf
Q59Restricting URLs by pattern"restrict()" — inventedantMatchers() · mvcMatchers()

Jump to a section

① Spring Core — 6 misses ② Testing — 4 ③ Spring MVC — 3 ④ Data Management — 2 ⑤ Spring Security — 2 ⑥ Spring Boot — 1

① Spring Core 6 misses

73%, stable. These six are the largest genuine-knowledge cluster on the paper — and now the biggest remaining topic once the fake-name habit is fixed.

Q1 · Two @Configuration classes, each with its own @ComponentScan

Both scans run — beans from both packages end up in the same context

Your answer: three wrong options ticked — "must import", "only the first runs", "only repositories". All three assume the scans compete. They don't.

Each @Configuration class is processed independently, and every bean discovered by any scan lands in one shared ApplicationContext. There is no precedence, no override, no "first one wins":

@Configuration @ComponentScan("com.example.services")     class ServiceConfig {}
@Configuration @ComponentScan("com.example.repositories") class RepositoryConfig {}
// both loaded → beans from BOTH packages available

The distractor worth dismantling is "@ComponentScan must be at the application entry point". It works on any @Configuration class — the entry point is just where Boot conventionally puts it, via @SpringBootApplication. Splitting scans across configs is a legitimate modularisation pattern.

The equivalent single-class form, worth recognising: @ComponentScan(basePackages = {"com.example.services", "com.example.repositories"}).

Memory hook: Scans are additive, not competitive. Any @Configuration class can declare one. One context holds them all.
Q14 · What the ApplicationContext is

The bean container — not the front servlet, and there can be more than one

Your answer: "it is the front servlet of the application". That's the DispatcherServlet — it uses an ApplicationContext but isn't one.

Its responsibilities, which is what these questions enumerate:

DoesVia
Instantiate and manage bean lifecyclesBeanFactory inheritance
Resolve external configurationEnvironmentCapable + @Value
Publish eventsApplicationEventPublisher
Resolve i18n messagesMessageSource
Load resourcesResourcePatternResolver
Create AOP proxiesregistered BeanPostProcessors

The other statement that caught you — "a running application has only one" — is false because of context hierarchies. Classic Spring MVC has a root context (services, repositories) and a child servlet context per DispatcherServlet (controllers, view resolvers). The child can see the parent's beans; the parent cannot see the child's. Spring Boot usually collapses this into one, but the hierarchy is still supported — and Spring Cloud uses a parent bootstrap context.

Memory hook: ApplicationContext = the container. DispatcherServlet = the front controller that uses one. Parent/child hierarchies are normal.
Q22 · Forcing CGLIB proxies two invented annotations

@EnableAspectJAutoProxy(proxyTargetClass = true) — it's an attribute, not an annotation

Your answer: @ProxyMode("CGLIB") and @SetProxyMode("CGLIB"). Neither exists. The real mechanism is a boolean on the annotations you already know.

The generalisable fact: proxy strategy is a single flag — proxyTargetClass — exposed by every annotation that sets up an auto-proxy creator:

AnnotationPlain Spring defaultSpring Boot 2.x default
@EnableAspectJAutoProxyfalsetrue
@EnableTransactionManagementfalsetrue
@EnableCachingfalsetrue
@EnableAsyncfalsetrue

Boot flipped these to true in 2.0 so that injecting by concrete class always works — with a JDK proxy you can only inject by interface, which surprises people. Note the flag only matters when the target has an interface; with no interface Spring uses CGLIB regardless.

And a caution: setting it on one annotation does not set it on the others. If both AOP and transactions are in play, set it consistently.

On the invented options: ScopedProxyMode is a real enum — but it's used on @Scope(proxyMode = …) for scoped beans, not for AOP strategy. That's what makes @ProxyMode feel familiar: it's a real word from a neighbouring concept.

Memory hook: Proxy strategy is the proxyTargetClass attribute, on every @Enable* that creates proxies. Boot defaults it to true.
Q24 · What determines bean creation order

The dependency graph — declaration order is irrelevant

Your answer: "created on first access" and "reverse order". The first describes @Lazy; the second isn't a Spring behaviour at all.

Spring resolves the graph and instantiates in dependency order: beanAbeanB(beanA)beanC(beanB). Reorder the methods in the file and nothing changes.

MechanismEffect on order
A method parameter (or constructor arg)the argument bean is created first
@DependsOn("beanX")forces beanX first with no injection
@Lazydefers creation until first use
Declaration order in the filenone

Why "on first access" is wrong by default: an ApplicationContext instantiates singletons eagerly at startup — that's one of the things it adds over a bare BeanFactory, and it's deliberate, so wiring errors surface immediately rather than on first request. @Lazy opts out per bean.

The companion fact: a circular dependency between constructor-injected singletons throws BeanCurrentlyInCreationException. Break it with setter injection, @Lazy, or — better — a redesign.

Memory hook: Dependencies decide the order, never declaration position. Singletons are eager; @Lazy opts out; @DependsOn orders without injecting.
Q44 · Ways to handle dependencies between beans

@Autowired constructor · @Inject · depends-onnot @Required

Your answer: you ticked @Required. It's a real annotation — which makes it a smarter distractor than the invented ones. But it enforces that a property was set; it doesn't wire anything.
MechanismDoesStatus
@Autowiredinjects by type — constructor, setter or fieldthe standard
@Inject (JSR-330)the same, vendor-neutralfine
@Resource (JSR-250)injects by namefine
depends-on / @DependsOnorders initialisation without injectingfine
@Requiredasserts a setter was called — no injectiondeprecated (Spring 5.1)

Why @Required was deprecated is the point: constructor injection makes it unnecessary. If a dependency is a constructor parameter, it cannot be missing — the object can't be built without it. @Required only ever existed to patch a weakness in setter injection.

Note the shape of this distractor: a real but obsolete annotation. That's the second family to watch alongside invented names — @Required, WebSecurityConfigurerAdapter, @MockBean are all real and all superseded.

Memory hook: @Autowired / @Inject / @Resource inject. @DependsOn orders. @Required only asserts — and is deprecated.
Q48 · How many profiles can be active at once

No limit

Your answer: "2" and "3". Two numeric guesses on a question whose answer is "none of the above" — and ticking two mutually exclusive numbers can't be right under any reading.

Profiles are a comma-separated list and Spring imposes no cap:

spring.profiles.active=dev,logging,metrics,eu-west
java -jar app.jar --spring.profiles.active=prod,monitoring
SPRING_PROFILES_ACTIVE=dev,debug

A bean is registered if any of its @Profile values matches an active profile. Related facts worth carrying: spring.profiles.include adds profiles unconditionally; spring.profiles.default (default: default) applies when none are active; and @Profile supports ! for negation.

The technique lesson matters more than the fact here. When the options are small numbers and you don't know a limit exists, "no limit" is usually right — frameworks rarely impose arbitrary caps. And ticking both 2 and 3 guaranteed a zero: they can't both be true, so at least one tick was known to be wrong at the moment you made it.

Memory hook: Unlimited active profiles, comma-separated. Any matching @Profile registers the bean.

② Testing 4 misses

100% → 33%, but look at the content before concluding it decayed. Three of these four hinge on a fabricated name. The knowledge is largely intact; the filter isn't.

Q5 · Committing a test transaction two invented annotations

@Commit or @Rollback(false) — both work

Your answer: @NoRollback and @NoRollback(true). The same invention offered twice, and you took both — while the two genuine answers sat unticked.

Spring's test support rolls back by default, which is the opposite of production. Two ways to override, and they're equivalent:

AnnotationEffect
@Commitcommit after the test — semantically explicit
@Rollback(false)identical effect
@Rollback(true)the default — usually written implicitly
@Test @Transactional @Commit
void persistsForReal() { … }        // survives the test

@Test @Transactional
void rolledBackAutomatically() { … } // the default

Both work at class level or method level, with method beating class. And remember the pairing from review #7: a rolled-back test never exercises the real commit, so constraint violations that surface only at flush time can hide — which is exactly when you'd reach for @Commit.

Memory hook: Tests roll back by default. @Commit and @Rollback(false) both flip it. There is no @NoRollback.
Q17 · @SpringBootTest web environments invented constant

Four values: MOCK · RANDOM_PORT · DEFINED_PORT · NONE

Your answer: you ticked LOCALE_PORT. "Locale" is about language and region — it has nothing to do with ports. The word you were reaching for is "local", and even that isn't one of them.
ValueServer?Use with
MOCK (default)no — mock servlet environmentMockMvc
RANDOM_PORTyes, random portTestRestTemplate, WebTestClient
DEFINED_PORTyes, the configured portsame
NONEno web features at allplain service tests

The consequences chain together, and you've met them before: MOCK means no TestRestTemplate (there's no server to call), and a real port means no @AutoConfigureMockMvc (MockMvc's whole point is that there's no server). @LocalServerPort injects whichever port RANDOM_PORT chose.

Memory hook: MOCK · RANDOM_PORT · DEFINED_PORT · NONE. Four constants. MOCK ⇒ MockMvc; a real port ⇒ TestRestTemplate.
Q47 · What @SpringBootTest is meta-annotated with taught in #8

@ExtendWith(SpringExtension.class) — JUnit 5

Your answer: both @RunWith(…) options. Every option mixed the two frameworks; you had to spot which pairing is coherent.

The two ecosystems don't interchange — and each option in that question paired one framework's annotation with the other's class:

JUnitAnnotationSpring class
4@RunWithSpringRunner (= SpringJUnit4ClassRunner)
5@ExtendWithSpringExtension

@RunWith(SpringExtension.class) and @ExtendWith(SpringRunner.class) are both incoherent — a JUnit 4 runner slot given a JUnit 5 extension, and vice versa. Match the version on both sides and only one option survives.

The practical fact from review #8: since Boot 2.1 the extension is baked into @SpringBootTest, so writing @ExtendWith yourself is redundant — and @RunWith on a JUnit 5 class is silently ignored, leaving every @Autowired field null.

Memory hook: JUnit 4 = @RunWith + SpringRunner. JUnit 5 = @ExtendWith + SpringExtension. Never cross them.
Q32 · Where Spring provides mock objects

Environment and JNDI — not RMI, not JMX

Your answer: you ticked RMI. You correctly rejected JMX, so the boundary was half there.

Spring's spring-test module ships mock implementations for a specific, small set of things — the ones that are awkward to stand up in a unit test:

AreaMocks provided
EnvironmentMockEnvironment, MockPropertySource
JNDISimpleNamingContextBuilder — a fake JNDI tree
Servlet APIMockHttpServletRequest/Response, MockHttpSession, MockServletContext
Reactive webMockServerHttpRequest/Response
RMInone
JMXnone — you need a real MBeanServer

The organising idea: Spring mocks the things it abstracts over — the Environment, the Servlet API, JNDI lookups. RMI and JMX are JVM/network facilities Spring merely integrates with; there's no Spring abstraction to substitute.

The servlet mocks are the ones you use constantly without noticing — they're what MockMvc is built on.

Memory hook: Spring mocks what it abstracts: Environment, JNDI, the Servlet API. Not RMI, not JMX.

③ Spring MVC 3 misses

50% — and the MVC clinic is the one clinic you haven't drilled. Two of these three are in it.

Q37 · Statements about @RequestMapping MVC clinic §6

It maps every HTTP verb by default, and path takes an array

Your answer: under-selected — you took one of the two correct statements. You correctly rejected both false ones, which is the harder half.
StatementVerdict
Maps all HTTP methods unless method is setTRUE — the reason @GetMapping exists
path/value accept an array of StringsTRUE@RequestMapping({"/users","/members"})
Method-level onlyfalse — class and method; it's the only one that does both
Redundant under @RestControllerfalse — method names are never auto-mapped

The last distractor is worth a moment: Spring never derives a URL from a method name. @RestController only means "write the return value to the body" — you still declare every mapping. That's a different framework's convention (Rails, JAX-RS with some configs), not Spring's.

And the narrowing attributes beyond method: params, headers, consumes, produces.

Memory hook: Bare @RequestMapping = every verb. path takes an array. Class or method level — the only mapping annotation that does both.
Q43 · Mapping an exception to a status code invented annotation

@ResponseStatus(HttpStatus.NOT_FOUND)404

Your answer: @HttpResponseStatus, 500 and @ResponseStatus, 500. Two errors compounded: an invented annotation, and NOT_FOUND read as 500.

HttpStatus.NOT_FOUND is 404 — the enum constant names the status directly. Worth having the common ones cold, since they appear constantly:

ConstantCodeConstantCode
OK200BAD_REQUEST400
CREATED201UNAUTHORIZED401
NO_CONTENT204FORBIDDEN403
MOVED_PERMANENTLY301NOT_FOUND404
FOUND302INTERNAL_SERVER_ERROR500
NOT_MODIFIED304SERVICE_UNAVAILABLE503
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Not Found")
public class MyException extends RuntimeException { }
// thrown from a controller → client receives 404

From the MVC clinic: @ResponseStatus works on a handler method or an exception class, and it overrides status set by other means — including a redirect's default 302. The programmatic equivalent is ResponseStatusException (Spring 5+), which saves you a class per status.

Memory hook: @ResponseStatus — no "Http" prefix. NOT_FOUND = 404, INTERNAL_SERVER_ERROR = 500.
Q57 · The default template engine

Thymeleaf

Your answer: JSP and JSON. JSON isn't a template engine at all — it's a data format. JSP is a real engine but explicitly not Boot's choice.
EngineDefault?Starter
Thymeleafyesspring-boot-starter-thymeleaf
FreeMarkernospring-boot-starter-freemarker
Mustachenospring-boot-starter-mustache
Groovy Templatesnospring-boot-starter-groovy-templates
JSPno — actively discouraged

Why Boot pushes away from JSP is the interesting part: JSP doesn't work in an executable fat jar. It requires a real servlet container with a JSP compiler and an exploded WAR layout, so java -jar can't serve it. Thymeleaf is plain files on the classpath, which works everywhere — and its "natural templates" are valid HTML that opens in a browser without a server.

That connects to a fact you already know: fat jars nest dependencies under BOOT-INF/lib, and JSP's tooling can't see inside them. The template-engine default is a consequence of the packaging model.

Memory hook: Thymeleaf is the default because JSP can't work inside an executable jar. JSON is a data format, not a template engine.

④ Data Management 2 misses

82% — your best Data score of the series, and it has now held 75–82% across three papers since the clinic. Both misses are in that clinic.

Q38 · The JDBC transaction manager Data clinic §3 · missed for the third time

DataSourceTransactionManager — named after the resource, not the technology

Your answer: JDBCTransactionManager and JDBCDataSourceTransactionManager. Two of the three invented "JDBC…" options — and you also ticked JDBCPlatformTransactionManager on attempt #8.

The rule, one more time, because it generalises: Spring's transaction managers are named after the resource they hold, never after the technology or the interface:

HoldsClass
a DataSourceDataSourceTransactionManager
a JPA EntityManagerFactoryJpaTransactionManager
a Hibernate SessionFactoryHibernateTransactionManager
a JTA UserTransactionJtaTransactionManager
an R2DBC connectionR2dbcTransactionManager

No Spring class in this area starts with JDBC. That single observation eliminates three of the four options without knowing anything else — which is exactly the check that would have converted this mark on all three attempts.

Note the option shape too: JDBCPlatformTransactionManager puts the interface name inside the implementation name. Real Spring implementations don't do that — DataSourceTransactionManager implements PlatformTransactionManager without saying so.

Memory hook: Named after what it wraps: DataSource → DataSourceTransactionManager. Nothing in Spring is called JDBC*TransactionManager.
Q46 · Finder-method comparison keywords Data clinic §8

LessThan and IsDifferentOf and BiggerThan are inventions

Your answer: you ticked DifferentOf. You correctly rejected BiggerThan, so the filter was working on one of the two fakes.

The keyword vocabulary is finite and closed — anything outside it throws PropertyReferenceException at application startup, not at call time:

Real keywordSQLInvented look-alike
Is / Equals= ?
Not / IsNot<> ?DifferentOf
LessThan / LessThanEqual< ? / <= ?SmallerThan
GreaterThan / GreaterThanEqual> ? / >= ?BiggerThan
BetweenBETWEEN ? AND ?
IsNull / IsNotNullIS [NOT] NULLIsDifferentNull
Like, StartingWith, Containing, In, True/False, IgnoreCase, OrderBy…the rest of the vocabulary

The invented ones share a tell: they use everyday comparative English (bigger, smaller, different) where Spring Data uses the terms from SQL and the Comparable APIgreater, less, not. If a keyword sounds conversational rather than technical, distrust it.

Memory hook: Spring Data speaks SQL: GreaterThan, LessThan, Not. Not conversational English: BiggerThan, SmallerThan, DifferentOf.

⑤ Spring Security 2 misses

33% off just two misses — and both were invented names.

Securing the service layer two invented annotations

@Secured and @PreAuthorize, on methods

Your answer: "@Secure, @Authorize, classes" and "@Secure, @Authorize, methods". You ticked both options containing the same two invented names — and the difference between them (classes vs methods) was the only thing you were comparing.

The real method-security family, with the switch each one needs:

AnnotationEnabled bySpEL?
@Secured("ROLE_ADMIN")securedEnabled = trueno — role names only
@PreAuthorize("hasRole('ADMIN')")prePostEnabled = trueyes
@PostAuthorize, @PreFilter, @PostFilterprePostEnabled = trueyes
@RolesAllowed (JSR-250)jsr250Enabled = trueno

Switched on with @EnableGlobalMethodSecurity(prePostEnabled = true) (Security 5) or @EnableMethodSecurity (Security 6, where prePostEnabled is on by default).

Worth noting the exam's own caveat: both annotations can go on a class as well as a method — the "classes" option failed only because of @Secure. So the invented name was the entire question; the classes-vs-methods distinction was a decoy.

The one-letter trap is the thing to internalise: @Secured, past tense. And the "authorize" family always carries a position prefix — @PreAuthorize, @PostAuthorize — never a bare @Authorize.

Memory hook: @Secured (roles only) and @PreAuthorize (SpEL). Never @Secure, never bare @Authorize.
Q59 · Restricting endpoints by URL pattern invented method

antMatchers(), mvcMatchers() — and regexMatchers()

Your answer: you ticked restrict(). You correctly rejected match(), so one of the two fakes was filtered.
MethodPattern styleNote
antMatchers("/admin/**")Ant pathsthe classic
mvcMatchers("/admin")Spring MVC pathsrecommended — matches how MVC itself resolves URLs
regexMatchers("^/api/v[0-9]+/.*")regular expressionsfor complex cases
anyRequest()everythingalways last

Why mvcMatchers is recommended is a real security point: antMatchers("/admin") matches only that exact string, while Spring MVC would also serve /admin/, /admin.html and (historically) /admin;jsessionid=…. So an Ant matcher can leave a route reachable but unprotected. mvcMatchers uses the same matching Spring MVC uses, closing that gap.

Note the naming convention across all three: every one ends in Matchers. restrict() and match() both break it — the API describes what it matches on, not what it does with the result. (In Spring Security 6 these were unified as requestMatchers(); your exam targets 5.x.)

Memory hook: ant · mvc · regex — all end in Matchers. Prefer mvcMatchers: Ant patterns can miss /admin/ and /admin.html.

⑥ Spring Boot 1 miss

86% — up 30 points, from your worst section to your best, in one day. Actuator, which had cost you marks in four consecutive papers, cost you nothing here. One miss, and it's a fine detail.

Q27 · Micrometer Gauge semantics Boot clinic §3 · also #3

A polled snapshot of a value you maintain — not cumulative, and it never updates itself

Your answer: you ticked "gauges are suitable for cumulative metrics" and "the Gauge bean automatically updates the value it tracks". Both describe a Counter. You got the other three right.

The code in that question makes the mechanism visible — and it's exactly why the distinction matters:

@Bean AtomicInteger gaugeValue() { return new AtomicInteger(0); }

@Bean Gauge customGauge(MeterRegistry reg, AtomicInteger gaugeValue) {
    return Gauge.builder("custom.gauge.value", gaugeValue, AtomicInteger::get)
                .register(reg);                  // ← registers a SUPPLIER, not a value
}

// the application must move the value itself:
@GetMapping("/increment")
String increment() { gaugeValue.incrementAndGet(); return "ok"; }

The gauge holds a function, not a number. When the registry is scraped it calls AtomicInteger::get and reports whatever it finds. It never accumulates, never averages, and does nothing on its own — which is precisely why the @GetMapping has to increment the AtomicInteger explicitly.

MeterAnswersWho updates it
Gauge"what is it now?"you — the gauge just samples
Counter"how many so far?"you call increment(); it accumulates
Timer"how long, how often?"you record; it aggregates

One trap in the code worth knowing: the gauge holds a weak reference to its source. If the AtomicInteger were a local rather than a @Bean, it could be garbage collected and the gauge would report NaN. Declaring it as a bean is what keeps it alive.

Memory hook: A Gauge registers a supplier and samples it on scrape. Cumulative ⇒ Counter. The gauge never moves the value — your code does.

Your close-the-gap checklist — attempt #10

The 18 facts, one line each
How to improve your answers — the specific change (1) Run the existence check on every option that names something. Before ticking any class, annotation, method or constant, ask "have I actually seen this, or does it just sound right?" If the honest answer is the second, that's a no. On this paper alone it was worth 8 marks — double your gap, for zero study time. Do this first, on every question, before you think about the topic at all. (2) When two options are variants of the same invented name, that's the signal. Q5 offered @NoRollback twice; Q22 offered two ProxyMode spellings; Q38 offered three JDBC… names. Exam writers pad with variants of a fake to make it look like a family. If two options differ only in decoration, both are usually wrong and the answer is elsewhere. (3) Drill the MVC clinic — it's the one you haven't done. Data and Boot both jumped after theirs; MVC is at 50% and its clinic covers Q37 and Q43 directly. (4) Keep the clock where it is, then extend it. Two papers at ~42 minutes is real progress from 29. You still have 87 minutes spare. Target 60+, and spend the extra time on step (1). (5) Then Spring Core. Five genuine-knowledge marks in Lessons 1–3 — but you don't need them to pass.

Where you actually are, after ten attempts

Proven: topic clinics lift a section 18–30 points and it holds — Data 57→75→81→82, Boot 56→86. Two of three are done, and those are now your two best sections. Fixed: under-selection (5 marks in #5 → 1 today) and the clock (29 → 42 minutes, held over two papers). Remaining: one habit worth 8 marks on this paper, one un-drilled clinic, and about five marks of genuine Spring Core detail.

You have been within 6 marks of the pass on every paper since #7, and this one had 8 free marks in it. The knowledge is not the constraint any more.

I'm your teacher — ask me anything. The highest-value ask right now is "drill the fakes" — a round made entirely of real-versus-invented Spring names, which is worth more than any topic revision on this evidence. Or say "drill the MVC clinic" (the one you haven't done), "quiz me on the 18" for this attempt, or "merged round" for all 194 corrected facts from the ten reviews.
← Dashboard ← Review #9 MVC clinic Boot clinic