<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Spring-Boot on Devops Monk</title><link>https://devops-monk.com/tags/spring-boot/</link><description>Recent content in Spring-Boot on Devops Monk</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 03 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://devops-monk.com/tags/spring-boot/index.xml" rel="self" type="application/rss+xml"/><item><title>API Documentation with OpenAPI and Springdoc</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-openapi-springdoc/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-openapi-springdoc/</guid><description>Good API documentation is non-negotiable. Springdoc reads your Spring MVC code and auto-generates interactive OpenAPI 3.1 documentation — no separate doc files to maintain.
Setup &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springdoc&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;springdoc-openapi-starter-webmvc-ui&amp;lt;/artifactId&amp;gt; &amp;lt;version&amp;gt;2.5.0&amp;lt;/version&amp;gt; &amp;lt;/dependency&amp;gt; Start the app and visit:
Swagger UI: http://localhost:8080/swagger-ui.html OpenAPI JSON: http://localhost:8080/v3/api-docs OpenAPI YAML: http://localhost:8080/v3/api-docs.yaml Springdoc scans your @RestController classes and generates the spec automatically. Zero configuration needed for basic docs.
Configuring the API Info @Configuration public class OpenApiConfig { @Bean public OpenAPI openAPI() { return new OpenAPI() .</description></item><item><title>API Gateway with Spring Cloud Gateway</title><link>https://devops-monk.com/tutorials/spring-boot/spring-cloud-gateway/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-cloud-gateway/</guid><description>The API gateway is the single entry point for all client traffic. It handles routing to downstream services, authentication, rate limiting, and request/response transformation — so individual services don&amp;rsquo;t have to.
Setup &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-cloud-starter-gateway&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-cloud-starter-netflix-eureka-client&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; Spring Cloud Gateway is reactive (WebFlux-based) — don&amp;rsquo;t include spring-boot-starter-web.
Route Configuration YAML Configuration spring: application: name: api-gateway cloud: gateway: routes: - id: order-service uri: lb://order-service # lb:// = load-balanced via Eureka predicates: - Path=/api/orders/** filters: - StripPrefix=0 # don&amp;#39;t strip path prefix - AddRequestHeader=X-Gateway-Source, api-gateway - id: customer-service uri: lb://customer-service predicates: - Path=/api/customers/** filters: - StripPrefix=0 - id: payment-service uri: lb://payment-service predicates: - Path=/api/payments/** filters: - StripPrefix=0 # Versioned routing - id: order-service-v2 uri: lb://order-service-v2 predicates: - Path=/api/v2/orders/** - Header=X-API-Version, 2 default-filters: - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin Programmatic Route Configuration @Configuration public class GatewayRouteConfig { @Bean public RouteLocator routeLocator(RouteLocatorBuilder builder) { return builder.</description></item><item><title>API Versioning in Spring Boot 4</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-api-versioning/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-api-versioning/</guid><description>APIs evolve. Adding fields is safe — removing or changing fields breaks clients. Versioning gives you a path to evolve the API without breaking existing integrations.
When You Need Versioning You need a new API version when:
Removing a field from a response Changing a field&amp;rsquo;s type or semantics Changing URL structure significantly Breaking backward-incompatible business logic changes You don&amp;rsquo;t need a new version for:
Adding new optional fields (non-breaking) Adding new endpoints Bug fixes that don&amp;rsquo;t change the contract Strategy 1: URL Path Versioning The most common and explicit approach:</description></item><item><title>Application Configuration: Properties, YAML, and Profiles</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-configuration-profiles/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-configuration-profiles/</guid><description>Every real application needs different configuration for different environments — a local database for dev, a connection pool for staging, a secret manager for prod. This article covers everything Spring Boot gives you to handle this cleanly.
application.properties vs application.yml Spring Boot reads configuration from src/main/resources/application.properties (or .yml) by default. Both formats express the same thing:
application.properties:
server.port=8080 spring.datasource.url=jdbc:postgresql://localhost:5432/orders spring.datasource.username=app spring.datasource.password=secret spring.jpa.show-sql=false application.yml:
server: port: 8080 spring: datasource: url: jdbc:postgresql://localhost:5432/orders username: app password: secret jpa: show-sql: false YAML is generally preferred for nested properties — it&amp;rsquo;s less repetitive.</description></item><item><title>Async Processing with @Async and Virtual Threads</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-async-virtual-threads/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-async-virtual-threads/</guid><description>Not every operation needs to complete before the response returns. Sending an email, generating a report, publishing an event — these can run in the background. Async processing keeps request latency low while the work continues.
@Async — Fire and Forget @SpringBootApplication @EnableAsync public class OrderServiceApplication { } @Service @Slf4j public class NotificationService { @Async // runs in a separate thread public void sendOrderConfirmation(Order order) { log.info(&amp;#34;Sending confirmation for order {}&amp;#34;, order.</description></item><item><title>Bean Validation: @Valid, Custom Validators, and Error Messages</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-bean-validation/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-bean-validation/</guid><description>Every request that enters your API needs validation. Without it, invalid data propagates through your application and produces confusing errors deep in the stack. This article covers how to validate data at the API boundary using Jakarta Bean Validation.
Setup &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-boot-starter-validation&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; This includes Hibernate Validator — the reference implementation of Jakarta Bean Validation 3.0.
Built-in Constraints Annotate fields in your DTO with constraint annotations:
public record CreateOrderRequest( @NotNull(message = &amp;#34;Customer ID is required&amp;#34;) UUID customerId, @NotEmpty(message = &amp;#34;Order must contain at least one item&amp;#34;) @Size(max = 50, message = &amp;#34;Order cannot have more than {max} items&amp;#34;) List&amp;lt;@Valid OrderItemRequest&amp;gt; items, @Valid ShippingAddressRequest shippingAddress, @Size(max = 20, message = &amp;#34;Promo code cannot exceed {max} characters&amp;#34;) String promoCode ) {} public record OrderItemRequest( @NotNull UUID productId, @Positive(message = &amp;#34;Quantity must be positive&amp;#34;) @Max(value = 999, message = &amp;#34;Cannot order more than {value} units of a product&amp;#34;) int quantity, @NotNull @Positive BigDecimal unitPrice ) {} public record ShippingAddressRequest( @NotBlank(message = &amp;#34;Address line 1 is required&amp;#34;) @Size(max = 100) String line1, @Size(max = 100) String line2, @NotBlank @Size(max = 50) String city, @NotBlank @Pattern(regexp = &amp;#34;[A-Z]{2}&amp;#34;, message = &amp;#34;Country must be a 2-letter ISO code&amp;#34;) String country, @NotBlank @Pattern(regexp = &amp;#34;\\w{3,10}&amp;#34;, message = &amp;#34;Invalid postal code format&amp;#34;) String postalCode ) {} Common Constraint Annotations Annotation Validates @NotNull Value is not null @NotEmpty String/collection not null and not empty @NotBlank String not null, not empty, not just whitespace @Size(min, max) String length or collection size @Min(value) Number ≥ value @Max(value) Number ≤ value @Positive Number &amp;gt; 0 @PositiveOrZero Number ≥ 0 @Negative Number &amp;lt; 0 @Pattern(regexp) String matches regex @Email Valid email format @Past Date is in the past @Future Date is in the future @DecimalMin(value) Decimal ≥ value (as string) @AssertTrue Boolean is true @AssertFalse Boolean is false Triggering Validation with @Valid Add @Valid to the controller parameter to trigger validation:</description></item><item><title>Building a Modular Monolith with Spring Modulith</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-spring-modulith/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-spring-modulith/</guid><description>Microservices solve organizational and scalability problems — but they add operational complexity. Most applications don&amp;rsquo;t need that complexity. A modular monolith gives you clean boundaries and loose coupling without the distributed systems overhead. Spring Modulith enforces those boundaries.
The Problem with Unstructured Monoliths Without explicit boundaries, every part of the codebase can talk to every other part:
// OrderService calling PaymentRepository directly — skipping the Payment module @Service public class OrderService { @Autowired PaymentRepository paymentRepository; // ← wrong @Autowired NotificationService notificationService; // ← wrong @Autowired AnalyticsService analyticsService; // ← wrong } This creates hidden coupling.</description></item><item><title>Building Your First REST API with Spring Boot</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-rest-api/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-rest-api/</guid><description>Time to build something real. In this article you&amp;rsquo;ll create a fully functional REST API for the order-service — create, read, update, and delete orders over HTTP.
Project Setup Start with these dependencies at start.spring.io:
&amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-boot-starter-web&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-boot-starter-validation&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; spring-boot-starter-web includes:
Embedded Tomcat (no WAR deployment needed) Spring MVC (the web framework) Jackson (JSON serialization) The Request Processing Pipeline Before writing code, understand how Spring MVC handles a request:</description></item><item><title>Caching with Caffeine and Redis</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-caching/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-caching/</guid><description>Caching sits between your application and the database. A cache hit returns data in microseconds; a database query takes milliseconds. For frequently-read, infrequently-changed data, caching is the highest-leverage performance improvement.
Spring Cache Abstraction Spring&amp;rsquo;s cache abstraction lets you add caching with annotations — the backing store (Caffeine, Redis, Hazelcast) is swappable:
@Service @RequiredArgsConstructor public class ProductService { private final ProductRepository repository; @Cacheable(&amp;#34;products&amp;#34;) // cache the result public Product findById(UUID id) { return repository.</description></item><item><title>Centralized Configuration with Spring Cloud Config Server</title><link>https://devops-monk.com/tutorials/spring-boot/spring-cloud-config-server/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-cloud-config-server/</guid><description>Managing configuration for 10 services across 3 environments means 30 separate config files. Spring Cloud Config Server centralizes all of them — one place to change a database URL, one place to rotate secrets, and services pick up changes without redeployment.
Config Server Setup &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-cloud-config-server&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; @SpringBootApplication @EnableConfigServer public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } } # application.yml — config-server server: port: 8888 spring: application: name: config-server cloud: config: server: git: uri: https://github.</description></item><item><title>CRUD Operations with JpaRepository</title><link>https://devops-monk.com/tutorials/spring-boot/spring-data-jpa-crud/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-data-jpa-crud/</guid><description>You have entities and repositories set up. Now let&amp;rsquo;s work through every data operation in depth — create, read, update, delete — and the JPA mechanics behind each.
Create: save() @Service @RequiredArgsConstructor @Transactional public class OrderService { private final OrderRepository orderRepository; public Order createOrder(CreateOrderRequest request) { Order order = new Order(); order.setCustomerId(request.customerId()); order.setOrderNumber(generateOrderNumber()); order.setStatus(OrderStatus.PENDING); request.items().forEach(itemReq -&amp;gt; { OrderItem item = new OrderItem(); item.setProductId(itemReq.productId()); item.setQuantity(itemReq.quantity()); item.setUnitPrice(itemReq.unitPrice()); order.addItem(item); // manages bidirectional relationship }); return orderRepository.</description></item><item><title>Database Migrations with Flyway</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-flyway-migrations/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-flyway-migrations/</guid><description>Never use spring.jpa.hibernate.ddl-auto=update in production. It&amp;rsquo;s unpredictable, irreversible, and can corrupt data. Flyway gives you version-controlled, audited, reproducible schema changes.
Why Flyway? Every database change runs as a versioned SQL script. Flyway tracks which scripts have run in a flyway_schema_history table. When the app starts:
Flyway reads all migration files Checks which have already run (by checking the history table) Runs any new ones, in order If the current state doesn&amp;rsquo;t match the expected state → fails fast Benefits:</description></item><item><title>Dockerizing Spring Boot Applications</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-docker/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-docker/</guid><description>Packaging your Spring Boot application as a Docker container is the standard way to deploy it — to Kubernetes, cloud platforms, or any container runtime. This article covers building production-quality images.
The Naive Dockerfile (Don&amp;rsquo;t Use This) FROM eclipse-temurin:21-jdk COPY target/order-service.jar app.jar ENTRYPOINT [&amp;#34;java&amp;#34;, &amp;#34;-jar&amp;#34;, &amp;#34;app.jar&amp;#34;] Problems:
600MB+ image (JDK, not JRE) No layer caching — every code change rebuilds the whole JAR layer Runs as root (security risk) No health check Layered JARs (Better Cache Utilization) Spring Boot 3 creates layered JARs by default.</description></item><item><title>DTOs and Response Shaping</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-dto-response/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-dto-response/</guid><description>Every beginner makes the same mistake: returning JPA entities directly from REST controllers. This article explains why that&amp;rsquo;s dangerous, and how to design clean DTOs that make your API stable, secure, and maintainable.
Why Not Return Entities Directly? Consider this:
@GetMapping(&amp;#34;/{id}&amp;#34;) public Order getOrder(@PathVariable UUID id) { return orderRepository.findById(id).orElseThrow(); // Entity returned directly } Problems with this:
1. Serialization of lazy-loaded relationships crashes
@Entity public class Order { @OneToMany(fetch = FetchType.</description></item><item><title>Entity Relationships: @OneToMany, @ManyToOne, @ManyToMany</title><link>https://devops-monk.com/tutorials/spring-boot/spring-data-jpa-relationships/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-data-jpa-relationships/</guid><description>Relationships are the trickiest part of JPA. A wrong cascade type or a missing mappedBy causes subtle bugs that appear in production. This article covers every relationship type with real examples and the pitfalls to avoid.
Relationship Fundamentals JPA relationships can be:
Direction: Unidirectional (one side knows about the other) or Bidirectional (both sides know each other) Cardinality: @OneToOne, @OneToMany, @ManyToOne, @ManyToMany Fetch: LAZY (load on access) or EAGER (load immediately) Ownership: The side with the foreign key column is the owner Default fetch types:</description></item><item><title>Event-Driven Spring Boot: Transactional Outbox Pattern with Kafka</title><link>https://devops-monk.com/2026/05/spring-boot-kafka-transactional-outbox/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-kafka-transactional-outbox/</guid><description>Publishing an event to Kafka after saving to the database looks simple. It has a subtle, dangerous flaw: if the Kafka publish fails after the DB commit, or the app crashes between the two, your event is lost and your data is inconsistent.
The Transactional Outbox Pattern solves this by writing the event to the database in the same transaction as the business data, then publishing to Kafka separately. This guide covers the pattern, the implementation, and idempotent consumers.</description></item><item><title>Externalized Configuration with @ConfigurationProperties</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-configuration-properties/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-configuration-properties/</guid><description>@ConfigurationProperties binds external configuration to a typed Java class — replacing scattered @Value annotations with a single, validated, testable object.
Why @ConfigurationProperties Over @Value // @Value — scattered, no type safety, no validation @Service public class PaymentService { @Value(&amp;#34;${payment.gateway.url}&amp;#34;) private String gatewayUrl; @Value(&amp;#34;${payment.gateway.timeout:5000}&amp;#34;) private int timeoutMs; @Value(&amp;#34;${payment.gateway.api-key}&amp;#34;) private String apiKey; @Value(&amp;#34;${payment.gateway.max-retries:3}&amp;#34;) private int maxRetries; } // @ConfigurationProperties — one place, typed, validated @Service public class PaymentService { private final PaymentProperties properties; // all config in one place, injected as a single object } @ConfigurationProperties gives you:</description></item><item><title>Full Observability: Prometheus + Grafana + Tempo + Loki</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-observability/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-observability/</guid><description>Observability means being able to answer &amp;ldquo;what&amp;rsquo;s wrong and why&amp;rdquo; from the outside — without modifying the code. The three pillars: metrics (what happened), logs (what the code did), and traces (how a request flowed). This article wires them all together.
The Stack Spring Boot App ├── Metrics → Micrometer → Prometheus scrape → Grafana dashboards ├── Traces → Micrometer Tracing → OTLP → Tempo → Grafana trace view └── Logs → Logback → Loki4j → Loki → Grafana log explorer All three converge in Grafana — click a metric spike to see the correlated logs and traces for that exact time window.</description></item><item><title>Global Exception Handling with @ControllerAdvice and ProblemDetail</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-exception-handling/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-exception-handling/</guid><description>Without global exception handling, Spring returns raw stack traces or inconsistent error shapes. This article shows how to centralize all error handling in one place and return structured, RFC 7807-compliant responses.
The Problem Without Global Handling Default Spring Boot error responses are inconsistent:
// Validation failure (MethodArgumentNotValidException) { &amp;#34;timestamp&amp;#34;: &amp;#34;2026-05-03T10:00:00.000+00:00&amp;#34;, &amp;#34;status&amp;#34;: 400, &amp;#34;error&amp;#34;: &amp;#34;Bad Request&amp;#34;, &amp;#34;path&amp;#34;: &amp;#34;/api/orders&amp;#34; } // Details of which fields failed? Not included. // Custom exception not handled // → 500 Internal Server Error with a stack trace in the body (in dev mode) What clients actually need:</description></item><item><title>GraalVM Native Images with Spring Boot 4: From 8 Seconds to 37ms Startup</title><link>https://devops-monk.com/2026/05/spring-boot-graalvm-native-images/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-graalvm-native-images/</guid><description>Spring Boot applications running as GraalVM native images start in milliseconds, use a fraction of the memory, and fit in tiny containers. The tradeoff is a longer build time. In 2026, with Spring Boot 4 and GraalVM 24, native images are production-ready for most Spring applications.
This guide covers everything: what Spring AOT does, how to build your first native image, how to fix the common issues, and how to add native builds to CI.</description></item><item><title>GraalVM Native Images: Millisecond Startup</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-graalvm-native/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-graalvm-native/</guid><description>A regular Spring Boot application takes 2–10 seconds to start. A GraalVM native image of the same application starts in under 100 milliseconds. For serverless functions, batch jobs, and CLI tools, this is the difference between viable and unusable.
What Is a Native Image? GraalVM&amp;rsquo;s native image compiler performs ahead-of-time (AOT) compilation. Instead of shipping a JAR that the JVM interprets at runtime, you ship a standalone executable that:
Contains only the code your application actually uses Has no JVM startup overhead Uses much less memory (no JIT compiler, no class metadata) Starts in milliseconds The tradeoff: compile time increases from seconds to minutes.</description></item><item><title>Graceful Shutdown and Production Readiness</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-production-readiness/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-production-readiness/</guid><description>An application that starts and serves traffic is not production-ready. Production readiness means it shuts down cleanly, handles spikes, recovers from transient failures, and gives you visibility into what it&amp;rsquo;s doing. This article covers the operational layer.
Graceful Shutdown When Kubernetes terminates a pod, it sends SIGTERM. Without graceful shutdown, in-flight requests are killed mid-execution — users see 500 errors or dropped writes.
Enable graceful shutdown:
server: shutdown: graceful # wait for in-flight requests to complete spring: lifecycle: timeout-per-shutdown-phase: 30s # max wait before forcing shutdown With this configured, Spring Boot:</description></item><item><title>Handling Requests: Path Variables, Query Params, and Request Bodies</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-request-handling/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-request-handling/</guid><description>A REST API receives data in many places: URL path, query string, body, headers, cookies. This article covers every way to extract that data in Spring MVC.
@PathVariable — Extract from URL Use @PathVariable when the data is part of the URL path:
// URL: GET /api/orders/550e8400-e29b-41d4-a716-446655440000 @GetMapping(&amp;#34;/{id}&amp;#34;) public OrderResponse getOrder(@PathVariable UUID id) { return orderService.findById(id) .map(OrderResponse::from) .orElseThrow(() -&amp;gt; new OrderNotFoundException(id)); } Spring automatically converts the string segment to the parameter type (UUID, Long, int, etc.</description></item><item><title>How Spring Boot Auto-Configuration Actually Works (Behind the Magic)</title><link>https://devops-monk.com/2026/05/spring-boot-auto-configuration-deep-dive/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-auto-configuration-deep-dive/</guid><description>&amp;ldquo;Spring Boot is magic&amp;rdquo; is something you hear a lot. Add spring-boot-starter-data-jpa and suddenly you have a working DataSource, a JpaTransactionManager, and a LocalContainerEntityManagerFactoryBean — without writing a single @Bean method. Understanding how this actually works turns the magic into a tool you can control, debug, and extend.
The Entry Point: @EnableAutoConfiguration @SpringBootApplication is a shorthand for three annotations:
@Configuration @EnableAutoConfiguration // this is the one that matters here @ComponentScan public class MyApplication { public static void main(String[] args) { SpringApplication.</description></item><item><title>How Spring Boot Auto-Configuration Works — The Magic Explained</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-auto-configuration/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-auto-configuration/</guid><description>Spring Boot &amp;ldquo;just works&amp;rdquo; — you add a dependency and things appear in your application context. This article explains exactly how that happens, so you can debug it when it doesn&amp;rsquo;t, and extend it when you need to.
What Auto-Configuration Actually Does When you add spring-boot-starter-data-jpa to your project, you don&amp;rsquo;t write a single line of config — yet Spring creates a DataSource, EntityManagerFactory, and JpaTransactionManager automatically. That&amp;rsquo;s auto-configuration.
Auto-configuration is a set of @Configuration classes that Spring Boot ships.</description></item><item><title>Integration Testing with @SpringBootTest and Testcontainers</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-integration-testing/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-integration-testing/</guid><description>Integration tests verify that all layers work together — HTTP → controller → service → repository → database. This article shows how to write them efficiently with Testcontainers and manage test isolation.
@SpringBootTest — The Full Context @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class OrderIntegrationTest { // Loads the FULL Spring ApplicationContext // Everything: controllers, services, repositories, security // Starts on a random port (avoids port conflicts when running tests in parallel) } WebEnvironment options Option What it starts Use for RANDOM_PORT Embedded server on random port Full HTTP round-trip tests DEFINED_PORT Embedded server on configured port When you need a fixed port MOCK (default) No real server, MockMvc available Fast tests without real HTTP NONE No server at all Service/repo tests only Testcontainers — Real Database &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.</description></item><item><title>Inter-Service Communication with OpenFeign and RestClient</title><link>https://devops-monk.com/tutorials/spring-boot/spring-cloud-feign-restclient/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-cloud-feign-restclient/</guid><description>Services call each other over HTTP. You can use raw RestClient with a URL, or you can use OpenFeign — a declarative HTTP client that turns an interface into a fully functional HTTP client. This article covers both.
OpenFeign: Declarative HTTP Client &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-cloud-starter-openfeign&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; @SpringBootApplication @EnableFeignClients public class OrderServiceApplication { } Defining a Feign Client @FeignClient( name = &amp;#34;inventory-service&amp;#34;, // service name — resolved via Eureka path = &amp;#34;/api/inventory&amp;#34; ) public interface InventoryClient { @GetMapping(&amp;#34;/products/{productId}/availability&amp;#34;) InventoryResponse checkAvailability( @PathVariable UUID productId, @RequestParam int quantity ); @PostMapping(&amp;#34;/reservations&amp;#34;) ReservationResponse reserve(@RequestBody ReservationRequest request); @DeleteMapping(&amp;#34;/reservations/{reservationId}&amp;#34;) void cancelReservation(@PathVariable UUID reservationId); @GetMapping(&amp;#34;/products&amp;#34;) Page&amp;lt;ProductResponse&amp;gt; findProducts( @RequestParam String category, @SpringQueryMap Pageable pageable // Pageable as query params ); } Using it — just inject and call:</description></item><item><title>Introduction to Messaging with Apache Kafka</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-kafka-introduction/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-kafka-introduction/</guid><description>REST APIs are synchronous — the caller waits for a response. Sometimes you don&amp;rsquo;t want that. An order creation shouldn&amp;rsquo;t wait for the inventory system, the notification system, and the analytics system to all respond before confirming to the user. Kafka decouples these concerns.
What Kafka Is Kafka is a distributed event streaming platform. It stores events (messages) in an ordered, immutable log. Producers write to Kafka; consumers read from it.</description></item><item><title>Introduction to Spring Boot — What It Is and Why It Exists</title><link>https://devops-monk.com/tutorials/spring-boot/introduction-to-spring-boot/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/introduction-to-spring-boot/</guid><description>You want to build a Java web application or REST API. You&amp;rsquo;ve heard everyone uses Spring Boot. But what is it exactly, and why does it exist?
This article answers that — clearly — before writing a single line of code.
What Is Spring Boot? Spring Boot is an opinionated framework for building Spring-based Java applications with minimal configuration.
Break that down:
Spring-based — it sits on top of the Spring Framework, which has been the dominant Java application framework since 2003 Minimal configuration — you describe what you want (a web app, a database connection), and Spring Boot figures out how to set it up Opinionated — it makes sensible default choices so you don&amp;rsquo;t have to make every decision yourself The one-line version: Spring Boot lets you go from a blank project to a running application in minutes, with production-ready defaults built in.</description></item><item><title>Introduction to Spring Data JPA</title><link>https://devops-monk.com/tutorials/spring-boot/spring-data-jpa-introduction/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-data-jpa-introduction/</guid><description>Most Spring Boot applications need to read and write data to a relational database. Spring Data JPA makes this dramatically simpler by generating the boilerplate data access code for you. This article explains what it is, how it fits together, and how to get started.
The Stack: JPA, Hibernate, and Spring Data JPA These three things work together — understanding the layering matters:
Your Code (Repository interfaces, @Entity classes) │ ▼ Spring Data JPA (generates repository implementations, adds convenience methods) │ ▼ JPA (Jakarta Persistence API) (standard specification: @Entity, @Id, EntityManager, JPQL) │ ▼ Hibernate (JPA implementation) (translates JPA operations to SQL, manages sessions) │ ▼ JDBC (Java Database Connectivity) (sends SQL to the database) │ ▼ PostgreSQL / MySQL / H2 / etc.</description></item><item><title>JPA Entity Mapping: @Entity, @Id, @Column, and More</title><link>https://devops-monk.com/tutorials/spring-boot/spring-data-jpa-entity-mapping/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-data-jpa-entity-mapping/</guid><description>JPA entity mapping defines how Java objects translate to database tables. Get it right and your schema is clean, performant, and expressive. This article covers every mapping annotation you&amp;rsquo;ll need.
@Entity and @Table @Entity @Table( name = &amp;#34;orders&amp;#34;, // table name (default: class name) schema = &amp;#34;commerce&amp;#34;, // database schema indexes = { @Index(name = &amp;#34;idx_orders_customer_id&amp;#34;, columnList = &amp;#34;customer_id&amp;#34;), @Index(name = &amp;#34;idx_orders_status_created&amp;#34;, columnList = &amp;#34;status, created_at&amp;#34;) }, uniqueConstraints = { @UniqueConstraint(name = &amp;#34;uq_order_number&amp;#34;, columnNames = &amp;#34;order_number&amp;#34;) } ) public class Order { // .</description></item><item><title>JPA Performance: Solving N+1, Lazy Loading, and Query Optimization</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-jpa-performance-tuning/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-jpa-performance-tuning/</guid><description>JPA makes data access easy — until it silently runs hundreds of queries to load what you think is a single query. This article covers how to find and fix the most common JPA performance problems.
Enable Query Logging First You can&amp;rsquo;t fix what you can&amp;rsquo;t see. Enable SQL logging before optimizing:
logging: level: org.hibernate.SQL: DEBUG org.hibernate.orm.jdbc.bind: TRACE # log bind parameters (Spring Boot 3+) spring: jpa: properties: hibernate: format_sql: true generate_statistics: true # log query count, cache hits, etc.</description></item><item><title>JPQL, @Query, and Native Queries in Spring Data JPA</title><link>https://devops-monk.com/tutorials/spring-boot/spring-data-jpa-queries/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-data-jpa-queries/</guid><description>Derived query methods cover simple cases. Complex filtering, aggregation, and reporting queries need JPQL or native SQL. This article covers both with practical examples.
JPQL vs SQL vs Native SQL JPQL Native SQL Writes Entity-oriented (FROM Order o) Table-oriented (FROM orders o) Portability DB-agnostic DB-specific Features Basic SQL + JPA joins Full DB-specific SQL (CTEs, window functions, JSONB) Type-safety Partial None Use for Most queries Reporting, DB-specific features @Query with JPQL public interface OrderRepository extends JpaRepository&amp;lt;Order, UUID&amp;gt; { // Basic JPQL — uses entity/field names, not table/column names @Query(&amp;#34;SELECT o FROM Order o WHERE o.</description></item><item><title>JWT Authentication: Build a Complete Login System</title><link>https://devops-monk.com/tutorials/spring-boot/spring-security-jwt/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-security-jwt/</guid><description>JWT (JSON Web Token) is the standard for stateless REST API authentication. This article builds a complete JWT authentication system — login, token generation, request validation, and token refresh.
What is a JWT? A JWT has three base64url-encoded parts separated by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 ← Header (algorithm + type) .eyJzdWIiOiJ1c2VyMTIzIiwicm9sZXMiOlsiVVNFUiJdLCJpYXQiOjE3MTQ3MjY0MDAsImV4cCI6MTcxNDczMDAwMH0 ← Payload .SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ← Signature The payload contains claims:
{ &amp;#34;sub&amp;#34;: &amp;#34;user123&amp;#34;, // subject (user identifier) &amp;#34;roles&amp;#34;: [&amp;#34;USER&amp;#34;], &amp;#34;iat&amp;#34;: 1714726400, // issued at &amp;#34;exp&amp;#34;: 1714730000 // expires at } The signature is a HMAC of the header+payload — tamper-proof.</description></item><item><title>Logging: SLF4J, Logback, and Structured Logging</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-logging/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-logging/</guid><description>Logging done right gives you everything you need to diagnose production issues. Done wrong, it either buries you in noise or leaves you blind. This article covers the full logging stack — from basics to structured production logging.
The Logging Stack Your Code → SLF4J API → Logback (implementation) → Appenders (console, file, etc.) SLF4J is the facade — your code always calls LoggerFactory.getLogger() and log.info(). The implementation (Logback) is swappable without changing your code.</description></item><item><title>Microservices Architecture: When to Split and When Not to</title><link>https://devops-monk.com/tutorials/spring-boot/microservices-architecture-guide/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/microservices-architecture-guide/</guid><description>Microservices are not a technology — they&amp;rsquo;re an organizational strategy. The right reason to split a monolith is team autonomy and independent deployment, not technical elegance. This article covers when splitting makes sense and how to do it without creating a distributed monolith.
What Microservices Actually Solve Microservices address two problems:
1. Independent deployment: Team A can deploy the Order Service without coordinating with Team B&amp;rsquo;s Payment Service. No shared deployment pipeline, no release freeze, no &amp;ldquo;all-hands&amp;rdquo; deploy windows.</description></item><item><title>Migrating from Spring Boot 3.x to 4.0</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-3-to-4-migration/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-3-to-4-migration/</guid><description>Migrating from Spring Boot 3.x to 4.0 is straightforward if you&amp;rsquo;ve kept up with deprecation warnings. This guide walks through every step — from dependency updates to API changes — with before/after examples.
Pre-Migration: Fix Boot 3 Deprecations Before bumping the version, fix all deprecation warnings in your current Boot 3.x project. Every deprecated API in Boot 3 is removed in Boot 4. In IntelliJ IDEA: Analyze → Code Cleanup with &amp;ldquo;Remove deprecated usages&amp;rdquo; enabled.</description></item><item><title>Null Safety with JSpecify</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-jspecify-null-safety/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-jspecify-null-safety/</guid><description>NullPointerException is the most common runtime error in Java. JSpecify is the standardized solution — annotate your APIs and get compile-time null safety. Spring Framework 7 adopts JSpecify throughout, and your code can too.
The Problem // Is this safe? You don&amp;#39;t know without reading the implementation. public Order findById(UUID id) { return repository.findById(id).orElse(null); // returns null! } // The caller has no warning: Order order = service.findById(id); order.cancel(); // ← NullPointerException if not found Without null annotations, every method call is potentially null — you write defensive code everywhere, or you miss a case and get a NPE in production.</description></item><item><title>OAuth2 Authorization Server with Spring Security</title><link>https://devops-monk.com/tutorials/spring-boot/spring-security-oauth2-authorization-server/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-security-oauth2-authorization-server/</guid><description>Most teams use a managed auth provider (Keycloak, Auth0). But sometimes you need your own — multi-tenant SaaS, air-gapped environments, or full control over token contents. Spring Authorization Server provides a production-ready OAuth2 + OIDC implementation.
When to Build Your Own vs Use a Provider Use a managed provider (Keycloak/Auth0): Most applications. Faster to set up, maintained externally, handles compliance.
Build your own: Multi-tenant platforms issuing tokens on behalf of tenant auth providers, air-gapped or regulated environments, products that ARE the identity provider, or when you need full control over token structure and storage.</description></item><item><title>OAuth2 Resource Server: Validate JWTs from an Auth Provider</title><link>https://devops-monk.com/tutorials/spring-boot/spring-security-oauth2-resource-server/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-security-oauth2-resource-server/</guid><description>In production, you rarely build your own auth server. You use an external provider — Keycloak, Auth0, Okta, or AWS Cognito. This article shows how to configure Spring Boot as a Resource Server that validates JWTs issued by any OIDC-compliant provider.
The OAuth2 Architecture ┌─────────────────┐ │ Auth Server │ │ (Keycloak/Auth0) │ │ │ │ Issues JWTs │ │ Publishes JWKS │ └────────┬────────┘ │ ┌────────────┐ │ JWT │ Client │──────────►│ │ (Browser/ │ │ │ Mobile) │ │ └────────────┘ ▼ ┌─────────────────┐ Bearer │ Resource Server │ Token ►│ (Spring Boot) │ │ │ │ Validates JWT │ │ via JWKS URI │ └─────────────────┘ Client authenticates with the Auth Server and receives a JWT Client sends the JWT as Authorization: Bearer &amp;lt;token&amp;gt; to the Resource Server Resource Server validates the JWT by fetching the public key from the Auth Server&amp;rsquo;s JWKS endpoint If valid, the Resource Server processes the request Setup &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.</description></item><item><title>OWASP Top 10 for Spring Boot: Real Vulnerabilities and How to Fix Them</title><link>https://devops-monk.com/2026/05/spring-boot-owasp-security/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-owasp-security/</guid><description>The OWASP Top 10 lists the most critical web application security risks. Spring Boot apps have their own common failure patterns: exposed Actuator endpoints, secrets in properties files, SQL built from string concatenation, and Spring Security misconfiguration.
This guide covers the vulnerabilities that actually appear in Spring Boot applications and how to fix each one.
1. SQL Injection SQL injection remains one of the most critical vulnerabilities. It allows attackers to manipulate database queries.</description></item><item><title>Pagination and Sorting in Spring Boot</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-pagination-sorting/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-pagination-sorting/</guid><description>Returning all records from a large table in a single response is a recipe for slow APIs and crashed servers. Pagination is not optional — this article shows how to implement it properly with Spring Data.
The Problem with Returning Everything // Never do this for large datasets @GetMapping(&amp;#34;/api/orders&amp;#34;) public List&amp;lt;Order&amp;gt; getOrders() { return orderRepository.findAll(); // 1 million orders → OutOfMemoryError } Even for &amp;ldquo;small&amp;rdquo; tables, always paginate. Requirements change, data grows.</description></item><item><title>Password Encoding and User Authentication</title><link>https://devops-monk.com/tutorials/spring-boot/spring-security-authentication/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-security-authentication/</guid><description>Every application needs user registration and login. This article builds a complete authentication system — from storing passwords safely to handling failed login attempts.
Never Store Passwords in Plain Text Store a one-way hash, not the password. BCrypt is the industry standard:
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(12); // cost factor 12 → ~250ms per hash on modern hardware // strong enough to slow down brute-force attacks } BCrypt properties:</description></item><item><title>Producing and Consuming Kafka Messages</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-kafka-producer-consumer/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-kafka-producer-consumer/</guid><description>This article implements Kafka producers and consumers with the full production setup — error handling, retries, dead-letter topics, and idempotent consumers.
Producer: KafkaTemplate @Service @RequiredArgsConstructor @Slf4j public class OrderEventPublisher { private final KafkaTemplate&amp;lt;String, Object&amp;gt; kafkaTemplate; public void publishOrderCreated(Order order) { OrderCreatedEvent event = new OrderCreatedEvent( order.getId(), order.getCustomerId(), order.getCustomerEmail(), order.getItems().stream().map(OrderItemDto::from).toList(), order.getTotalAmount(), Instant.now() ); // Key = customerId: all events for same customer go to same partition kafkaTemplate.send(&amp;#34;order-events&amp;#34;, order.getCustomerId().toString(), event) .whenComplete((result, ex) -&amp;gt; { if (ex !</description></item><item><title>Reliable Event Publishing: The Transactional Outbox Pattern</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-kafka-outbox-pattern/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-kafka-outbox-pattern/</guid><description>There is a fundamental problem with publishing Kafka events after a database commit: if the application crashes between the commit and the publish, the event is lost forever. The Transactional Outbox Pattern solves this.
The Problem @Transactional public Order createOrder(CreateOrderRequest request) { Order order = orderRepository.save(buildOrder(request)); // DB committed ✓ kafkaTemplate.send(&amp;#34;order-events&amp;#34;, event); // ← Crash here → event lost, DB already committed // → Inventory never updated, customer never notified return order; } Two distributed systems (PostgreSQL and Kafka) can&amp;rsquo;t be in a single transaction.</description></item><item><title>Resilience Patterns with Resilience4j</title><link>https://devops-monk.com/tutorials/spring-boot/spring-cloud-resilience4j/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-cloud-resilience4j/</guid><description>In microservices, every network call can fail. A slow dependency can exhaust your thread pool, cascading into a full outage. Resilience4j provides the patterns to handle these failures gracefully — without hiding them.
Setup &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;io.github.resilience4j&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;resilience4j-spring-boot3&amp;lt;/artifactId&amp;gt; &amp;lt;version&amp;gt;2.2.0&amp;lt;/version&amp;gt; &amp;lt;/dependency&amp;gt; &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-boot-starter-aop&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; Circuit Breaker A circuit breaker wraps a remote call. When failures exceed a threshold, the circuit &amp;ldquo;opens&amp;rdquo; and calls fail immediately (without waiting for a timeout) — protecting your thread pool and giving the failing service time to recover.</description></item><item><title>Role-Based Access Control with @PreAuthorize</title><link>https://devops-monk.com/tutorials/spring-boot/spring-security-rbac/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-security-rbac/</guid><description>Roles and permissions control what authenticated users can do. This article implements a complete RBAC system — from URL-level rules to method-level security and resource ownership checks.
Roles vs Permissions Roles are coarse-grained groupings (USER, MANAGER, ADMIN).
Permissions are fine-grained actions (READ_ORDERS, WRITE_PRODUCTS, DELETE_USERS).
Assign permissions to roles:
ADMIN → all permissions MANAGER → READ_ORDERS, WRITE_ORDERS, READ_PRODUCTS, WRITE_PRODUCTS USER → READ_OWN_ORDERS, WRITE_OWN_ORDERS, READ_PRODUCTS Model permissions as a typed enum:
public enum Permission { // Order permissions READ_ORDERS, WRITE_ORDERS, DELETE_ORDERS, READ_OWN_ORDERS, WRITE_OWN_ORDERS, // Product permissions READ_PRODUCTS, WRITE_PRODUCTS, DELETE_PRODUCTS, // User management READ_USERS, WRITE_USERS, DELETE_USERS } public enum Role { USER(Set.</description></item><item><title>Service Discovery with Eureka</title><link>https://devops-monk.com/tutorials/spring-boot/spring-cloud-eureka-service-discovery/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-cloud-eureka-service-discovery/</guid><description>In a microservices environment, services scale up and down dynamically. You can&amp;rsquo;t hardcode IP addresses — a service running on 10 pods today has 10 different addresses. Service discovery solves this: services register themselves, and clients look up live instances by name.
What Service Discovery Does Without service discovery: Order Service → http://192.168.1.45:8081/api/inventory ← hardcoded, breaks when IP changes With service discovery: Order Service → &amp;#34;inventory-service&amp;#34; → Eureka → [192.168.1.45:8081, 192.</description></item><item><title>Spring AI 2.0: Build a RAG Application with Spring Boot</title><link>https://devops-monk.com/2026/05/spring-ai-rag-application/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-ai-rag-application/</guid><description>Spring AI 1.0 GA shipped in May 2025. It brings the Spring programming model to AI development: a unified ChatClient API that works across Claude, OpenAI, Gemini, Ollama, and Azure OpenAI — switching AI providers is changing one dependency.
This guide builds a complete RAG (Retrieval-Augmented Generation) application that answers questions about your documentation using any AI provider.
What Is RAG? A large language model (LLM) knows everything in its training data but nothing about your specific documents, code, or business data.</description></item><item><title>Spring AI: Build a RAG Application</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-spring-ai-rag/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-spring-ai-rag/</guid><description>Large language models know a lot — but not about your data. RAG (Retrieval-Augmented Generation) solves this: find the relevant context from your documents, inject it into the prompt, and let the model answer grounded in your data. This article builds a complete RAG API with Spring AI 2.0.
What You&amp;rsquo;ll Build A Q&amp;amp;A API over your product documentation:
User: &amp;#34;What&amp;#39;s the return policy for electronics?&amp;#34; → Search vector store for relevant docs → Inject matching paragraphs into prompt → Claude/GPT answers based on your actual docs Without RAG: the LLM guesses or hallucinate your policy.</description></item><item><title>Spring Bean Scopes and Lifecycle</title><link>https://devops-monk.com/tutorials/spring-boot/spring-bean-scopes-lifecycle/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-bean-scopes-lifecycle/</guid><description>Every bean in the Spring container has a scope (how many instances exist and for how long) and a lifecycle (what happens when it&amp;rsquo;s created and destroyed). Understanding these prevents subtle bugs and lets you optimize resource usage.
Bean Scopes Overview Scope Instances Available in singleton One per ApplicationContext All apps prototype New instance every time All apps request One per HTTP request Web apps session One per HTTP session Web apps application One per ServletContext Web apps Singleton (Default) By default, every Spring bean is a singleton — one instance per ApplicationContext.</description></item><item><title>Spring Boot 2.x → 3.x → 4.x Migration: The Definitive Checklist</title><link>https://devops-monk.com/2026/05/spring-boot-migration-guide/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-migration-guide/</guid><description>Many teams are still running Spring Boot 2.7.x. Spring Boot 2.x reached end of life in November 2023, which means no more security patches. The jump to 4.0 is two generations, and the breaking changes are real — but they are also well-documented and mostly automatable.
This guide walks through the migration in stages: 2.x → 3.0 first, then 3.x incremental updates, then 4.0. Each section lists what breaks and how to fix it.</description></item><item><title>Spring Boot 4.0: Everything That Changed (Complete Guide)</title><link>https://devops-monk.com/2026/05/spring-boot-4-complete-guide/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-4-complete-guide/</guid><description>Spring Boot 4.0 was released on November 20, 2025. It is built on Spring Framework 7 and represents the most significant shift in the Spring ecosystem since the Jakarta EE migration in Spring Boot 3. The headline change is full modularisation — the single spring-boot-autoconfigure JAR has been split into 70+ granular modules. But that is just the start.
This guide covers every change that matters, what breaks on upgrade, and what is genuinely new and useful.</description></item><item><title>Spring Boot Actuator: Health, Metrics, and Management Endpoints</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-actuator/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-actuator/</guid><description>A running application is not enough — you need to know if it&amp;rsquo;s healthy, how it&amp;rsquo;s performing, and what it&amp;rsquo;s doing. Spring Boot Actuator exposes that information through HTTP endpoints and metrics.
Setup &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-boot-starter-actuator&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; By default, only /actuator/health and /actuator/info are exposed over HTTP. Everything else is available via JMX. Enable what you need:
management: endpoints: web: exposure: include: health,info,metrics,prometheus,conditions,beans,env,loggers,threaddump,heapdump base-path: /actuator endpoint: health: show-details: when-authorized # or &amp;#39;always&amp;#39; (dev), &amp;#39;never&amp;#39; (public) show-components: when-authorized metrics: enabled: true server: port: 8081 # expose actuator on a separate port (not public-facing) Health Endpoint GET /actuator/health — used by Kubernetes liveness/readiness probes and load balancers:</description></item><item><title>Spring Boot Actuator: Production Monitoring with Prometheus and Grafana</title><link>https://devops-monk.com/2026/05/spring-boot-actuator-prometheus-grafana/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-actuator-prometheus-grafana/</guid><description>Spring Boot Actuator exposes production-ready operational endpoints — health checks, metrics, environment info, thread dumps — out of the box. Combined with Prometheus and Grafana, you get a full monitoring stack with minimal configuration.
This guide covers everything from initial setup to Kubernetes health probes, custom metrics, and securing your management endpoints.
Setup Dependencies &amp;lt;dependencies&amp;gt; &amp;lt;!-- Actuator --&amp;gt; &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-boot-starter-actuator&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; &amp;lt;!-- Micrometer Prometheus registry --&amp;gt; &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;io.micrometer&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;micrometer-registry-prometheus&amp;lt;/artifactId&amp;gt; &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt; &amp;lt;/dependency&amp;gt; &amp;lt;/dependencies&amp;gt; Basic configuration # application.</description></item><item><title>Spring Boot Caching: Multi-Level Cache with Caffeine + Redis</title><link>https://devops-monk.com/2026/05/spring-boot-caching-caffeine-redis/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-caching-caffeine-redis/</guid><description>Caching reduces database load and response latency. Spring Boot&amp;rsquo;s cache abstraction lets you add caching with annotations, then swap the implementation (Caffeine, Redis, multi-level) without changing your business code.
This guide covers Caffeine for in-JVM caching, Redis for distributed caching, and a multi-level cache that combines both.
Spring Cache Abstraction Spring&amp;rsquo;s cache abstraction uses three annotations:
Annotation Behaviour @Cacheable Cache the return value. On subsequent calls, return from cache without executing the method.</description></item><item><title>Spring Boot Docker: Multi-Stage Builds, Layered JARs, and Buildpacks</title><link>https://devops-monk.com/2026/05/spring-boot-docker-guide/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-docker-guide/</guid><description>There are three ways to containerise a Spring Boot application: a naive single-stage Dockerfile, a proper multi-stage Dockerfile with layered JARs, and Cloud Native Buildpacks. Each has different tradeoffs in build speed, image size, and maintenance overhead.
This guide covers all three approaches, explains why layered JARs matter for CI/CD speed, and shows how to produce small, secure, production-ready images.
The Problem with the Naive Dockerfile Most tutorials show this:</description></item><item><title>Spring Boot Full Observability: Prometheus + Grafana + Tempo + Loki</title><link>https://devops-monk.com/2026/05/spring-boot-observability-stack/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-observability-stack/</guid><description>Observability means you can answer &amp;ldquo;what is wrong and why&amp;rdquo; from your system&amp;rsquo;s outputs alone — without adding new instrumentation after an incident. It requires three types of data: metrics (what happened), traces (why it happened), and logs (the details).
Spring Boot 4 ships a single OpenTelemetry starter that covers all three. This guide shows how to wire up the complete observability stack: Prometheus + Grafana for metrics, Grafana Tempo for distributed tracing, and Grafana Loki for logs.</description></item><item><title>Spring Boot Integration: Zero-Config Setup and Full Properties Reference</title><link>https://devops-monk.com/tutorials/liquibase/liquibase-spring-boot-integration/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/liquibase/liquibase-spring-boot-integration/</guid><description>Running Liquibase from the CLI is fine for learning and for standalone scripts. In a real Spring Boot application, you want migrations to run automatically at startup — before the application code touches the database. Spring Boot&amp;rsquo;s Liquibase auto-configuration handles this with zero boilerplate: add the dependency, point to your changelog, and migrations run before the application context is ready.
This article covers the complete integration: Maven/Gradle setup, how auto-run works and why, the full spring.</description></item><item><title>Spring Boot JPA Performance: Solving N+1, Lazy Loading, and Query Optimization</title><link>https://devops-monk.com/2026/05/spring-boot-jpa-performance/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-jpa-performance/</guid><description>JPA makes database access simple. It also makes it dangerously easy to write code that fires 100 SQL queries to load 10 records. The N+1 problem alone has caused more production performance incidents than almost any other JPA issue.
This guide covers how to find and fix the five most common JPA performance problems: N+1 queries, LazyInitializationException, over-fetching, poor connection pool sizing, and Hibernate 6 breaking changes.
Enable SQL Logging First Before optimizing anything, see exactly what queries are firing:</description></item><item><title>Spring Boot Microservices Full Stack: Eureka + Gateway + Config Server + Resilience4j</title><link>https://devops-monk.com/2026/05/spring-boot-microservices-full-stack/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-microservices-full-stack/</guid><description>Building microservices requires more than splitting a monolith into services. You need service discovery, a gateway to route traffic, centralised configuration management, and resilience patterns to handle inevitable failures. Spring Cloud provides all of this as a cohesive stack.
This guide builds a complete microservices architecture from scratch: Eureka for service discovery, Spring Cloud Gateway for routing, Spring Cloud Config Server for centralised config, and Resilience4j for circuit breakers and retry.</description></item><item><title>Spring Boot OAuth2 + JWT: End-to-End Zero-Trust API Security</title><link>https://devops-monk.com/2026/05/spring-boot-oauth2-jwt-security/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-oauth2-jwt-security/</guid><description>Zero-trust API security means every request is validated independently — no session state, no &amp;ldquo;trusted network&amp;rdquo; assumptions. A JWT bearer token is issued by an authorisation server, signed cryptographically, and validated on every API call. The API never calls back to the authorisation server during validation; it verifies the token&amp;rsquo;s signature locally.
This guide covers the complete setup: dependencies, resource server configuration, token validation (both symmetric and asymmetric), extracting claims, role-based access control, method-level security, and the Spring Security 7 changes that break existing setups.</description></item><item><title>Spring Boot on Kubernetes</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-kubernetes/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-kubernetes/</guid><description>Kubernetes is the standard platform for running containerized microservices. Spring Boot integrates naturally with Kubernetes — Actuator probes map directly to Kubernetes probes, and Spring configuration maps to ConfigMaps and Secrets.
Core Kubernetes Resources Deployment # deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: order-service labels: app: order-service spec: replicas: 3 selector: matchLabels: app: order-service template: metadata: labels: app: order-service version: &amp;#34;1.2.3&amp;#34; spec: containers: - name: order-service image: devopsmonk/order-service:1.2.3 ports: - containerPort: 8080 name: http - containerPort: 8081 name: management # Resource limits — always set these resources: requests: memory: &amp;#34;256Mi&amp;#34; cpu: &amp;#34;250m&amp;#34; limits: memory: &amp;#34;512Mi&amp;#34; cpu: &amp;#34;1000m&amp;#34; # Environment from ConfigMap and Secret envFrom: - configMapRef: name: order-service-config - secretRef: name: order-service-secrets # Individual env vars env: - name: SPRING_PROFILES_ACTIVE value: prod - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.</description></item><item><title>Spring Boot on Kubernetes: Health Checks, Graceful Shutdown, and Config Management</title><link>https://devops-monk.com/2026/05/spring-boot-kubernetes-guide/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-kubernetes-guide/</guid><description>Running Spring Boot on Kubernetes is not just packaging the app in a container and deploying it. You need to configure health probes correctly, handle graceful shutdown so in-flight requests don&amp;rsquo;t get dropped, manage configuration without baking secrets into images, and make sure the JVM respects container memory limits.
This guide covers the production-critical Kubernetes configuration for Spring Boot applications.
Health Probes Kubernetes uses three probe types to manage pod lifecycle:</description></item><item><title>Spring Boot Project Structure Explained</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-project-structure/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-project-structure/</guid><description>A Spring Boot project looks simple on the surface but has a specific structure with specific conventions. Understanding it upfront saves hours of confusion later.
The Standard Layout order-service/ ├── pom.xml ├── mvnw # Maven Wrapper script (Unix) ├── mvnw.cmd # Maven Wrapper script (Windows) ├── .mvn/ │ └── wrapper/ │ └── maven-wrapper.properties └── src/ ├── main/ │ ├── java/ │ │ └── com/devopsmonk/orderservice/ │ │ └── OrderServiceApplication.java │ └── resources/ │ ├── application.</description></item><item><title>Spring Boot Testing with Testcontainers: The Right Way</title><link>https://devops-monk.com/2026/05/spring-boot-testcontainers/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-testcontainers/</guid><description>Testcontainers spins up real Docker containers for your tests — a real PostgreSQL database, a real Redis, a real Kafka broker. No more mocking JDBC connections or in-memory H2 databases that behave differently from production.
Spring Boot 3.1 added @ServiceConnection, which removes the boilerplate of configuring connection URLs manually. This guide covers the right patterns for fast, reliable integration tests with Testcontainers.
Why Testcontainers Over H2 Teams use H2 in-memory databases for testing because it&amp;rsquo;s fast.</description></item><item><title>Spring Boot Virtual Threads: Benchmarks, Pitfalls, and When NOT to Use Them</title><link>https://devops-monk.com/2026/05/spring-boot-virtual-threads/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-virtual-threads/</guid><description>Virtual Threads landed in Java 21 as a stable feature, and Spring Boot 3.2 added first-class support with a single property. The promise: write simple blocking code and get WebFlux-level throughput. The reality is mostly true — with some important exceptions.
This article covers what Virtual Threads actually are, how to enable them in Spring Boot, real benchmark numbers, the three pitfalls that will silently destroy your performance, and a decision framework for when to use them (and when not to).</description></item><item><title>Spring Boot vs Quarkus in 2026: An Honest Benchmarked Comparison</title><link>https://devops-monk.com/2026/05/spring-boot-vs-quarkus/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-vs-quarkus/</guid><description>Every year, someone asks: &amp;ldquo;Should we use Spring Boot or Quarkus?&amp;rdquo; In 2026, both frameworks are mature, both run natively, and both work well on Kubernetes. The differences come down to developer experience, ecosystem size, and specific performance characteristics.
This is an honest comparison with real numbers, not marketing claims.
The Frameworks at a Glance Spring Boot 4 (November 2025): Built on Spring Framework 7. The de-facto standard for enterprise Java.</description></item><item><title>Spring Data with PostgreSQL</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-postgresql/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-postgresql/</guid><description>PostgreSQL offers powerful features beyond basic SQL — JSONB, arrays, full-text search, advisory locks. This article shows how to use them from Spring Boot and how to tune HikariCP for production.
Project Setup &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-boot-starter-data-jpa&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.postgresql&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;postgresql&amp;lt;/artifactId&amp;gt; &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt; &amp;lt;/dependency&amp;gt; spring: datasource: url: jdbc:postgresql://localhost:5432/orderdb username: app password: ${DB_PASSWORD} driver-class-name: org.postgresql.Driver jpa: database-platform: org.hibernate.dialect.PostgreSQLDialect hibernate: ddl-auto: validate HikariCP — Connection Pool Tuning Spring Boot uses HikariCP by default — the fastest JDBC connection pool.</description></item><item><title>Spring IoC and Dependency Injection</title><link>https://devops-monk.com/tutorials/spring-boot/spring-ioc-dependency-injection/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-ioc-dependency-injection/</guid><description>Every Spring Boot application is built on one idea: the framework creates and wires your objects, not you. This article explains how that works and how to use it effectively.
Inversion of Control In traditional Java, you create objects yourself:
// You control the dependencies public class OrderService { private final OrderRepository repository = new JpaOrderRepository(); private final EmailService email = new SmtpEmailService(&amp;#34;smtp.gmail.com&amp;#34;); } Problems:
OrderService is tightly coupled to specific implementations You can&amp;rsquo;t swap JpaOrderRepository for a mock in tests without editing OrderService If SmtpEmailService needs its own dependencies, you must construct those too Inversion of Control (IoC) flips this: instead of creating your dependencies, you declare what you need and let a container provide them.</description></item><item><title>Spring Modulith: Build a Modular Monolith Before You Commit to Microservices</title><link>https://devops-monk.com/2026/05/spring-modulith-guide/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-modulith-guide/</guid><description>Microservices solve real problems: independent deployability, team autonomy, technology flexibility. They also create real problems: distributed transactions, network latency, operational complexity. Many teams split into microservices too early, before they understand their domain well enough to draw stable boundaries.
Spring Modulith gives you module boundaries, enforced isolation, and event-driven decoupling inside a single deployable JAR. It&amp;rsquo;s the pragmatic middle ground.
The Modular Monolith Problem It Solves A typical Spring Boot monolith looks like this after a year:</description></item><item><title>Spring Security Fundamentals: Filter Chain, Authentication, and Authorization</title><link>https://devops-monk.com/tutorials/spring-boot/spring-security-fundamentals/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-security-fundamentals/</guid><description>Spring Security is powerful but famously hard to understand. This article demystifies the core: the filter chain, how requests are processed, and how authentication and authorization work before writing a line of security config.
Setup &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-boot-starter-security&amp;lt;/artifactId&amp;gt; &amp;lt;/dependency&amp;gt; The moment you add this dependency, Spring Boot&amp;rsquo;s auto-configuration secures all endpoints with HTTP Basic authentication. A random password is printed at startup. This is the starting point — you&amp;rsquo;ll replace the defaults.</description></item><item><title>Testing Secured Endpoints</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-security-testing/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-security-testing/</guid><description>Security tests verify that your endpoints behave correctly for different users, roles, and authentication states. This article covers the full toolkit — from simple annotations to custom security contexts.
Setup &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.security&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-security-test&amp;lt;/artifactId&amp;gt; &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt; &amp;lt;/dependency&amp;gt; spring-boot-starter-test includes this automatically.
@WithMockUser — Simple Role-Based Tests The simplest way to run a test as an authenticated user:
@WebMvcTest(OrderController.class) class OrderControllerSecurityTest { @Autowired MockMvc mockMvc; @MockBean OrderService orderService; // No authentication @Test void unauthenticatedUserIsRejected() throws Exception { mockMvc.</description></item><item><title>Testing Spring Boot Apps: Unit Tests with JUnit 5 and Mockito</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-unit-testing/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-unit-testing/</guid><description>Good tests catch regressions, document behavior, and give you confidence to refactor. Bad tests slow you down. This article covers unit testing at the service layer — fast, focused, no Spring context needed.
Setup &amp;lt;!-- spring-boot-starter-test includes JUnit 5, Mockito, AssertJ --&amp;gt; &amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;spring-boot-starter-test&amp;lt;/artifactId&amp;gt; &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt; &amp;lt;/dependency&amp;gt; This pulls in:
JUnit 5 (Jupiter) — test runner and assertions Mockito — mocking framework AssertJ — fluent assertions (assertThat(...)) Hamcrest — matcher library MockMvc — web layer testing (next article) Testcontainers integration Unit Tests vs Integration Tests Unit Integration Scope One class in isolation Multiple components together Dependencies All mocked Real or near-real Speed Milliseconds Seconds to minutes Context No Spring context Spring context loads Purpose Logic correctness Component interaction Start with unit tests.</description></item><item><title>Testing the Repository Layer with @DataJpaTest</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-repository-testing/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-repository-testing/</guid><description>Repository tests verify your queries work correctly against a real database. Spring Boot&amp;rsquo;s @DataJpaTest starts a minimal slice — only JPA components — making tests fast while still catching real SQL issues.
@DataJpaTest — What It Loads @DataJpaTest is a test slice annotation:
@DataJpaTest class OrderRepositoryTest { // Spring loads: // - Your @Entity classes // - Your @Repository interfaces // - JPA infrastructure (EntityManager, transactions) // - An in-memory H2 database (by default) // // Spring does NOT load: // - @Service, @Controller, @Component classes // - Security configuration // - The full ApplicationContext } Each test method runs in a transaction that&amp;rsquo;s rolled back at the end — no data pollution between tests.</description></item><item><title>Testing the Web Layer with @WebMvcTest and MockMvc</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-web-layer-testing/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-web-layer-testing/</guid><description>Controller tests verify HTTP mapping, request parsing, validation, serialization, and security — without starting a full server. @WebMvcTest + MockMvc gives you a fast, focused web layer test.
@WebMvcTest — What It Loads @WebMvcTest(OrderController.class) class OrderControllerTest { // Spring loads: // - Your @Controller class (and its dependencies) // - DispatcherServlet, MVC configuration // - Jackson ObjectMapper // - Security (if configured) // // Spring does NOT load: // - @Service, @Repository beans // - Database, JPA // // You @MockBean all services } Basic Controller Test @WebMvcTest(OrderController.</description></item><item><title>Top 50 Spring Boot Interview Questions for 2026 (With Detailed Answers)</title><link>https://devops-monk.com/2026/05/spring-boot-interview-questions/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/2026/05/spring-boot-interview-questions/</guid><description>These are the questions that actually come up in Spring Boot interviews — at startups, scale-ups, and large enterprises. Each answer explains the concept clearly, with the level of depth an interviewer expects from a mid-level or senior developer.
Questions are grouped by topic. For junior roles, focus on sections 1–3. For senior roles, everything here is fair game.
Section 1: Core Fundamentals Q1. What is the difference between Spring and Spring Boot?</description></item><item><title>Transactions: @Transactional, Propagation, and Isolation Levels</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-transactions/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-transactions/</guid><description>A transaction ensures that a group of operations either all succeed or all fail — no partial state. Spring&amp;rsquo;s @Transactional makes this simple to use, but the underlying mechanics matter when things go wrong.
How @Transactional Works @Transactional is implemented via AOP (Aspect-Oriented Programming). Spring wraps your bean in a proxy:
Client calls orderService.create() │ ▼ Spring AOP proxy intercepts the call │ ▼ BEGIN TRANSACTION │ ▼ Your actual method body executes (all DB operations share one connection and transaction) │ ├─ No exception → COMMIT │ └─ RuntimeException thrown → ROLLBACK │ ▼ Client receives result (or exception) This means @Transactional only works when:</description></item><item><title>What's New in Spring Boot 4.0</title><link>https://devops-monk.com/tutorials/spring-boot/spring-boot-4-whats-new/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/spring-boot-4-whats-new/</guid><description>Spring Boot 4.0 (November 2025) is a major release built on Spring Framework 7 and Java 17+. It&amp;rsquo;s the most significant Spring release since Boot 3&amp;rsquo;s Jakarta EE migration. This article covers every change that affects a practicing developer.
Minimum Requirements Spring Boot 3.x Spring Boot 4.0 Java 17 17 (baseline), 21 recommended Spring Framework 6.x 7.x Jakarta EE 10 11 Tomcat 10.x 11.x Hibernate 6.x 7.x Gradle (if used) 7.</description></item><item><title>Your First Spring Boot Application</title><link>https://devops-monk.com/tutorials/spring-boot/first-spring-boot-application/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://devops-monk.com/tutorials/spring-boot/first-spring-boot-application/</guid><description>In this article you&amp;rsquo;ll create a Spring Boot application, add a REST endpoint, and run it — all in under 10 minutes. Then you&amp;rsquo;ll understand exactly what each piece does.
What you&amp;rsquo;ll build: A Spring Boot app that responds to GET /hello with &amp;quot;Hello, Spring Boot!&amp;quot;.
Prerequisites JDK 21 or higher installed (java -version to verify) Maven 3.9+ installed (mvn -version to verify) An IDE — IntelliJ IDEA (recommended), VS Code with Java extension, or Eclipse Step 1: Generate the Project Go to start.</description></item></channel></rss>