This is the only lesson in the course that is not about CicloUrbana, and that is deliberate. The Ribalta network is built, tested, deployed, observed and reviewed; what is left is not another piece of the project but the ability to keep learning once there is no syllabus to follow.

And that has a technique of its own. The internet is full of material about Spring Boot, and a good part of it is out of date in a particularly treacherous way: a Spring Boot 2 tutorial does not look old — the code compiles almost the same — but it teaches javax.persistence instead of jakarta.persistence, WebSecurityConfigurerAdapter instead of SecurityFilterChain and Spring Cloud Sleuth instead of Micrometer Tracing. Knowing how to tell the difference is worth more than any list of links.

This lesson organises the resources that are worth your time, annotated and with judgement: which documentation to read and how, why the source code is the best source, how to keep up to date and plan a major version upgrade, which books are worth it and for whom, where the community is, how to practise properly, which topics are the natural next step from where you are now, and a reasoned roadmap for the next six months.

Contents

  1. Learning with judgement
  2. The official documentation and how to read it
  3. The source code as documentation
  4. Keeping up to date
  5. Planning a major version upgrade
  6. The Java ecosystem
  7. Books
  8. Certifications
  9. Community
  10. Deliberate practice
  11. Natural topics for the next step
  12. How to evaluate a resource
  13. A six-month roadmap
  14. Common Mistakes and Tips
  15. Exercises

  1. Learning with judgement

A warning before the list, because it decides whether the rest is any use.

The bottleneck is not access to information: it is attention. There is more content about Spring Boot than anyone could consume in a lifetime, and the natural impulse — bookmarking twenty links, subscribing to three newsletters, starting four courses — produces the feeling of learning without anything consolidating. The approach that does work has three traits:

Trait What it means Frequent counter-example
With a problem in front of you You learn what you need for something concrete Watching a whole course "just in case"
Writing code Typing, breaking and fixing Reading about WebFlux without opening the IDE
Spaced out Coming back to the topic days later A weekend marathon forgotten within two

And a hierarchy of sources worth internalising, from most to least reliable: the source code > the reference documentation > the official guides > books by recognised authors > conference talks > blog articles > forum answers > unreviewed generated content. It does not mean always starting at the top: it means that when two sources contradict each other, the one higher up wins.

  1. The official documentation and how to read it

Resource What it is When to reach for it
Spring Boot Reference Documentation The complete manual: autoconfiguration, properties, packaging, Actuator The daily reference. Its common properties appendix is the canonical list of everything configurable
Spring Framework Reference The core: container, AOP, transactions, MVC, validation When the question is about the mechanism, not about Boot
Spring Data JPA Reference Repositories, derived queries, projections, Specification, auditing When writing any non-trivial query
Spring Security Reference Filter chain, authorisation, OAuth2, method security Reorganised for Spring Security 6: the examples no longer use the retired adapter
spring.io guides Short tutorials on one concrete task, maintained by the team To get going with something new in half an hour
Release notes in the GitHub wiki What changes in each minor version, with the breaking changes flagged Before upgrading, always
Migration guides The route from one major version to the next When planning a major upgrade (section 5)
Javadoc The exact contract of each class When the reference says what it does but not with what precision

How to read the reference documentation without getting lost. Three tactics that change the experience:

  • Search it, do not read it top to bottom. It is written to be consulted. The section structure and the built-in search are designed to take you straight to the paragraph that answers your question.
  • Start with the properties appendix. When you are unsure whether something is configurable, the answer is usually there, with the default value — which is half the useful information.
  • Read the release notes for the version you use. It is half an hour well spent: you find out about features you have spent months reimplementing by hand.

How to read javadoc productively. It is not marketing documentation: it is the contract. What to look for in it are the three things the signature does not tell you: what happens at the edge cases (does it return null or an empty list? does it accept zero?), which exceptions it throws and when, and whether it is thread-safe. That last piece frequently appears in a single sentence of the class javadoc, and it is exactly the one you go looking for when something fails under load.

A concrete worked example, because the technique is better understood in action. Suppose you want to know whether you can limit the size of the async executor's queue and what happens when it fills up:

Step Where you look What you get
1 The properties appendix, searching for task.execution pool.queue-capacity and pool.max-size exist, with their default values
2 TaskExecutionProperties in the source code The typed, complete list, with the defaults on the fields
3 The javadoc of ThreadPoolTaskExecutor That the queue fills before the pool grows, and which rejection policy kicks in afterwards
4 The "Task Execution and Scheduling" section of the reference How Spring Boot wires it and when your bean replaces theirs

Four lookups, five minutes, and an answer that does not depend on any article having got it right.

  1. The source code as documentation

Here is the tip with the best effort-to-benefit ratio in the whole lesson: read Spring's code. It is open, it is on GitHub, it is reasonably commented and it answers questions no documentation answers.

Why it is the best source. The documentation describes the intention; the code describes the behaviour. When something does not work as you expected, the difference between the two is exactly where your problem is. And unlike an article, the code is never out of date with respect to itself.

Three things worth learning to read:

The autoconfiguration classes. Searching for *AutoConfiguration in the spring-boot-autoconfigure tree and reading one all the way through — DataSourceAutoConfiguration, JacksonAutoConfiguration or WebMvcAutoConfiguration — dismantles the feeling of magic in one go. You see which conditions (@ConditionalOnClass, @ConditionalOnMissingBean) activate each bean, and therefore what you have to do to replace it: almost always, declare your own.

The *Properties classes. ServerProperties, JpaProperties or DataSourceProperties are the exact, typed list of what can be configured, with their default values on the fields. It is usually faster than searching the documentation.

The spring.factories and AutoConfiguration.imports files. The file META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports is literally the list of everything Spring Boot can autoconfigure. Reading it once gives you a sense of the framework's scope that nothing else does.

# Search in your own local Maven repository, without leaving the machine
find ~/.m2 -name "spring-boot-autoconfigure-*-sources.jar"
./mvnw dependency:sources          # downloads the sources of every dependency

With the sources downloaded, Ctrl+B on any annotation in the IDE takes you to its definition. That is the habit: when you do not understand why something behaves the way it does, go in.

  1. Keeping up to date

The release cycle and support

Spring Boot ships one minor version every six months (November and May, roughly) and bug-fix releases every month. What matters is not the calendar but the support policy:

Type What it includes Typical duration
OSS support Bug fixes and security fixes, free ~12 months from the minor version's release
Commercial support Security fixes beyond OSS, paid Several additional years
End of life Nothing: not even security patches —

The practical consequence is harsh and worth accepting: an application in production needs to move up a minor version at least once a year. It is not an optional improvement, it is security maintenance. A project that has stayed on the same minor version for three years is not "stable": it is accumulating known vulnerabilities with no patch.

The healthy strategy is to upgrade early and often: going from 3.3 to 3.4 as soon as it is out and there is time is a few hours' work; going from 2.7 to 3.x four years late is a project of weeks.

Where to find out

Source What it gives you Frequency
The official Spring blog Releases, security advisories and articles from the team The primary source; subscribe
This Week in Spring A weekly digest of the ecosystem from the developer relations team Weekly, read in five minutes
Spring Office Hours A regular session with the team, with real questions Video, for the commute
InfoQ (Java) Analysis with perspective, not just announcements Monthly
GitHub release notes The exact detail, with the breaking changes Before every upgrade
Spring security advisories The CVEs that affect you A mandatory subscription on a real project

The last row is not negotiable: a known vulnerability in such a widespread framework is exploited en masse within hours of being published.

How to read release notes in ten minutes. They always have the same structure and it is worth walking it in this order: first "Breaking Changes", which is the only part that can break you and usually takes up half a screen; then "Deprecations", so you know what you have to start changing even though it still works today; then "Dependency Upgrades", where you see which versions of Hibernate, Jackson or Tomcat come inside — and whether any of them affects you directly; and finally "New and Noteworthy", which is the fun part and the least urgent. Reading them backwards, starting with the new features, is why so many people get caught out.

  1. Planning a major version upgrade

Moving from one major version to the next — the paradigmatic case being Spring Boot 2.7 → 3.0, with the jump from javax to jakarta — is not a change of number. This is the procedure that works.

flowchart LR
    A["0. Test suite<br/>green"] --> B["1. Read the<br/>migration guide"]
    B --> C["2. properties-migrator:<br/>fix the YAML"]
    C --> D["3. OpenRewrite:<br/>the mechanical part"]
    D --> E["4. One minor version<br/>at a time"]
    E --> F["5. Review what the<br/>BOM does not manage"]
    F --> G["6. Deploy to pre<br/>and measure"]
    E -->|"suite red"| E

Step 0: have tests. Without the module 6 suite, a major upgrade is a leap into the void. If the project does not have them, writing them is the first step of the migration, not a separate task.

Step 1: read the migration guide in full, before touching anything. It is in the Spring Boot repository wiki and lists the breaking changes one by one. Half an hour of reading saves days.

Step 2: spring-boot-properties-migrator. A temporary dependency that, at startup, reports the renamed or removed properties and temporarily applies the equivalences:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-properties-migrator</artifactId>
    <scope>runtime</scope>
</dependency>

You start up, read the report in the log, fix the YAML and remove the dependency. Leaving it in is a classic mistake: it masks the problems instead of solving them.

Step 3: OpenRewrite for the mechanical part. The repetitive migrations — javax.* to jakarta.*, retired annotations, renamed APIs — are done by an automatic recipe:

./mvnw org.openrewrite.maven:rewrite-maven-plugin:run \
  -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_3

It is a sweeping change, so it goes in a commit of its own, with nothing else mixed in, and is reviewed by reading the diff. OpenRewrite does 80% of the mechanical work; the remaining 20% — the part that requires judgement — is still yours.

Step 4: go up one minor version at a time. You do not jump from 2.5 to 3.3: you go 2.5 → 2.6 → 2.7 → 3.0 → …, with the suite green at every rung. If something breaks, you know exactly which rung broke it.

Step 5: review what the BOM does not manage. The dependencies with their own <version> — in CicloUrbana, JJWT, ShedLock, MapStruct, Resilience4j — are not upgraded by Spring Boot. They are the ones left behind and the ones that produce surprises.

Step 6: deploy to pre and measure. A major upgrade can change performance in either direction. The module 9 k6 baseline exists for exactly this.

  1. The Java ecosystem

Spring Boot lives on top of Java, and for some years now Java has been moving fast.

LTS versions and what they bring. The extended-support versions come out every two years, and they are the ones used in production:

Version Most relevant additions for a Spring application
Java 17 record, sealed, pattern matching in instanceof, text blocks, switch as an expression
Java 21 Virtual threads, pattern matching in switch, record patterns, sequenced collections
Java 25 Consolidation of the above, garbage collector and startup improvements

Of all the above, what CicloUrbana already uses daily are the records for the DTOs, the text blocks in the JPQL queries, switch as an expression and virtual threads.

Project Loom and virtual threads. It is the most important conceptual change in Java in the last decade: a thread that, when it blocks on I/O, releases the operating system thread instead of occupying it. For a blocking application with a lot of database waiting — which is the vast majority of business applications — it enables high concurrency with no reactive stack.

// Java 21: a million waiting threads, without exhausting the operating system
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 1_000_000).forEach(i ->
            executor.submit(() -> { Thread.sleep(Duration.ofSeconds(1)); return i; }));
}   // try-with-resources waits for them all to finish: no shutdown() needed

That fragment with platform threads would exhaust memory long before reaching a million. It is worth understanding thoroughly, including its two traps: pinning with synchronized, and the fact that the real limit becomes the connection pool, as we saw in 09-01.

GraalVM and native images. Compiling the application to a native executable reduces startup from seconds to milliseconds and memory to a fraction. In exchange, compilation takes minutes, reflection needs explicit RuntimeHints and sustained throughput may be somewhat lower than on the JVM. Its clear case is serverless functions and short-lived processes; for a service that starts once a day, it contributes little.

And an underlying idea: Spring Boot is the most visible part of your work, but the part that transfers most is Java. A good grasp of the language, the JVM and concurrency outlives any framework.

  1. Books

Only widely recognised works, with who each one is for. A book is read in weeks and consulted for years; it is the format with the best long-term return.

Book Author Who it is for and what for
Spring in Action Craig Walls A broad, practical tour of Spring; a good complement to this course, especially for the areas we have not touched
Spring Boot: Up and Running Mark Heckler A direct focus on Boot, with good explanations of autoconfiguration
Effective Java Joshua Bloch The book that most improves your Java. Ninety items on API design, generics, equals, immutability and concurrency. If you read only one, this
Clean Code Robert C. Martin Names, functions and comments; the basis of module 10, though it should be read with your own judgement and not as dogma
Refactoring (2nd ed.) Martin Fowler The catalogue of safe transformations; used as a reference, not read cover to cover
Patterns of Enterprise Application Architecture Martin Fowler Explains where the repository, the data mapper, the unit of work and the anaemic model come from
Domain-Driven Design Eric Evans The original on ubiquitous language, aggregates and bounded contexts. Dense; many people start with the next one
Implementing Domain-Driven Design Vaughn Vernon The applicable version of DDD, with code
Growing Object-Oriented Software, Guided by Tests Freeman and Pryce How tests drive the design; the best book on the "why" of TDD
Unit Testing: Principles, Practices, and Patterns Vladimir Khorikov What to test and what not to, and why verifying interactions produces brittle tests
High-Performance Java Persistence Vlad Mihalcea The serious reference on JPA and Hibernate: N+1, identifiers, locks, batching, caching
Designing Data-Intensive Applications Martin Kleppmann Replication, partitioning, consistency and distributed transactions. Essential before splitting a system
Building Microservices (2nd ed.) Sam Newman Honest about the costs; the book to read before deciding to split
Site Reliability Engineering Various (Google) SLIs, SLOs, error budgets and on-call. Free online
Observability Engineering Majors, Fong-Jones and Miranda The conceptual framework behind module 9
Accelerate Forsgren, Humble and Kim The research behind module 8's DORA metrics
The Pragmatic Programmer Hunt and Thomas Craft and attitude, beyond any technology

If you had to pick three for the next six months, starting from where you are: Effective Java (it makes you a better Java programmer, not a better Spring user), High-Performance Java Persistence (because the database is where the time is) and Designing Data-Intensive Applications (because it is the one that widens the view beyond a single application).

  1. Certifications

The ecosystem's reference certification is the VMware Spring Professional, which covers the container, AOP, data, MVC, security, Boot and testing: roughly the syllabus of this course.

An honest assessment:

In favour Against
It gives structure and a deadline, which organises study for many people It costs money and several weeks of preparation
It forces you to cover areas you would otherwise avoid It rewards memorising details you could look up in a second
In some markets and consultancies, it filters CVs Nobody with experience hires on the basis of a certification
The syllabus is well chosen It expires: the ecosystem moves faster than the exam

When it is worth it, concretely: if you work in a consultancy where it influences project assignment or your rate; if your employer pays for it and gives you the time; or if you need external structure to study consistently. When it is not: if the goal is to demonstrate that you know your stuff. For that, a well-made public project — with tests, a pipeline and a decent README — says far more, and it is what actually gets looked at in a technical interview.

There are also adjacent certifications that in many contexts are worth more than the Spring one: the Kubernetes ones (CKA and CKAD) and the cloud providers', because they cover an area where demand clearly outstrips supply and where the exam is practical, with a real terminal, rather than a battery of questions. If the goal is employability and you already know Spring Boot, that direction is usually the better investment.

  1. Community

Place What it is for How to get the most from it
Stack Overflow (tags spring-boot, spring-data-jpa) Concrete questions already solved Check the date and the version of the answers; and sort by votes, not by acceptance
The Spring issue tracker (GitHub) Finding out whether "that weird thing" is a known bug Search the literal error message before asking anywhere
The projects' GitHub Discussions Design questions answered by the team Hugely underused
SpringOne The ecosystem's conference; talks from the team The recordings are free
Devoxx, Codemotion, JavaZone Java and the ecosystem in general Devoxx publishes almost everything openly
Local Java User Groups (JUGs) Talks and contacts in your city The real value is in the conversation afterwards, not in the talk

And the advice about asking, which applies in any of these places: a good question includes the Spring Boot version, a minimal example that reproduces the problem, the complete error message and what you have already tried. Preparing that question solves the problem by itself one time in three, and the phenomenon has a name — rubber duck debugging: being forced to explain the problem precisely makes you see the gap in your own reasoning.

On the issue tracker, which deserves a paragraph of its own because almost nobody uses it: when Spring does something you do not understand, there is a high probability that somebody has already reported it, and that a team member has explained why it works that way. Those answers are frequently better than the documentation, because they answer the exact question you have. Searching the literal error message in quotes is the first move, before writing on any forum.

  1. Deliberate practice

Reading about programming does not teach you to program, just as reading about swimming does not teach you to swim. Four ways of practising that do work:

Your own projects of increasing difficulty. The usual mistake is starting with "a social network": too big, abandoned in week three. A progression that works:

Level Project What it forces you to solve
1 A CRUD with authentication and tests, deployed The whole flow, end to end. It sounds like little and it is not
2 Add an external integration with a circuit breaker and a cache Partial failures, timeouts, invalidation
3 Add background work and notifications Concurrency, idempotency, delivery
4 Put it through a load test and optimise it up to an SLO Measuring, profiling, deciding
5 Extract a part into a separate service, with messaging Eventual consistency, contracts, tracing

The seven extensions in 10-04 cover exactly that progression on a project you already know.

Contributing to an open source project. Start with documentation or with an issue labelled good first issue. What you learn is not so much the code as the process: demanding reviews, mandatory tests, design discussions in the open. It is the cheapest way to work with people better than you.

Katas and short exercises. Repeating a small problem while concentrating on one thing at a time — this time with TDD, this time with no if, this time with perfect names — is the closest thing to practising scales. Half an hour a week.

Reading other people's code. The most undervalued habit. Pick a well-regarded Spring Boot project on GitHub and read it the way you read a book: the package structure, one service, its tests, its pipeline. You are going to find decisions different from this course's, and understanding why they took them is more instructive than agreeing.

And a warning about the first three: practice without feedback is not deliberate practice, it is repetition. Writing code nobody reviews consolidates the mistakes as firmly as the successes. The three available sources of feedback, from most to least accessible, are: the tests, which tell you whether it works; the tools from 10-03 — ArchUnit, SpotBugs, static analysis — which tell you whether it is well built; and a person, who is the only one who tells you whether it is well thought out. If you work alone, contributing to an open source project is the cheapest way to get the third.

  1. Natural topics for the next step

All of these start from something you already know. The third column is the one that matters: it says which lesson left you prepared.

Topic What it is What in the course prepares you
Spring Modulith Modules with verified boundaries inside the monolith, with events and per-module tests The packages-by-feature from 01-04 and the ArchUnit rules from 10-03
Messaging with Kafka or RabbitMQ Durable asynchronous communication between systems The limits of @Async in 07-03 and the events from 04-07
Spring Batch Batch processing with restart, retries and chunking The scheduled tasks from 07-03 and the TransactionTemplate importer from 04-07
WebFlux and R2DBC The non-blocking reactive stack The threading model from 09-01. With a caveat: Java 21's virtual threads now cover a good part of its use case with far less complexity
Hexagonal architecture Ports and adapters; the domain at the centre The dependency rule from 10-01 and the framework-free domain from 10-03
Tactical DDD Aggregates, value objects, domain events, repositories The anaemic model discussion from 10-03 and the events from 02-02
Kubernetes in depth Operators, service meshes, network policies, GitOps The manifests and Helm from 08-04
Spring AI Integration with language models from Spring The fault-tolerant external client pattern from 07-06
OAuth2 and OpenID Connect Delegating identity to a provider The home-made JWT from 05-04, which is the artisanal version of the same problem

Which to choose first. Not the one that sounds best, but the one that solves a problem you have. If your application loses work when it restarts, messaging. If two teams tread on each other in the same code, Spring Modulith. If the domain is dissolving into your services, tactical DDD. And if nothing hurts yet, the order that best consolidates what you have learnt is Spring Modulith → messaging → tactical DDD.

  1. How to evaluate a resource

Three questions, in this order, before investing time in an article, a video or a course:

1. When is it from? If there is no visible date, be suspicious. An undated article about a framework that ships two versions a year is not a resource, it is a risk.

2. Which Spring Boot version does it use? This is the decisive question, and it is almost always answered by glancing at the code for ten seconds:

Signal What it indicates
javax.persistence, javax.servlet, javax.validation Spring Boot 2: the move to Jakarta EE 9+ renamed all those packages in Boot 3
WebSecurityConfigurerAdapter Spring Security 5: retired, replaced by SecurityFilterChain
@EnableGlobalMethodSecurity Likewise: today it is @EnableMethodSecurity
spring-cloud-starter-sleuth Discontinued: today it is Micrometer Tracing
WebMvcConfigurerAdapter, @MockBean A retired adapter; @MockBean replaced by @MockitoBean in Boot 3.4+
RestTemplate as the recommendation It is not retired, but since Boot 3.2 the default choice is RestClient
application.properties with spring.datasource.initialize Boot 1.x properties

Why a Spring Boot 2 tutorial confuses more than it helps. It is not that it is "a bit dated": it is that the code does not compile in a Boot 3 project — the packages of every persistence, validation and servlet annotation change — and, worse, the conceptual explanation still sounds plausible. A novice reader cannot tell "this no longer exists" from "I typed this wrong", and loses hours. With the table above, those ten seconds of checking save you the afternoon.

3. Who signed it and what is at stake for them? An article from the Spring team, from an author with a track record or from a peer-reviewed project has an incentive to be right. Content optimised for search rankings does not.

And a fourth criterion that applies above all to automatically generated content, which is increasingly abundant: if the code cannot be run as it stands, be suspicious. Examples that mix versions, invent methods that do not exist or call APIs from two different eras are the characteristic signature.

  1. A six-month roadmap

A concrete, reasoned proposal for whoever finishes this course and wants to consolidate rather than scatter. The principle that orders it: each month has one deliverable, and each deliverable builds on the previous one.

Month Focus Concrete deliverable
1 Consolidate what you learnt. Nothing new Implement two extensions from 10-04: the operator panel and the reports with export. With tests and deployed
2 Java, not Spring. Effective Java Refactor the project applying ten concrete items from the book; write down what improved and what did not
3 Persistence for real. High-Performance Java Persistence A load test with realistic data, EXPLAIN ANALYZE on the five most expensive queries, indexes and a measured p95 improvement
4 Messaging. Kafka or RabbitMQ with Spring Extract the notifications into a message consumer, with the outbox pattern, idempotency and traces that cross the boundary
5 Design. Spring Modulith and tactical DDD Reorganise the project into modules with verified boundaries and events between them; move into the domain the rules that today live in services
6 Real production. SRE and observability Define SLOs with an error budget, alerts on symptoms, a dashboard and a timed incident drill

Why this order and not another. Month 1 deliberately learns nothing new: what you have just seen consolidates by being used, not by piling more topics on top. Month 2 is Java and not Spring because it is what transfers most and expires least. Month 3 attacks where the time really is. Months 4 and 5 are the two conceptual leaps — asynchronous communication and domain design — and they come after the base is solid. And month 6 closes the cycle, because operating what you build is what turns a programmer into an engineer.

How to make it realistic. Four or five hours a week, with a visible deliverable each month. A twenty-hours-a-week plan does not get followed and produces guilt; a five-hour one sustained for six months produces real change. And if some month does not work out, you do not skip it: you delay it. The sequence matters more than the calendar.

And if your situation is different, adapt it with this criterion instead of copying it. If you are job-hunting, move month 6 to the start: a deployed, observable project is what you show in an interview. If your team is going to split the monolith next quarter, bring month 4 forward and add Designing Data-Intensive Applications. If you have just joined a legacy project, months 1 and 2 are replaced by writing characterisation tests and upgrading the version, which is what unblocks everything else. The right roadmap is the one that attacks the problem you have today, not the one that covers the most topics.

Common Mistakes and Tips

Collecting resources instead of using them. Fifty open tabs and three started courses produce the feeling of learning and no learning. One resource at a time, with a problem in front of you.

Following a tutorial without checking the version. It is the number one cause of hours lost with Spring. Ten seconds looking at whether it says javax or jakarta save them for you.

Learning the new before mastering the current. WebFlux, GraalVM or Spring AI are interesting; if you are not yet clear on how the @Transactional proxy works, they are not your next step.

Copying configuration without understanding it. An application.yml copied from a blog brings properties you do not need, some of them dangerous — ddl-auto: update, an open Actuator, show-sql on — and no explanation at all.

Confusing "I have read about this" with "I know how to do this". The test is simple and merciless: open the IDE and do it without looking.

Accepting an assistant's suggested code without verifying it. Language models are trained on everything that has been published, and what has been published about Spring Boot is mostly from the 2.x era: you will see WebSecurityConfigurerAdapter, javax.persistence and @MockBean delivered with absolute confidence. They are excellent tools for exploring and for writing the repetitive parts, and exactly the same criteria from section 12 apply: check the version, run it and do not paste it if you do not understand it.

Only studying what you already enjoy. It is comfortable to go deeper into what you are good at and avoid what feels foreign — for many programmers, operations and the database. And that is precisely where the biggest gap between what you know and what the project needs usually sits.

Tip: write down what you learn. An article, an internal note or a docs/decisions/ file in your project. Explaining something forces you to genuinely understand it, and it uncovers the gaps that passive reading hides.

Tip: keep a living project. A repository of your own that you come back to every few weeks is worth more than ten courses. It is where you try each new thing and where you check whether it works in your hands and not only in the author's.

Tip: learn to read code before writing it. You will spend most of your career reading: your team's code, a framework's, that of somebody who left three years ago. It is a skill that can be trained, and almost nobody trains it on purpose.

Tip: when something surprises you, stop and go in. That instant of "oh, I didn't know it did that" is the best learning signal available, and it is wasted almost every time because you are in a hurry. Ten minutes reading the class that caused it are worth more than two hours of a course on something that has never surprised you.

Tip: the best way to study a new topic is to write the smallest possible example. Not a project: a Maven module with three classes that does one thing. A Kafka consumer that prints messages. An @Observed that produces a span. It is quick to write, quick to throw away, and it answers questions no article answers.

Exercises

Exercise 1: evaluate three resources

Search for three articles or tutorials about "Spring Boot JWT authentication" in any search engine. For each one, apply the criteria from section 12 and write a card with: the date, the Spring Boot version you deduced and from which concrete signal you deduced it, whether the code would compile today, three things you would do differently based on module 5, and your final verdict. It is very likely at least one is out of date; the exercise is to spot it in under a minute.

Exercise 2: read an autoconfiguration class

Download the sources with ./mvnw dependency:sources and open DataSourceAutoConfiguration (or JacksonAutoConfiguration, if you prefer something shorter). Answer: which conditions must be met for it to activate? which beans does it declare? which annotation makes your own bean win over theirs? which *Properties class does it read its configuration from and what defaults does it have? And finally: what would you have to do to replace its DataSource entirely with one of your own?

Exercise 3: your own roadmap

Adapt the roadmap from section 13 to your real situation. Start from three questions: what problem do you have today at work or in your project that Spring Boot has not solved for you yet? how many hours a week can you genuinely sustain for six months? and what visible deliverable would mark each month? Write the result with one deliverable per month and an objective criterion for knowing whether you have met it.

Solutions

Solution 1

An example of a well-made card, on a very common case:

Article A — No visible date (first alarm signal; the blog footer says 2021). Deduced version: Spring Boot 2.5. The signals, in order of conclusiveness: it extends WebSecurityConfigurerAdapter and overrides configure(HttpSecurity), retired in Spring Security 5.7; it imports javax.servlet.FilterChain; it uses antMatchers(...), replaced by requestMatchers(...); and io.jsonwebtoken 0.9.1, whose Jwts.parser().setSigningKey(String) API no longer exists in 0.12. Would it compile today? No. It would fail on the javax.* imports and on the retired base class, and would not even reach the JJWT API errors. Three things I would do differently based on module 5: (1) a SecurityFilterChain bean instead of the adapter, with authorizeHttpRequests ending in anyRequest().denyAll(); (2) the secret from an environment variable and 256 bits long, not a "secret" constant in the code; (3) a fifteen-minute access token with rotating refresh, instead of the article's ten hours. Verdict: discard. Not because it is old, but because the mistake it teaches is a security one, which is the worst category to copy without understanding.

The three signals that settle 90% of cases in ten seconds: javax versus jakarta, WebSecurityConfigurerAdapter, and spring-cloud-starter-sleuth. If any of the three appears, the resource is from the Spring Boot 2 era.

And the nuance that keeps you from being unfair: an old resource can still be conceptually correct. The explanation of what a JWT is, why it is signed and why its payload is readable has not changed. What you cannot copy is the code.

Solution 2

On DataSourceAutoConfiguration, the answers and — more importantly — what each one teaches:

Which conditions activate it? @ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}), that is, only if those classes are on the classpath. Hence the rule that explains all of autoconfiguration: adding a data starter does not magically "switch" anything on; it simply puts classes on the classpath and the conditions are met.

Which beans does it declare? A DataSource, resolved in nested configurations: if it detects HikariCP it uses it (@ConditionalOnClass(HikariDataSource.class)), and if not it tries Tomcat JDBC or DBCP2, in that order. It also declares DataSourceInitializer and the properties beans.

What makes your bean win? @ConditionalOnMissingBean. It is the key annotation of the whole of Spring Boot: autoconfiguration only acts if you have not decided anything. Declaring your own @Bean DataSource disables it without needing to exclude anything.

Where does it read from? From DataSourceProperties (prefix spring.datasource), which holds url, username, password, driverClassName, generate-unique-name and the rest, with their default values written on the fields — which is faster to consult than the documentation.

How would you replace it entirely? Three ways, from best to worst: declare your own @Bean DataSource, which wins thanks to @ConditionalOnMissingBean; exclude it with @SpringBootApplication(exclude = DataSourceAutoConfiguration.class); or remove the dependency, so the class condition stops being met.

What the exercise really teaches is not this class but the pattern: @ConditionalOnClass + @ConditionalOnMissingBean + a *Properties class. With that you understand the remaining two hundred autoconfigurations, including the one for the custom starter we wrote in 02-06. And it confirms the claim in section 3: when you read the code, the magic disappears.

Solution 3

There is no single solution, but there is a recognisable way of having done the exercise well. An example:

Situation: I work in a team of four with a Spring Boot 2.7 monolith nobody dares upgrade. I can sustain four hours a week. The real problem is not technical: it is that there are no tests, and that is why nobody touches anything.

Month Focus Deliverable Objective criterion
1 Characterisation tests for the three critical flows A suite that runs in CI ./mvnw verify green in the pipeline, not on my laptop
2 Upgrade to Spring Boot 3, rung by rung A branch with 2.7 → 3.0 → 3.3 The month 1 suite green at every rung
3 Effective Java + refactoring one module A clean billing module Ten items applied, documented in docs/decisions/
4 Performance: k6, EXPLAIN ANALYZE, indexes A baseline and a measured improvement The worst endpoint's p95 below 300 ms
5 Observability: metrics, logs and traces A dashboard and two alerts Provoke an incident and diagnose it in under ten minutes
6 Spring Modulith Boundaries between billing and orders ArchUnit rules that fail if somebody crosses them

What makes this roadmap a good one: month 1 is not "learn something", it is removing the real blocker — without tests nothing else can be done; every month has an objective, verifiable criterion, not "understand X"; the order respects the dependencies between topics; and the hours are the ones the person can genuinely sustain, not the ones they would like.

The typical mistake in this exercise is writing a list of technologies that sound good — Kafka, Kubernetes, WebFlux, GraalVM — with no problem behind them. A roadmap with no problem to solve gets abandoned in week five.

And a final check worth doing: if in six months you completed the whole plan, what would you know how to do that you do not today? If the answer can be phrased with verbs — "upgrade a legacy project without fear", "diagnose a high p99 in ten minutes" — the plan is good. If it can only be phrased with nouns — "Kafka", "Kubernetes" — it is still a list of topics and not a roadmap.

Conclusion

The course ends here, and it is worth looking at the whole route before closing it.

We started in 01-03 with a nine-line @RestController that returned four hand-written stations and a curl that answered on localhost:8080. We finish with CicloUrbana: an application with a versioned, documented REST contract, with its DTOs, its validation and its errors in RFC 7807; with persistence on PostgreSQL governed by nine Flyway migrations and transactions that guarantee no Ribalta bike is ever left half locked; with JWT authentication, a role hierarchy and security rules that depend on the data and not only on the route; with a test suite that runs from the one-millisecond unit test to the complete flow against a real, ephemeral PostgreSQL; with scheduled tasks coordinated across replicas and asynchronous work that does not block the citizen; packaged in a multi-stage image, deployed to Kubernetes by a pipeline that builds it, scans it and promotes it on its own; and observed end to end, where the metric detects, the trace locates and the log explains, joined by a single traceId. And with the judgement, at the end, to know why it is built that way and where each rule would have to be broken.

What matters is that almost none of that is specific to Spring Boot. Inversion of control, the separation between domain and contract, the atomicity of a use case, deny by default, the testing pyramid, measuring before optimising, percentiles instead of the mean, backward-compatible migrations, one artefact for every environment, secrets out of the repository, structured and correlated logs, technical debt recorded with its cost: all of that travels with you to any framework, any language and any team. Spring Boot has been the vehicle; what you have learnt to drive is bigger than that.

There are things left to know, and there always will be. It is the uncomfortable part of this craft and also the best: nobody ever finishes learning it, and the difference between somebody with two years' experience and somebody with fifteen is not the number of frameworks they know, but the quality of the questions they ask before deciding. This course has tried, above all, to teach you those questions: what problem does this solve? what does it cost me? how will I know it works? what happens when it fails? will the next person who reads it understand it?

Now it is your turn. Take CicloUrbana somewhere: add the dynamic fares, extract the billing, connect it to a map. Or start something of your own, smaller and more real, and do it properly from beginning to end. What does not work is waiting until you know everything before you build: you learn by building, measuring what you build and fixing what breaks.

The Ribalta network is up and running. Thank you for making it this far, and safe travels.

Spring Boot Course

Module 1: Introduction to Spring Boot

Module 2: Spring Boot Core Concepts

Module 3: Building RESTful Web Services

Module 4: Data Access with Spring Boot

Module 5: Security in Spring Boot

Module 6: Testing in Spring Boot

Module 7: Advanced Spring Boot Features

Module 8: Deploying Spring Boot Applications

Module 9: Performance and Monitoring

Module 10: Best Practices and Tips

© Copyright 2026. All rights reserved