Chapter 01
Java and Spring Boot essentials
Modern Java features and how Spring Boot wires an application together, from beans to builds.
Spring beans and dependency injection
Also called DI, IoC, Spring Boot
- What
- Spring creates objects (beans) for classes annotated
@Service,@Repositoryor@RestControllerand passes their dependencies through the constructor. Spring Boot adds auto-configuration and starters. - Why
- Classes ask for what they need instead of building it, so you can swap real implementations for fakes in tests and configure everything in one place.
@Service
class OrderService {
private final OrderRepository orders;
private final PaymentClient payments;
OrderService(OrderRepository orders, PaymentClient payments) {
this.orders = orders;
this.payments = payments;
}
}Watch out
Field injection with @Autowired on private fields: it hides dependencies and makes plain unit tests awkward.
Records
Also called record, DTO
- What
- A
recordis a compact, immutable data class: the compiler writes the constructor, accessors,equals,hashCodeandtoString. A compact constructor can validate fields. - Why
- Ideal for request and response DTOs, events and value objects, with far less boilerplate than a classic class.
public record UserDto(long id, String email, String name) {
public UserDto {
Objects.requireNonNull(email, "email");
}
}Watch out
Using records as JPA entities: entities need a no-args constructor and mutable state, which records do not have.
Virtual threads
Also called Project Loom
- What
- Lightweight threads managed by the JVM (Java 21+). Millions can exist, and a blocked virtual thread frees its carrier OS thread while it waits on I/O.
- Why
- Blocking, easy-to-read code scales like async code for I/O-heavy services. Spring Boot switches its request handling to virtual threads with one property.
spring:
threads:
virtual:
enabled: trueWatch out
Expecting more throughput when the real limit is a pool of 10 database connections or CPU-bound work.
Exceptions and @RestControllerAdvice
Also called ProblemDetail, @ExceptionHandler
- What
- A
@RestControllerAdviceclass maps exceptions thrown anywhere in controllers to HTTP responses.ProblemDetailbuilds the standard problem JSON body. - Why
- One place turns domain errors into consistent status codes and bodies, so controllers stay short and clients see one error shape.
@RestControllerAdvice
class ApiErrors {
@ExceptionHandler(NotFoundException.class)
ProblemDetail notFound(NotFoundException e) {
return ProblemDetail.forStatusAndDetail(
HttpStatus.NOT_FOUND, e.getMessage());
}
}Watch out
Catching Exception and returning its message, which leaks stack details to the client.
Maven and Gradle builds
Also called Maven, Gradle, pom.xml
- What
- Build tools that download dependencies, compile, run tests and package the app as a runnable JAR. The wrapper scripts (
mvnw,gradlew) pin the tool version. - Why
- Everyone and every CI run builds the same way. Spring Boot plugins add
bootRunand a fat JAR that contains all dependencies.
./mvnw spring-boot:run
./mvnw test
./mvnw package # target/app.jar
./gradlew bootRun
./gradlew buildWatch out
Declaring versions for libraries Spring Boot already manages, which breaks its tested version set.
Java basics: types, classes and objects
Also called class, object, equals
- What
- Java is statically typed. Primitives such as
intandbooleanhold values, while everything else is an object reached through a reference. Classes define fields and methods, andvarinfers a local variable's type. - Why
- Spring code is classes all the way down, and knowing references,
equalsversus==and access modifiers prevents the most common beginner bugs.
public class Order {
private final long id;
private final int totalPence;
public Order(long id, int totalPence) {
this.id = id;
this.totalPence = totalPence;
}
public long id() { return id; }
}
var a = "hi"; var b = new String("hi");
a.equals(b); // true, but a == b is falseWatch out
Comparing strings or boxed numbers with ==, which compares references, not values.
Java collections
Also called List, Map, Set, ArrayList, HashMap
- What
- The Collections Framework gives the
List,MapandSetinterfaces with implementations such as ArrayList, HashMap and HashSet, plus streams for filtering and mapping. - Why
- Almost every service method moves data through these, and choosing the right one decides both correctness and speed.
List<Order> orders = new ArrayList<>();
Map<Long, Order> byId = new HashMap<>();
for (Order o : orders) byId.put(o.id(), o);
List<Long> ids = orders.stream()
.filter(o -> o.totalPence() > 5000)
.map(Order::id)
.toList();
List<String> fixed = List.of("a", "b"); // immutableWatch out
Removing items from a list inside a for-each loop, which throws ConcurrentModificationException.