Spring-Boot

209 posts in this section

Centralized Configuration with Spring Cloud Config Server

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 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> @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.

Continue reading »

Chunk-Oriented Processing: The Core Spring Batch Pattern

The read-process-write loop is at the heart of almost every Spring Batch job. Understanding exactly how it works — where transactions begin and end, what gets rolled back on failure, and how Spring Batch knows where to restart — makes everything else in the framework click into place. This article goes deep on chunk-oriented processing: the execution model, the three interfaces, the counters that track progress, and how to size chunks correctly.

Continue reading »

Configuring Jobs and Steps: Flows, Decisions, and Conditional Execution

Introduction So far every example has had a single step. Real batch jobs usually have multiple steps — validate input, import data, generate a report, send a notification, clean up temp files. Spring Batch’s JobBuilder DSL lets you compose these steps into flows with conditional branching, parallel execution, and decision logic. This article covers: Linear multi-step jobs Conditional step transitions using ExitStatus JobExecutionDecider for runtime branching Parallel flows with split Nested jobs with FlowStep The Flow abstraction for reusable step sequences Linear Multi-Step Job The simplest multi-step job runs steps in sequence.

Continue reading »

CRUD Operations with JpaRepository

You have entities and repositories set up. Now let’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 -> { OrderItem item = new OrderItem(); item.setProductId(itemReq.productId()); item.setQuantity(itemReq.quantity()); item.setUnitPrice(itemReq.unitPrice()); order.addItem(item); // manages bidirectional relationship }); return orderRepository.

Continue reading »

Database Migrations with Flyway

Never use spring.jpa.hibernate.ddl-auto=update in production. It’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’t match the expected state → fails fast Benefits:

Continue reading »

Dockerizing Spring Boot Applications

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’t Use This) FROM eclipse-temurin:21-jdk COPY target/order-service.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"] 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.

Continue reading »

DTOs and Response Shaping

Every beginner makes the same mistake: returning JPA entities directly from REST controllers. This article explains why that’s dangerous, and how to design clean DTOs that make your API stable, secure, and maintainable. Why Not Return Entities Directly? Consider this: @GetMapping("/{id}") 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.

Continue reading »

Entity Relationships: @OneToMany, @ManyToOne, @ManyToMany

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:

Continue reading »

Event-Driven Spring Boot: Transactional Outbox Pattern with Kafka

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.

Continue reading »

Externalized Configuration with @ConfigurationProperties

@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("${payment.gateway.url}") private String gatewayUrl; @Value("${payment.gateway.timeout:5000}") private int timeoutMs; @Value("${payment.gateway.api-key}") private String apiKey; @Value("${payment.gateway.max-retries:3}") 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:

Continue reading »