{"id":3614,"date":"2025-12-23T10:00:16","date_gmt":"2025-12-23T15:00:16","guid":{"rendered":"https:\/\/www.mymiller.name\/wordpress\/?p=3614"},"modified":"2025-12-23T10:00:16","modified_gmt":"2025-12-23T15:00:16","slug":"lombok-annotations-that-do-the-heavy-lifting","status":"publish","type":"post","link":"https:\/\/www.mymiller.name\/wordpress\/java\/lombok-annotations-that-do-the-heavy-lifting\/","title":{"rendered":"Lombok: Annotations That Do the Heavy Lifting"},"content":{"rendered":"\n<div class=\"wp-block-jetpack-markdown\"><p>If you\u2019re a Java developer who\u2019s tired of writing repetitive boilerplate code, Lombok is your new best friend. This clever library uses annotations to automatically generate common code elements, making your classes cleaner, more concise, and less error-prone.<\/p>\n<h3>Why Lombok? The Benefits<\/h3>\n<ul>\n<li><strong>Reduced Boilerplate:<\/strong> Lombok takes care of getters, setters, constructors, <code>toString()<\/code>, <code>equals()<\/code>, <code>hashCode()<\/code>, and more.<\/li>\n<li><strong>Improved Readability:<\/strong> Your classes become leaner and easier to understand.<\/li>\n<li><strong>Less Error-Prone:<\/strong>  Let Lombok handle the mundane details, reducing the chance of manual mistakes.<\/li>\n<li><strong>Faster Development:<\/strong>  Spend less time typing and more time on the core logic of your applications.<\/li>\n<\/ul>\n<h3>Getting Started: Installation<\/h3>\n<p>To use Lombok, you\u2019ll need to add it as a dependency to your project (using Maven, Gradle, or similar) and then enable it in your IDE. Consult the Lombok documentation for detailed instructions based on your setup.<\/p>\n<h3>Core Lombok Annotations: A Deep Dive<\/h3>\n<p>Let\u2019s explore some of the most powerful Lombok annotations:<\/p>\n<ul>\n<li>\n<p><strong>@Data:<\/strong> The all-in-one powerhouse. This annotation combines <code>@Getter<\/code>, <code>@Setter<\/code>, <code>@ToString<\/code>, <code>@EqualsAndHashCode<\/code>, and <code>@RequiredArgsConstructor<\/code>. Perfect for plain old Java objects (POJOs).<\/p>\n<pre><code class=\"language-java\">@Data\npublic class Person {\n    private String name;\n    private int age;\n}\n<\/code><\/pre>\n<\/li>\n<li>\n<p><strong>@Getter \/ @Setter:<\/strong> Generate getters and setters for your fields, respectively.<\/p>\n<pre><code class=\"language-java\">@Getter @Setter\nprivate String address;\n<\/code><\/pre>\n<\/li>\n<li>\n<p><strong>@NoArgsConstructor \/ @AllArgsConstructor:<\/strong> Create constructors with no arguments or with arguments for all fields, respectively.<\/p>\n<pre><code class=\"language-java\">@NoArgsConstructor\npublic class Book { ... }\n\n@AllArgsConstructor\npublic class Movie { ... }\n<\/code><\/pre>\n<\/li>\n<li>\n<p><strong>@ToString:<\/strong> Automatically generates a meaningful <code>toString()<\/code> implementation.<\/p>\n<\/li>\n<li>\n<p><strong>@EqualsAndHashCode:<\/strong> Simplifies the creation of <code>equals()<\/code> and <code>hashCode()<\/code> methods.<\/p>\n<\/li>\n<li>\n<p><strong>@Builder:<\/strong> Provides a fluent builder pattern for creating complex objects.<\/p>\n<\/li>\n<li>\n<p><strong>@Slf4j:<\/strong> Injects a logger (<code>log<\/code>) field into your class.<\/p>\n<pre><code class=\"language-java\">@Slf4j\npublic class MyClass {\n    public void myMethod() {\n        log.info(&quot;Something happened!&quot;);\n    }\n}\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<h3>Advanced Annotations:<\/h3>\n<p>Lombok doesn\u2019t stop at the basics. It offers a suite of advanced annotations that can streamline specific scenarios and further enhance your code:<\/p>\n<ul>\n<li>\n<p><strong>@SneakyThrows:<\/strong> Elevate your exception handling. This annotation allows you to throw checked exceptions from your methods without explicitly declaring them in a <code>throws<\/code> clause. Under the hood, Lombok wraps your code in a <code>try-catch<\/code> block, catching any checked exceptions and re-throwing them as unchecked exceptions.<\/p>\n<pre><code class=\"language-java\">@SneakyThrows\npublic void processFile(String filename) {\n    \/\/ ... Code that might throw a checked exception (e.g., IOException)\n}\n<\/code><\/pre>\n<\/li>\n<li>\n<p><strong>@Synchronized:<\/strong>  Simplify thread safety. Instead of manually writing <code>synchronized<\/code> blocks, simply annotate a method with <code>@Synchronized<\/code>. Lombok will generate the equivalent synchronized code to ensure thread-safe access.<\/p>\n<pre><code class=\"language-java\">@Synchronized\npublic void updateCounter() {\n    \/\/ ... Thread-safe code \n}\n<\/code><\/pre>\n<\/li>\n<li>\n<p><strong>@Value:<\/strong> Embrace immutability. Annotating a class with <code>@Value<\/code> makes it immutable. All fields become <code>final<\/code>, and Lombok generates a constructor, getters, <code>equals()<\/code>, <code>hashCode()<\/code>, and <code>toString()<\/code> methods.<\/p>\n<pre><code class=\"language-java\">@Value\npublic class Point {\n    int x;\n    int y;\n}\n<\/code><\/pre>\n<\/li>\n<li>\n<p><strong>@With:<\/strong>  Create modified copies.  If you have immutable objects and want to create new instances with slight modifications, <code>@With<\/code> is your friend. It generates \u201cwither\u201d methods that return new objects with the specified field changes.<\/p>\n<pre><code class=\"language-java\">@Value\npublic class Person {\n    String name;\n    int age;\n\n    @With\n    public Person withAge(int newAge) {\n        return new Person(this.name, newAge);\n    }\n}\n\n\/\/ Usage:\nPerson john = new Person(&quot;John&quot;, 30);\nPerson olderJohn = john.withAge(31); \n<\/code><\/pre>\n<\/li>\n<li>\n<p><strong>@NonNull:<\/strong>  Enforce null checks. Add this annotation to fields or method parameters to indicate that null values are not allowed. Lombok generates null checks at compile time.<\/p>\n<pre><code class=\"language-java\">public void greet(@NonNull String name) {\n    \/\/ No need to manually check if name is null\n    System.out.println(&quot;Hello, &quot; + name);\n}\n<\/code><\/pre>\n<p>If you try to pass <code>null<\/code> to <code>greet()<\/code>, you\u2019ll get a <code>NullPointerException<\/code> at runtime.<\/p>\n<\/li>\n<li>\n<p><strong>@Builder:<\/strong> Streamline object creation. This annotation allows you to build complex objects step-by-step using a fluent builder pattern.<\/p>\n<pre><code class=\"language-java\">@Builder\npublic class Pizza {\n    private String size;\n    private String crust;\n    private List&lt;String&gt; toppings;\n}\n\n\/\/ Usage\nPizza pizza = Pizza.builder()\n                 .size(&quot;Large&quot;)\n                 .crust(&quot;Thin&quot;)\n                 .topping(&quot;Pepperoni&quot;)\n                 .topping(&quot;Mushrooms&quot;)\n                 .build();\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<h3>A Word of Caution<\/h3>\n<p>While Lombok is incredibly useful, be mindful of these considerations:<\/p>\n<ul>\n<li><strong>Tooling:<\/strong> Ensure your IDE and build tools are properly configured to work with Lombok.<\/li>\n<li><strong>Debugging:<\/strong> Generated code might make debugging slightly more challenging, but most IDEs handle it well.<\/li>\n<li><strong>Overuse:<\/strong> Avoid using Lombok for every single class. Sometimes, manually written code is more appropriate.<\/li>\n<\/ul>\n<h3>Example: Before and After Lombok<\/h3>\n<pre><code class=\"language-java\">\/\/ Before Lombok\npublic class Car {\n    private String make;\n    private String model;\n    private int year;\n\n    \/\/ Constructor, getters, setters, toString(), equals(), hashCode()...\n}\n<\/code><\/pre>\n<pre><code class=\"language-java\">\/\/ With Lombok\n@Data\npublic class Car {\n    private String make;\n    private String model;\n    private int year;\n}\n<\/code><\/pre>\n<p>Lombok is a game-changer for Java development. By automating repetitive tasks, it allows you to focus on the essence of your code, boosting productivity and maintainability.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":3486,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[280],"tags":[69],"series":[],"class_list":["post-3614","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java","tag-java-2"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/04\/ai-generated-8314612_640.jpg?fit=640%2C480&ssl=1","jetpack-related-posts":[{"id":3795,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_ai\/evrete-a-modern-java-rule-engine\/","url_meta":{"origin":3614,"position":0},"title":"EVRete: A Modern Java Rule Engine","author":"Jeffery Miller","date":"November 24, 2025","format":false,"excerpt":"EVRete is a high-performance, lightweight, and open-source rule engine designed for Java applications. It offers a flexible and expressive way to implement rule-based logic, making it a compelling alternative to traditional rule engines like Drools. This article delves into EVRete\u2019s features, focusing on its annotation-based approach to rule definition. Why\u2026","rel":"","context":"In &quot;Spring AI&quot;","block_context":{"text":"Spring AI","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_ai\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/compliance-5899194_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/compliance-5899194_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/compliance-5899194_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/compliance-5899194_1280-jpg.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/compliance-5899194_1280-jpg.avif 3x"},"classes":[]},{"id":3539,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_databases\/spring-data-cassandra-simplifying-java-development-with-apache-cassandra\/","url_meta":{"origin":3614,"position":1},"title":"Spring Data Cassandra: Simplifying Java Development with Apache Cassandra","author":"Jeffery Miller","date":"September 22, 2025","format":false,"excerpt":"Apache Cassandra is a powerful NoSQL database known for its scalability and high availability. Spring Data Cassandra seamlessly integrates Spring\u2019s familiar programming model with Cassandra, boosting developer productivity. Why Spring Data Cassandra? Simplified Configuration: Spring Boot auto-configuration minimizes manual setup. Object-Relational Mapping (ORM): Easily map Java objects to Cassandra tables.\u2026","rel":"","context":"In &quot;Spring Databases&quot;","block_context":{"text":"Spring Databases","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_databases\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/network-3396348_1280.jpg?fit=1200%2C720&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/network-3396348_1280.jpg?fit=1200%2C720&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/network-3396348_1280.jpg?fit=1200%2C720&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/network-3396348_1280.jpg?fit=1200%2C720&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/network-3396348_1280.jpg?fit=1200%2C720&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":3471,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_databases\/spring-jpa-auditing\/","url_meta":{"origin":3614,"position":2},"title":"Spring JPA Auditing","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Simplifying Entity Auditing with Spring Data JPA Annotations Keeping track of who created and modified your entities is crucial for various purposes, including audit trails, security, and data lineage. Spring Data JPA offers a convenient and efficient way to achieve this through dedicated annotations: @CreatedBy, @LastModifiedBy, @CreatedDate, and @LastModifiedDate. Leveraging\u2026","rel":"","context":"In &quot;Spring Databases&quot;","block_context":{"text":"Spring Databases","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_databases\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/02\/audit-4190944_640.jpg?fit=640%2C377&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/02\/audit-4190944_640.jpg?fit=640%2C377&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/02\/audit-4190944_640.jpg?fit=640%2C377&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3185,"url":"https:\/\/www.mymiller.name\/wordpress\/java_tips\/java-tips-part-3\/","url_meta":{"origin":3614,"position":3},"title":"Java Tips Part 3","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Continuing my Java Tips from experience that I have learned from code reviews to different programming tasks. Tip 11: Use Hibernate Statistics Now, this is only for your development profiles\/environments, not for production. Hibernate has built-in statistics on your queries. This will break down how much time is spent along\u2026","rel":"","context":"In &quot;Java Tips&quot;","block_context":{"text":"Java Tips","link":"https:\/\/www.mymiller.name\/wordpress\/category\/java_tips\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2021\/12\/sam-dan-truong-rF4kuvgHhU-unsplash-scaled-e1640791434235.jpg?fit=640%2C427&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2021\/12\/sam-dan-truong-rF4kuvgHhU-unsplash-scaled-e1640791434235.jpg?fit=640%2C427&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2021\/12\/sam-dan-truong-rF4kuvgHhU-unsplash-scaled-e1640791434235.jpg?fit=640%2C427&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3961,"url":"https:\/\/www.mymiller.name\/wordpress\/spring\/spring4\/architecting-spring-boot-4-with-official-spring-grpc-support\/","url_meta":{"origin":3614,"position":4},"title":"Architecting Spring Boot 4 with Official Spring gRPC Support","author":"Jeffery Miller","date":"January 15, 2026","format":false,"excerpt":"For years, the Spring community relied on excellent third-party starters (like net.devh) to bridge the gap between Spring Boot and gRPC. With the evolution of Spring Boot 4 and the official Spring gRPC project, we now have native support that aligns perfectly with Spring's dependency injection, observability, and configuration models.\u2026","rel":"","context":"In &quot;Spring4&quot;","block_context":{"text":"Spring4","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring\/spring4\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/01\/Gemini_Generated_Image_3yqio33yqio33yqi.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/01\/Gemini_Generated_Image_3yqio33yqio33yqi.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/01\/Gemini_Generated_Image_3yqio33yqio33yqi.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/01\/Gemini_Generated_Image_3yqio33yqio33yqi.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2026\/01\/Gemini_Generated_Image_3yqio33yqio33yqi.avif 3x"},"classes":[]},{"id":3951,"url":"https:\/\/www.mymiller.name\/wordpress\/java\/scaling-streams-mastering-virtual-threads-in-spring-boot-4-and-java-25\/","url_meta":{"origin":3614,"position":5},"title":"Scaling Streams: Mastering Virtual Threads in Spring Boot 4 and Java 25","author":"Jeffery Miller","date":"December 22, 2025","format":false,"excerpt":"As a software architect, I\u2019ve seen the industry shift from heavy platform threads to reactive streams, and finally to the \"best of both worlds\": Virtual Threads. With the recent release of Spring Boot 4.0 and Java 25 (LTS), Project Loom's innovations have officially become the bedrock of high-concurrency enterprise Java.\u2026","rel":"","context":"In &quot;JAVA&quot;","block_context":{"text":"JAVA","link":"https:\/\/www.mymiller.name\/wordpress\/category\/java\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_wqijejwqijejwqij-scaled.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_wqijejwqijejwqij-scaled.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_wqijejwqijejwqij-scaled.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_wqijejwqijejwqij-scaled.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_wqijejwqijejwqij-scaled.avif 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3614","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/comments?post=3614"}],"version-history":[{"count":1,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3614\/revisions"}],"predecessor-version":[{"id":3615,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3614\/revisions\/3615"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media\/3486"}],"wp:attachment":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media?parent=3614"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/categories?post=3614"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/tags?post=3614"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/series?post=3614"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}