Say No to Lombok: Embrace MapStruct + Java Records for Clean, Modern Java
araf

araf @haraf

Joined:
Feb 10, 2025

Say No to Lombok: Embrace MapStruct + Java Records for Clean, Modern Java

Publish Date: May 15
12 7

Drop the boilerplate and embrace immutability, type safety, and clean mapping in your Spring Boot applications — no more @Data magic ✨.


👋 Goodbye, Lombok (and Why)

If you've been a Java developer for any length of time, you've likely used Lombok to get rid of repetitive getter/setter/constructor code. It’s a convenient crutch—but like all shortcuts, it comes with trade-offs:

  • IDE confusion: Code generated behind the scenes sometimes breaks static analysis or autocomplete.
  • Debugging hell: Stepping into generated code? Not easy.
  • Hidden complexity: Lombok hides a lot of logic, making code less explicit.

It’s 2025 — we can do better.


✅ The Better Way: Java Records + MapStruct

🔹 Java Records

Introduced in Java 14 and stable since Java 16+, record is a special kind of class that’s:

  • Immutable by default
  • Comes with a compact syntax
  • Auto-generates equals(), hashCode(), toString(), and constructors
public record UserDTO(Long id, String name, String email) {}
Enter fullscreen mode Exit fullscreen mode

🔹 MapStruct

MapStruct is a code generator that simplifies object mapping between types (like Entity ↔ DTO).

It’s:

  • Type-safe and compile-time checked
  • Blazing fast (no reflection!)
  • Easy to integrate with Spring Boot

🧑‍💻 Real-World Example: Entity ↔ DTO

1. Define Your JPA Entity

@Entity
public class UserEntity {
    @Id
    private Long id;
    private String name;
    private String email;
}
Enter fullscreen mode Exit fullscreen mode

2. Create an Immutable DTO with Records

public record UserDTO(Long id, String name, String email) {}
Enter fullscreen mode Exit fullscreen mode

3. Auto-map with MapStruct

@Mapper(componentModel = "spring")
public interface UserMapper {
    UserDTO toDTO(UserEntity user);
    UserEntity toEntity(UserDTO dto);
}
Enter fullscreen mode Exit fullscreen mode

Spring will inject UserMapper automatically. No reflection, no surprises.


⚖️ Lombok vs MapStruct + Records

Feature Lombok MapStruct + Records
Boilerplate Removal
Immutability ❌ (@Value is limited) ✅ (Records are final)
Debuggable ❌ (hidden code) ✅ (explicit and generated)
IDE Support ⚠️ Sometimes flaky ✅ Excellent
Mapping Support ❌ Manual ✅ Automatic via MapStruct
Type Safety ⚠️ Risky ✅ Checked at compile time

🚧 Drawbacks to Consider

  • Java 14+ required: Records aren’t available in older versions.
  • No mutable DTOs: If you need setters, Records may not be ideal.
  • Extra annotation processing setup: MapStruct needs build-time config.

But for most modern Spring Boot microservices or REST APIs? This combo is a clear winner.


🔚 Final Thoughts

Lombok had its time. But in today’s world of immutability, clean architecture, and strong typing, it's time to move on.

By using MapStruct + Java Records, you:

  • Simplify DTO mapping
  • Improve code clarity and maintainability
  • Reduce bugs caused by unintended mutations

📦 Bonus: Starter Template?

Let me know in the comments if you’d like a GitHub starter repo with Spring Boot + MapStruct + Records — happy to share!

Comments 7 total

  • Semyon Levin
    Semyon LevinMay 17, 2025
    1. @Value is more flexible. Especially, together with @builder (+ @default/@Singular)
    2. All the bytecode that records have is also non-debuggable. And, frankly, there is nothing to debug in getters
    3. MapStruct does support Lombok. @builder is supported too.
    4. What can be risky is terms of type-safety?

    The only valid point could be IDE support. But current Lombok IDE plugins are very good.

    Java authers did a lot in terms of reducing boilerplate, but the points in this particular article are not relevant.

  • araf
    arafMay 19, 2025

    @semyon_levin_9929dfb719e8 ,Thanks for your perspective , it's great to see a thoughtful defense of Lombok. You're absolutely right that Lombok brings powerful features like @Value, @builder, @default, and @Singular, and modern IDE plugins have come a long way in supporting it.

    However, the risks with Lombok go beyond just type safety or IDE compatibility:

    1. Hidden Code Generation: While records generate visible and standard bytecode (and are part of the Java spec), Lombok introduces "magic" that's harder to reason about, especially for new team members or those unfamiliar with its annotations.
    2. Debugging and Tooling: Yes, records also generate synthetic methods, but they're part of the language — tools, debuggers, and static analyzers fully understand them. Lombok-generated bytecode can sometimes confuse tools (e.g., when doing static analysis, coverage reports, or reflection).
    3. Maintenance Risk: Lombok relies on annotation processing and internal compiler hooks. While it's stable today, it’s not part of the Java language or JDK, which means it can break with major Java upgrades — and it has, historically. Records are forward-compatible and designed to evolve with the JDK. 4._ Build Portability_: Not all build environments or CI pipelines play nicely with Lombok out of the box. This can lead to friction when moving between tools or setting up new projects.

    That said, you're right — Lombok is pragmatic and works well in many mature codebases. The article isn’t dismissing its utility, but rather suggesting that with records and MapStruct, many of Lombok's use cases can now be handled in a more transparent and standard way — especially for immutable DTOs and mapping layers.

    • Semyon Levin
      Semyon LevinMay 19, 2025

      Using AI for writing articles and comments do not replace real experience

  • Roger Wilco
    Roger WilcoMay 19, 2025

    What about @Cleanup annotation?

  • araf
    arafMay 19, 2025

    @rwilco , Good question,@Cleanup is one of Lombok’s more specialized features, and it does simplify resource management by auto-closing AutoCloseable objects.

    If a project is moving toward standard Java features like record classes and away from Lombok to reduce magic and increase transparency, then replacing @Cleanup with try-with-resources aligns with that goal.

  • Comp AI
    Comp AIMay 19, 2025

    Thank you! Glad you found it helpful!

Add comment