44/60 = 73%, against a 76% pass mark. 46/60 was the pass, so you missed it by two
questions. After three passes in a row this one breaks the run — and it is not spread evenly.
Spring Core went 96% → 61% and supplied nine of the sixteen misses. Every other
section is at or near its best: Data 89%, Boot 85%, MVC 80%, Security 100%.
You also took 30 minutes longer than #17 and scored seven marks lower, so this was not haste. It was
recall. This page is about Core, about the three questions where you ticked nothing false, and about the eight misses
that were already answered on this site.
The section sizes come out exactly this time. Data 8/9 = 88.9%, MVC 4/5 = 80%, Testing 4/7 = 57.1%,
Boot 11/13 = 84.6% and Core 14/23 = 60.9% are the only sizes that produce those percentages with those miss counts
and still add up to 60. That leaves Security 3/3.
Core is 23 of the 60 questions — 38% of the paper. It is the one section you cannot let slide,
because it is bigger than MVC, Testing and Security put together.
46/60 is the lowest pass. You had 44. Three of your sixteen misses had no false tick at all — Q16, Q30 and Q39. On each of those you judged every option you ticked correctly and then stopped before taking the rest. Those three alone would have passed this paper, with 55 minutes still on the clock.
| If you had… | Score | Result |
|---|---|---|
| Taken every true option on Q16, Q30, Q39 | 47 | Pass (78%) |
| …and fixed the eight repeats | 52+ | 87% |
| What actually happened | 44 | 73% — two short |
| Attempt #17 | Attempt #18 | Result | |
|---|---|---|---|
| Score | 51/60 (85%) | 44/60 (73%) | −7 · first fail since #14 |
| Misses | 9 | 16 | +7 |
| Questions with a false tick | 7 | 13 | +6 |
| Stopped short (no false tick) | 2 | 3 | +1 |
| Left blank | 0 | 0 | Held — 60/60 answered, sixth paper running |
| Spring Core misses | 1 | 9 | +8 |
| Data + MVC + Security misses | 6 | 2 | −4 |
| Time | 44m 22s | 1h 14m 45s | +30m, and −7 marks |
Read the two middle rows together. The three sections #17's routine drilled — Data, MVC and the trap shapes — went from six misses to two. The routine works. What it did not cover collapsed. And the extra half hour bought nothing, which tells you these were not careless errors: on the three "stopped short" questions you had all the time in the world and still stopped.
#17's page ended with a 30-minute routine. Here is exactly what each section got, and what it did next:
| Section | Time in #17's routine | #17 → #18 | Misses |
|---|---|---|---|
| Data Management | 10 min — its own clinic | 70% → 89% | 3 → 1 |
| Spring MVC | 5 min | 71% → 80% | 2 → 1 |
| Spring Security | none needed | 100% → 100% | 0 → 0 |
| Spring Boot | mixed drill only | 89% → 85% | 1 → 2 |
| Testing | 5 min | 75% → 57% | 2 → 3 |
| Spring Core | mixed drill only | 96% → 61% | 1 → 9 |
Every section with its own block rose. Every section without one fell. This is the third time the site has recorded it: #16 → #17 (Core and Boot up, the other three down), the mixed practice set (Boot up, MVC and Data down), and now. Your score is tracking which section you revised most recently, not what you know.
The fix is not a better rotation — rotation is the problem. It is a short pass over all six sections before every paper, weighted by section size. Core gets the most minutes not because it is your weakest but because it is 23 of 60 questions. The routine at the bottom of this page is built that way.
There is a revision clinic for Data, MVC, Testing, Boot and Security. There is none for Spring Core — the biggest section on the paper. The closest things are two drill pages, Container and Core internals, plus lessons 1–7.
That gap lines up exactly with where the marks went. Ask me to build the Spring Core clinic — see the box at the bottom — and this paper's nine misses become its spine.
Two were drilled six days before this paper. One you had previously got right, and the page said so at the time. These eight marks need no new study, only recall.
| Q | Topic | Already on this site | Then → now |
|---|---|---|---|
| Q19 | Singletons are eager, prototypes are lazy | #17's mixed drill, six days before — "Singletons are created eagerly by an ApplicationContext" was a drill answer | Drilled as true → ticked "singletons are lazy" |
| Q41 | @RequestMapping statements | #10 Q37 and #17 Q41 — same question twice already | Third time. New false tick each time |
| Q5 | Where Spring provides mock objects | #10 Q32 — same question, and in that page's hook list | Ticked RMI again — the identical error |
| Q23 | @PostConstruct need not be public | #7 — that page says: "you were right to reject must be public — private works" | Rejected it correctly → now ticked it |
| Q39 | Web-aware-only bean scopes | #14, #8, #1, lesson 4 | Fourth sitting. Stopped short of all three |
| Q30 | Why Spring is "lightweight" | #9 Q22 — same question | Stopped short both times |
| Q54 | this() matches the proxy | #7's AOP table, mixed set's designator table | Ticked "direct implementors only" |
| Q10 | What changes the scan base packages | #14 Q23, Boot clinic | Ticked @EnableAutoConfiguration |
Q19 is the one to sit with. Six days before this paper you answered a drill that said in plain words that singletons are created eagerly. On the paper you ticked "singleton-scoped beans are lazy-initialized by default". Answering a drill once does not make the fact yours — that is the whole argument for the short six-section pass rather than one deep session.
| Bucket | Marks | What it costs you |
|---|---|---|
| The eight repeats | 8 | No new material. Q5, Q10, Q19, Q23, Q30, Q39, Q41, Q54 |
| Stopped short on a multi-answer | 3 | Q16, Q30, Q39 — this alone is the pass |
| A stricter rule than Spring actually has | 4 | Q6, Q23, Q25, Q57 — the shape drill |
| AOP designator precision | 2 | Q22 (within takes a type pattern), Q54 (this = proxy) |
| Genuinely new | 3 | Q6 (containsBean), Q47 (@MockBean targets), Q57 (nested property paths) |
The rows overlap, so don't add them up. Only three of the sixteen were new to you. Thirteen were facts this site has already written down. Get back to 51+ and then past it — the ceiling you showed on #17 is still the real number.
| Q | Topic | What went wrong | The answer |
|---|---|---|---|
| Q1–4 | Actuator base path | + /boot/actuator | http://localhost:8080/actuator |
| Q5 | Where Spring provides mocks | + RMI — 2nd time | Environment · JNDI |
| Q6 | Checking a bean exists | + hasBean(…) — invented | containsBean("productService") |
| Q10 | Changing the scan base packages | + @EnableAutoConfiguration | @SpringBootApplication · @ComponentScan |
| Q16 | Web integration test clients | Stopped short — all 3 were true | MockMvc · WebTestClient · TestRestTemplate |
| Q19 | Singleton vs prototype init | + "singletons are lazy" | Singletons eager · prototypes on demand |
| Q22 | Valid pointcut expressions | + within(… throws NPE) | within() takes a type pattern only |
| Q23 | @PostConstruct requirements | + "must be public" | void, no args, any visibility, non-static |
| Q25 | AnnotationConfigApplicationContext | + "must be @Configuration" | Lite mode works · by type · NoUniqueBeanDefinitionException |
| Q30 | Why Spring is "lightweight" | Stopped short — 2 were true | No JEE server · low overhead |
| Q39 | Web-aware-only scopes | Stopped short — 3 were true | request · session · application |
| Q41 | @RequestMapping — which is incorrect | + "can be restricted to one verb" (a true statement) | "Defaults to GET only" is the false one |
| Q47 | @MockBean on method parameters | + "yes" | No — @Target({TYPE, FIELD}) |
| Q51 | External config + profiles | + "spring.profiles.active inside application-prod is enough" | A profile file can never switch on its own profile |
| Q54 | this(Interface) | + "direct implementors only" | Matches when the proxy is an instance of the type |
| Q57 | Nested property finder | + findByAddressWithZipCode | findByAddressZipCode · findByAddress_ZipCode |
Eight of the sixteen misses are one of three shapes. Recognising the shape is worth more than any single fact, because the shape comes back on every paper.
On these three you ticked nothing that was wrong. You simply stopped before taking every true option. Q16 had three true clients and you took two. Q30 had two true statements. Q39 had three true scopes. Those three marks are the difference between 44 and 47.
It is the fourth paper in a row with this shape — #16 had three, #17 had two (Q2 was five of five), this one has three. The pattern is always the same: you are right about what you tick, and you tick too few.
| Q | Options | True | You took |
|---|---|---|---|
| Q16 | 5 | 3 | 2 |
| Q30 | 4 | 2 | 1 |
| Q39 | 4 | 3 | 2 |
The routine, unchanged from #17 because it is still the right one: go down the options and write T or F beside each one on its own, ignoring how many you have marked. Then tick every T. You had 55 spare minutes on this paper; there is no excuse on time.
On #17 the traps were real annotations given invented jobs. This paper's traps are invented strictness: a rule that sounds like good practice, dressed up as a framework requirement. All four read like something a careful reviewer would say. None of them is true.
| Q | The plausible rule | The truth | The test that exposes it |
|---|---|---|---|
| Q23 | @PostConstruct "must be public" | Any visibility — Spring uses reflection | Spring calls it with ReflectionUtils.makeAccessible. Only void and no-args are hard rules |
| Q25 | AppConfig "must be @Configuration" | Lite mode works without it | Beans still register. What you lose is CGLIB proxying of @Bean calls |
| Q6 | context.hasBean(name) | No such method — it's containsBean | Could you write the line? It doesn't compile |
| Q57 | findByAddressWithZipCode | With is not a traversal keyword | Spring Data would look for a property called addressWithZipCode and fail at startup |
void, no args), not about style.Q41 asked which statement about @RequestMapping is incorrect. You ticked
"@RequestMapping can be configured to map exclusively to a specific HTTP method" — which is perfectly
true (method = RequestMethod.GET). The false statement was "maps only to GET by default".
The mechanical fix: when the stem contains not, incorrect, false or except, mark each option T or F first without looking at the question, then pick the odd one out. Do not try to hold the inversion in your head while reading. The explanations for this question type are themselves confusing — the practice engine prints "Incorrect. This statement is correct" — which is exactly why you sort the options before applying the polarity.
Nine misses across six different corners of the container: bean lookup, scan configuration, scope initialisation, lifecycle callbacks, context bootstrapping and AOP. None of them is deep. That is what makes the drop a revision problem rather than a knowledge problem.
containsBean(String) — by name, and there is no hasBeancontext.hasBean("productService").
You correctly rejected beanExists, containsBean(Class) and the
getBean(...) != null trick.| Call | Real? | What it does |
|---|---|---|
containsBean(String name) | REAL — BeanFactory | true if a bean or alias with that name exists, including manually registered singletons |
containsBeanDefinition(String) | REAL — ListableBeanFactory | Definitions only — a singleton registered at runtime does not count |
getBeanNamesForType(Class) | REAL | How you check by type: .length > 0 |
getBeanProvider(Class) | REAL | ObjectProvider — getIfAvailable() returns null rather than throwing |
hasBean(String) | ❌ invented | — |
beanExists(String) | ❌ invented | — |
containsBean(Class) | ❌ no such overload | Would not compile |
Why getBean(...) != null is wrong and not merely ugly:
getBean never returns null. If the bean is missing it throws
NoSuchBeanDefinitionException, so the comparison is dead code that can only blow up.
In real code you would rarely call any of these. Prefer
@Autowired(required = false), ObjectProvider<T>, Optional<T>
injection, or @ConditionalOnMissingBean. containsBean is framework-level API.
containsBean takes a String. By type it's
getBeanNamesForType(X.class).length > 0. hasBean and beanExists don't exist.@ComponentScan and @SpringBootApplication. @EnableAutoConfiguration has nothing to do with scanning.@EnableAutoConfiguration. You correctly took both
real answers and rejected @Configuration.| Annotation | Its attributes | Affects the scan? |
|---|---|---|
@ComponentScan | value/basePackages, basePackageClasses, includeFilters, excludeFilters, lazyInit, nameGenerator, scopedProxy | Yes — canonical |
@SpringBootApplication | scanBasePackages, scanBasePackageClasses (@AliasFor the two above), plus exclude, excludeName, nameGenerator, proxyBeanMethods | Yes — via the aliases |
@EnableAutoConfiguration | exclude, excludeName — that is all | No — it filters auto-configuration classes |
@Configuration | value, proxyBeanMethods, enforceUniqueMethods | No |
// type-safe and refactor-proof — the marker class pins the package
@SpringBootApplication(
scanBasePackageClasses = { com.acme.web.Marker.class, com.acme.svc.Marker.class })
public class App { }
The default: the package of the annotated class, and everything below it. That is
why the main class belongs in the root package — put it in a sub-package and its siblings are silently
invisible. The same default applies in tests, because @SpringBootTest walks up from the test
class looking for a @SpringBootConfiguration.
Do not add a separate @ComponentScan beside
@SpringBootApplication on the same class — @SpringBootApplication already
declares one, and a second declaration overrides rather than adds. Put the attributes on
@SpringBootApplication itself.
@ComponentScan / scanBasePackages. Auto-config =
@EnableAutoConfiguration(exclude=…). One picks your beans, the other picks Boot's.singleton | prototype | |
|---|---|---|
| Created | At context refresh, before run() returns | On every getBean / injection point |
| Instances | One per container | A new one every request |
| Opt out | @Lazy on the bean, or @ComponentScan(lazyInit = true) | @Lazy is meaningless — it is already on demand |
@PostConstruct | Yes | Yes — on every instance |
@PreDestroy | Yes, at close() | Never. Spring hands the instance over and forgets it |
The nuance the exam leans on: a prototype injected into a singleton is created
once, while that singleton is being built — which is why the fourth option ("eagerly initialized only when
an instance is needed to satisfy a dependency") is marked true. For a genuinely fresh instance per use you need
ObjectProvider, @Lookup, or a scoped proxy.
One precision point: eager pre-instantiation is an ApplicationContext
behaviour (preInstantiateSingletons() during refresh()), not a
BeanFactory one. A bare DefaultListableBeanFactory is lazy throughout. The exam only ever
asks about the context.
within() takes a type pattern and nothing else. Only execution() has a throws slot.within(com.udemy..* throws NullPointerException) as valid.
You correctly accepted args(Double) and
execution(void com..App.get*()).execution( [modifiers] ret-type [declaring-type.]name(params) [throws ExPattern] )
// public void com.acme.App. get*() throws IOException
within( TypePattern ) // that's the whole grammar
within(com.acme..*) // ✅
within(com.acme..* throws NullPointerException) // ❌ parse error
execution(* com.acme..*(..) throws NullPointerException) // ✅ the legal way
| Designator | Takes | Matches on |
|---|---|---|
execution(…) | Full method signature pattern + optional throws | The method being called — the workhorse |
within(…) | Type pattern only | Any join point inside that type or package |
args(…) | Type list | Runtime argument types |
this(…) / target(…) | One type | The proxy / the target object |
@annotation, @within, @target, @args | Annotation type | Method / declaring class / runtime class / argument |
bean(…) | Bean name pattern | Spring-only, not in plain AspectJ |
Also worth knowing what Spring AOP does not support, since it is a cheap
question: call, get, set, initialization,
staticinitialization, preinitialization, handler,
adviceexecution, withincode, cflow, cflowbelow,
if. Using one of those throws IllegalArgumentException at startup. Spring AOP is
method execution only.
The option marked correct as
execution(public void com.udemy.spring.course.App.*) has no parameter parentheses, and the
parameter pattern is mandatory in the execution grammar — as pasted it would not parse.
execution(public void com.udemy.spring.course.App.*(..)) would be fine. Your mark was lost on the
within option regardless, so this changes nothing about the score. Don't learn the malformed
form.
within = where the code lives (a type pattern). execution
= what the method looks like (the only one with throws).@PostConstruct / @PreDestroy requirements ticked a false option you had this RIGHT on #7void, no parameters, non-static — any visibility| Requirement | Rule | If you break it |
|---|---|---|
| Return type | Must be void | Ignored / IllegalStateException |
| Parameters | Must take none | The container has nothing to pass |
| Visibility | Any — private works | Nothing. Spring calls
ReflectionUtils.makeAccessible |
| Static | Must not be static | Not invoked |
| Count | One per class by convention | Several is not a compile error but is not portable |
| Exceptions | May declare checked exceptions | A throw from @PostConstruct fails
bean creation (BeanCreationException) |
Where the annotations come from: javax.annotation on the exam's
stack (Spring 5.3 / Boot 2.5), jakarta.annotation from Boot 3. Either way the processor is
CommonAnnotationBeanPostProcessor, registered automatically by
AnnotationConfigApplicationContext, @ComponentScan and every Boot app — no
@EnableAnnotationLifecycle-style switch exists.
The three ways, in the order Spring runs them:
@PostConstruct → InitializingBean.afterPropertiesSet() →
@Bean(initMethod = "…"). Destruction mirrors it:
@PreDestroy → DisposableBean.destroy() → @Bean(destroyMethod = "…").
private void init() is fine.AnnotationConfigApplicationContext + getBean ticked a false option@Configuration is recommended, not requiredAppConfig.class must be annotated @Configuration for this
to work". You correctly took "retrieved by type" and "multiple beans → exception", and
rejected both the auto-close and the new-instance-per-call options.Full mode — @Configuration | Lite mode — no @Configuration | |
|---|---|---|
| Beans registered | Yes | Yes |
getBean(MyService.class) | Works | Works |
| Class CGLIB-subclassed | Yes (unless proxyBeanMethods = false) | No |
Calling myService() from another @Bean | Returns the singleton | Creates a second instance |
| Inter-bean dependencies | Method calls are fine | Must use method parameters |
The other three options, each a fact worth holding:
new AnnotationConfigApplicationContext(...) registers no shutdown hook.
Without close(), registerShutdownHook() or try-with-resources
(ConfigurableApplicationContext extends Closeable), no @PreDestroy ever runs.
Contrast SpringApplication.run(...), which does register one by default — that asymmetry is
the exam's favourite version of this question.getBean by type returns the singleton, the same instance each call, unless the bean is
prototype-scoped.NoUniqueBeanDefinitionException (a subclass of NoSuchBeanDefinitionException).
Fix with @Primary, @Qualifier, or getBean("name", MyService.class).@Configuration = lite mode = beans yes, proxying no. And a
plain context you new yourself never closes itself — SpringApplication.run does."Lightweight" means exactly two things, and the exam only ever says these two:
| Claim | Meaning |
|---|---|
| Non-invasive | Your classes stay POJOs. At worst they carry an annotation. No base class, no interface, no container-managed contract — the opposite of EJB 2.x |
| Low overhead | Small modular jars, and it runs in a plain servlet container like Tomcat. No application server |
What "lightweight" never meant: that there is no runtime (there is — the container), that it is small in scope (it is enormous), or that it is faster than alternatives. Review #9 flagged the "no runtime needed" distractor; this paper used the POJO one instead.
request, session, application — all three. (And websocket.)web", which is
not a scope. This fact has now been on four review pages and in lesson 4.| Scope | One instance per | Needs a web context? |
|---|---|---|
singleton | Container (the default) | No |
prototype | Request for the bean | No |
request | HTTP request | Yes |
session | HTTP session | Yes |
application | ServletContext | Yes |
websocket | WebSocket session | Yes |
web | ❌ does not exist | |
application vs singleton is the distinction that makes this
question non-trivial, and it is why application is the one people leave out.
singleton means one per ApplicationContext; application means one per
ServletContext, stored as a ServletContext attribute. A single web app can have more than one
context (a root context plus a DispatcherServlet child), and then a
singleton in each context gives you two instances while an application bean gives one.
Using a short-lived scope inside a singleton needs a scoped proxy:
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS), or
@RequestScope / @SessionScope / @ApplicationScope, which are the
meta-annotated shortcuts and already set the proxy mode.
this(com.example.service.ServiceInterface) ticked a false option #7's AOP table · mixed setthis() tests the proxy. target() tests the real object.ServiceInterface".
You correctly rejected the three call-site distractors.| Tests | JDK dynamic proxy | CGLIB proxy | |
|---|---|---|---|
this(T) | The proxy object | this(Interface) ✅ · this(ConcreteClass) ❌ | Both ✅ — the proxy is a subclass |
target(T) | The target (real) object | Both ✅ | Both ✅ |
The one case where they differ is a JDK dynamic proxy asked about the concrete
class: the proxy implements ServiceInterface but is not a RealService, so
this(RealService) misses while target(RealService) matches. Spring Boot proxies with
CGLIB by default (spring.aop.proxy-target-class=true since Boot 2.0), which is why the
difference rarely bites in practice and always bites on the exam.
Why none of the "call" answers can be right: Spring AOP has no call()
designator at all. It weaves at the proxy, so it only ever sees method execution on the target bean — never
the call site, and never a self-invocation from inside the same object.
this = the proxy (what the caller holds). target = the
bean inside it. They only diverge for a JDK proxy asked about the concrete class.Seven questions, three missed — the lowest section on the paper in percentage terms, and the second paper running that it has fallen. Five minutes in #17's routine was not enough because the three misses sit in three different corners: what Spring mocks, which clients exist, and where an annotation may be placed.
Environment and JNDI. Not RMI, not JMX.| Area | Mock provided | Package |
|---|---|---|
| Environment | MockEnvironment, MockPropertySource | org.springframework.mock.env |
| JNDI | SimpleNamingContextBuilder | org.springframework.mock.jndi |
| Servlet API | MockHttpServletRequest, …Response, MockHttpSession, MockServletContext, MockFilterChain, MockMultipartFile | org.springframework.mock.web |
| HTTP messages | MockHttpInputMessage, MockClientHttpRequest/Response | org.springframework.mock.http |
| RMI | none | — |
| JMX | none | — |
The rule that generates the answer: Spring mocks what it abstracts over. It
has its own Environment abstraction, its own JNDI lookup support and its own servlet-API-facing web
layer, so it ships fakes for all three. RMI and JMX are JVM/network facilities Spring merely integrates with
— testing those means using the real thing.
Small footnote for currency: SimpleNamingContextBuilder is deprecated
from Spring 5.2 in favour of third-party JNDI simulators. It is still the right exam answer on the 5.3 syllabus.
MockMvc, WebTestClient, TestRestTemplateEjbClient, MBeanClient and RemoteRmiClient, all three invented.
Every judgement you made was right. The mark went on the option you left.| Client | Real server? | Style | Auto-configured by |
|---|---|---|---|
MockMvc | No — mock DispatcherServlet | Blocking, fluent | @WebMvcTest, @AutoConfigureMockMvc |
WebTestClient | Optional — bind to a server, a controller, a context, or MockMvc | Non-blocking | @WebFluxTest, @AutoConfigureWebTestClient |
TestRestTemplate | Yes — needs a port | Blocking | @SpringBootTest(webEnvironment = RANDOM_PORT / DEFINED_PORT) |
@SpringBootTest(webEnvironment = RANDOM_PORT)
@AutoConfigureWebTestClient
class UserApiIT {
@Autowired WebTestClient web; // non-blocking, real port
@Autowired TestRestTemplate rest; // blocking, real port, never throws on 4xx/5xx
@Test void getUser() {
web.get().uri("/users/1").exchange().expectStatus().isOk();
rest.getForEntity("/users/1", User.class); // relative URL — the port is filled in
}
}
Two properties of TestRestTemplate the exam likes: it is
fault-tolerant — it never throws on a 4xx/5xx, it returns the status in the
ResponseEntity, which is the opposite of RestTemplate — and it does not follow
redirects by default. It is also not registered at all under the default
webEnvironment = MOCK, because there is no port to talk to.
And MockMvc's limit: no real container, so anything outside Spring's
own filter chain — a servlet container valve, a listener, real HTTP parsing — is never exercised. That is the
trade you make for the speed.
@MockBean on method parameters ticked a false option@Target({TYPE, FIELD}) — class level or field, never a parameter.@MockBean (Spring Boot) | @Mock (Mockito) | |
|---|---|---|
| Targets | TYPE, FIELD | FIELD, PARAMETER |
| On a test method parameter | No — won't compile | Yes, with MockitoExtension |
| In the Spring context | Yes — replaces the real bean | No — a plain object |
| Use for | Integration tests with a context | Unit tests without one |
@SpringBootTest
class OrderServiceTest {
@MockBean OrderRepository repo; // ✅ field — replaces the bean in the context
@Autowired OrderService service;
@Test void cancels(@MockBean Clock clock) { } // ❌ does not compile
@Test void cancels(@Mock Clock clock) { } // ✅ with @ExtendWith(MockitoExtension.class)
}
Two more things about @MockBean worth a mark: it is
@Repeatable, so the class-level form can be stacked; and it resets the mock after every test
method (MockReset.AFTER). Because it changes the bean definitions, each distinct set of
@MockBeans produces a separate cached context — which is the usual reason a test suite
suddenly starts several contexts.
Currency footnote: from Boot 3.4, @MockBean is deprecated in favour of
@MockitoBean. The exam is on Boot 2.5, so @MockBean is the answer.
@MockBean = class or field, in the context. @Mock =
field or parameter, no context. Parameters are Mockito's trick, not Boot's.Thirteen questions and two misses — Boot held up. Both misses are configuration mechanics rather than concepts.
http://localhost:8080/actuatorhttp://localhost:8080/boot/actuator.
You correctly rejected /bootactuator and /endpoint/actuator.| Setting | Default | Effect |
|---|---|---|
management.endpoints.web.base-path | /actuator | Set to /manage and every endpoint moves under it |
management.endpoints.web.exposure.include | health only (Boot 2.5+; info,health up to 2.4) | * exposes all; or list them |
management.endpoints.web.exposure.exclude | empty | Wins over include |
management.endpoint.<id>.enabled | true (except shutdown) | Enabled ≠ exposed — two independent switches |
management.endpoints.web.path-mapping.<id> | the endpoint id | Renames one path, e.g. health → healthcheck |
management.server.port | the app port | Move Actuator to its own port; the base path then applies there |
Enabled versus exposed is the distinction most Actuator questions turn on. Nearly
every endpoint is enabled by default (so its bean exists and JMX can see it) while only
health is exposed over HTTP. "I added the starter and /actuator/metrics 404s" is
not a bug — it is exposure.include.
/actuator, one segment, configurable via
management.endpoints.web.base-path. Only health is web-exposed by default.spring.profiles.active=prod to
application-prod.properties would be enough". You correctly took all four true
statements and rejected the spring.config.location distractor — five of six right on a six-option
question.The chicken-and-egg: Boot decides which profiles are active before it reads
profile-specific files, and it reads application-prod.properties only once prod is
already on. Since Boot 2.4 it does not even fail silently —
spring.profiles.active, spring.profiles.include and
spring.profiles.default inside a profile-specific document raise
InvalidConfigDataPropertyException and the application does not start.
# ✅ from outside the file
java -jar app.jar --spring.profiles.active=prod
SPRING_PROFILES_ACTIVE=prod java -jar app.jar
# ✅ in the NON-profile-specific application.properties
spring.profiles.active=prod
# ❌ in application-prod.properties → InvalidConfigDataPropertyException
| Default search location | Inside the jar? | Wins over |
|---|---|---|
classpath:/ | Yes | — |
classpath:/config/ | Yes | the row above |
file:./ | No | both classpath rows |
file:./config/ | No | everything above — this is where Q51's file lives |
file:./config/*/ | No | everything above |
So no extra setting was needed — ./config/ is already searched, and
"the current working directory" means the directory you launched from, not the directory holding the
jar. Two independent overrides then stack: profile-specific beats plain, and outside the jar beats
inside.
| Property | Effect | Where it may be set |
|---|---|---|
spring.config.location | Replaces the default locations | Command line, system property or env var — not in application.properties |
spring.config.additional-location | Adds to them | |
spring.config.import | Pulls in a specific extra document | Inside a properties/YAML file — this one is fine |
./config/ is searched by default. location replaces, additional-location adds.MVC improved after its five minutes in the routine. The one miss is a question you have now met three times.
@RequestMapping statement is incorrect ticked a false option 3rd time · #10 Q37 · #17 Q41@RequestMapping maps every HTTP verb — that is the false statement@RequestMapping can be configured to map the annotated method
exclusively to a specific HTTP method", which is true — so it cannot be the answer to a "which is
incorrect" question. You correctly rejected the two statements about arrays of paths and
class/method placement.The three previous sittings each had a different false tick, which tells you the fact is not the problem: the polarity is. On #10 and #17 you missed it too.
| Statement | True? |
|---|---|
Maps only GET unless method is given | FALSE — the answer. It maps GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, TRACE |
Accepts multiple paths — @RequestMapping({"/a","/b"}) | True |
Can be narrowed with method = RequestMethod.GET | True |
| Works at class and method level | True — the only mapping annotation that does both |
The full narrowing set: path/value,
method, params, headers, consumes, produces,
plus name. The shortcuts @GetMapping, @PostMapping,
@PutMapping, @DeleteMapping and @PatchMapping are
@Target(METHOD) only — a class-level mapping must be @RequestMapping. Class and
method paths concatenate.
Why the default matters in production, not just on the exam: a bare
@RequestMapping("/admin/delete") answers a GET as happily as a POST. That is
an accidental attack surface, and the reason the shortcuts exist.
@RequestMapping = every verb. And on a "which is incorrect"
question, label all four T/F first, then pick the odd one out.The biggest improvement on the paper: 70% → 89%, three misses down to one, after ten minutes on the Data clinic. This is the proof that the routine works.
findByAddressZipCode(…) or findByAddress_ZipCode(…)findByAddressWithZipCode. You correctly took both
real forms and rejected findByAddress@ZipCode.How Spring Data resolves …ByAddressZipCode: it first tries the whole
thing as one property (addressZipCode); failing that it splits at camel-case boundaries
from the right — addressZip.code, then address.zipCode — until a path resolves.
An underscore pins the boundary yourself and skips the guessing.
public interface PersonRepository extends JpaRepository<Person, Long> {
List<Person> findByAddressZipCode(ZipCode zip); // camel-case traversal
List<Person> findByAddress_ZipCode(ZipCode zip); // explicit boundary
}
Why With could never work — and the adjacent fact worth a mark:
everything between the subject keyword (find, read, get,
query, stream, count, exists, delete) and
By is free text and ignored — so findWithZipCodeByAddress(…) is legal and means
the same as findByAddress(…). But after By, every word must be a property name or a
recognised keyword. With is neither, so
findByAddressWithZipCode looks for a property called addressWithZipCode, doesn't find it,
and the application fails at startup — not at query time.
The exception to "ignored": Distinct, First and
Top are read in that gap — findDistinctTop3ByAddressZipCode(…).
_ pins the boundary. Before
By, words are decoration. After By, every word must be a property or a keyword — or it's
a startup failure.@PostConstruct but never @PreDestroycontainsBean takes a String. By type it's getBeanNamesForType(X.class).length > 0. No hasBean, no beanExists@PostConstruct: void, no args, not static. Visibility is free — private works@Configuration = lite mode: beans register, @Bean methods aren't proxied, inter-bean calls make new instancesnew yourself never closes itself. SpringApplication.run registers a shutdown hook; AnnotationConfigApplicationContext does notNoUniqueBeanDefinitionException@ComponentScan / scanBasePackages. @EnableAutoConfiguration only has exclude/excludeNamerequest, session, application, websocket. No "web" scope. application = per ServletContextwithin() takes a type pattern only. Only execution() has a throws slot. Spring AOP has no call()this() = the proxy, target() = the bean. They diverge only for a JDK proxy asked about the concrete classEnvironment, JNDI, the Servlet API. Not RMI, not JMXMockMvc (no server) · TestRestTemplate (real port, never throws) · WebTestClient (either)@MockBean = @Target({TYPE, FIELD}). Method parameters are Mockito's @Mock/actuator; only health is web-exposed by default. Enabled ≠ exposedInvalidConfigDataPropertyException since 2.4. ./config/ is searched by default; location replaces, additional-location adds@RequestMapping = every verb, and it's the only mapping annotation usable at class and method level_ pins the boundary. A bad derived name fails at startupTen questions with no topic label to prime you. Judge each option on its own, then tick every true one. Where the stem is negative, sort the options first and apply the polarity last.
@Configuration" — Spring is looser than the
option claims. The hard rules are about signatures.
(5) On a NOT question, sort first. Label all options T/F, then apply the polarity. Q41 is now three for
three against you.
(6) Time is not the constraint. You used 1h 15m of 2h 10m and still stopped short on three questions.
@MockBean's targets.
5 min — Spring Boot. Eight drills: Actuator exposure and config locations.
3 min — MVC + Data. Ten drills. Both are healthy — keep them warm.
5 min — the mixed drill. No headings, so nothing primes you.
Plus 2 min — Security. 100% for four papers running. Don't be
the one who lets the safe section slip.