Been Writing Spring Controllers for a Decade? Time to Ditch the Boilerplate Pattern

The article argues that traditional Spring Controllers impose heavy, repetitive scaffolding that outweighs business value, and demonstrates how a functional Java API can replace class‑based controllers with simple handler functions, reducing cognitive load, test complexity, and development overhead.

LuTiao Programming
LuTiao Programming
LuTiao Programming
Been Writing Spring Controllers for a Decade? Time to Ditch the Boilerplate Pattern

Problem: Heavy Spring Controller Boilerplate

Adding a simple read‑only endpoint often requires creating a controller class, request/response DTOs, a mapper, validation annotation, a unified exception wrapper and starting half a Spring Boot context for tests. A PR example shows seven new items across multiple packages, and review discussions focus on where to place annotations rather than on business logic.

Typical Reflexive Pattern

New requirement → New Controller → New DTO → Validation → Mapper → Unified response → Exception wrapper

Even when the core logic is a single line return userService.findById(id);, the project adopts a directory layout:

/src/main/java
└── com/icoderoad/demo
    ├── controller
    ├── service
    ├── dto
    ├── vo
    ├── mapper
    └── exception

This raises the question whether an interface truly needs so many layers.

Analysis of Boilerplate Ratio

≈80 % of controller code is repetitive boilerplate.

≈15 % is imposed conventions.

≈5 % implements actual business logic.

Consequences:

Tests must start a Spring container.

Changing a single line of logic touches many files.

Code reviews discuss annotations instead of business.

Functional Java API Alternative

Viewing an HTTP endpoint as input → processing → output leads to a function‑based definition.

Traditional Spring Controller

@RestController
@RequestMapping("/users")
public class UserController {
    @GetMapping("/{id}")
    public ResponseEntity<UserVO> findById(@PathVariable Long id) {
        User user = userService.findById(id);
        return ResponseEntity.ok(UserMapper.toVO(user));
    }
}

Functional API Definition

package com.icoderoad.api.user;
import static com.icoderoad.web.Http.*;

public class UserApi {
    public static final Handler getUserById =
        GET("/users/{id}", req -> {
            Long id = req.pathVar("id", Long.class);
            return ok(userService().findById(id));
        });
}

The only change is replacing the class‑plus‑annotations model with a plain function that returns the result directly, eliminating hidden framework magic.

Testing Comparison

Traditional controller tests require:

Starting the Spring context

Mocking the web layer

Building HTTP requests

Parsing the response

With the functional API the test becomes a simple unit test:

@Test
void should_return_user() {
    var response = UserApi.getUserById.handle(fakeRequest("/users/1"));
    assertThat(response.status()).isEqualTo(200);
}

No container, no framework dependency, and the business logic is directly verifiable, resulting in faster feedback.

When the Functional Style Is Advantageous

Read‑heavy, write‑light endpoints

Internal systems or admin back‑ends

API aggregation layers / gateways

Modules where test execution speed is critical

Key Insight

The issue is not the Spring framework itself but the habit of following a fixed layered template without considering the simplicity of the underlying logic. When the interface logic is simpler than its surrounding structure, the structure should yield.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaTestingBackend DevelopmentSpringControllerFunctional API
LuTiao Programming
Written by

LuTiao Programming

LuTiao Programming is a friendly community offering free programming lessons. We inspire learners to explore new ideas and technologies and quickly acquire job-ready skills.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.