Skip to main content

Java

Lombok @Builder: The Definitive Guide to Clean and Fluent Object Creation

As Java applications grow, creating and initializing objects can become a cumbersome task. We’ve all seen them: constructors with a long list of parameters, some of which are optional, leading to multiple overloaded constructors or the error-prone “telescoping constructor” anti-pattern. The traditional solution is the Builder design pattern, which provides a readable, fluent API for object creation. However, writing a Builder by hand for every DTO or entity is tedious and adds significant boilerplate code to your project. This is where Project Lombok’s @Builder annotation comes to the rescue. It automatically generates the complete, robust Builder pattern implementation for your class at compile time, leaving your source code clean, concise, and focused on its primary responsibility. In this guide, we’ll dive deep into @Builder, from basic setup to its most powerful and advanced features. 1. Why Do We Need a Builder? Let’s consider a simple Employee class. Without a builder, you might initialize it like this: // Telescoping constructors - hard to read, easy to make mistakes Employee emp1 = new Employee(1L, "Ankur", "Kumar", "DEV", "ACTIVE"); Employee emp2 = new Employee(2L, "John", "Doe", "QA"); // What is the default status?

Building Your First Spring RESTful API: A “Hello World” Guide

Let's dive into the exciting world of Spring Boot and RESTful APIs. If you’re looking to build robust, scalable web services, Spring Boot is an excellent choice and understanding how to create a simple REST API is a fundamental first step. In this tutorial, we’ll walk through creating a “Hello World” RESTful service that exposes JSON data. This example will cover the basic setup of a Spring Boot project and demonstrating how to handle HTTP GET requests. Prerequisites Before we begin, make sure you have the following installed: Java Development Kit (JDK) 8 or higher: You can download it from the Oracle website. Apache Maven: For project management and dependency handling. Download from the Maven website. An Integrated Development Environment (IDE): IntelliJ IDEA, Eclipse, or VS Code with Java extensions are all great choices. Step 1: Create a Spring Boot Project The easiest way to start a Spring Boot project is by using the Spring Initializr. Go to the website and configure your project as follows: Project: Maven Project Language: Java Spring Boot: Choose the latest stable version (e.g., 2.7.x or 3.x.x) Group: com.ankurm.restapi Artifact: hello-world Name: hello-world Package name: com.ankurm.restapi.helloworld Packaging: Jar Java: 17 (or your preferred version) Dependencies: Add Spring Web Click “Generate” to download the project as a ZIP file. Extract it to your desired location.

From Raw Threads to Virtual Threads: A Developer’s Guide to Java Concurrency

If you’ve been a Java developer for any length of time, you’ve heard the words “multithreading” and “concurrency.” They can sound intimidating, conjuring images of deadlocks, race conditions, and nights spent debugging bizarre, unpredictable behavior. But the truth is, in the modern world of multi-core processors, concurrency isn’t optional—it’s essential for building responsive, high-performance applications. The good news? Java’s approach to concurrency has undergone a massive evolution, a journey from unwieldy, manual controls to elegant, high-level abstractions. It’s like going from manually shifting gears on a Model T to driving a modern car with a sophisticated automatic transmission. Let’s take a walk through this evolution. Understanding this journey doesn’t just teach you history; it gives you a mental model for choosing the right tool for the job today. Chapter 1: The Wild West — Thread and Runnable In the beginning, there was Thread. This is the bedrock of Java concurrency. It’s a direct, one-to-one mapping to an operating system (OS) thread. You want something to run in the background? You create a Thread and you tell it what to do via a Runnable.

The Visitor Pattern: A Practical Guide to Adding New Operations

As software engineers, we often face a dilemma: we have a stable set of classes, but we constantly need to add new functionality that operates on them. Do we keep modifying these existing, stable classes? That can be risky and violates the Open/Closed Principle. Or is there a cleaner way? Enter the Visitor Design Pattern. It’s a behavioral pattern that lets you add new operations to a set of objects without changing the classes of those objects. It’s like hiring a specialist to work on your existing equipment, rather than trying to rebuild the equipment every time you need a new task done. In this guide, we’ll break down the Visitor pattern, understand the problem it solves, and walk through a practical Java example. The Core Problem: Scattered Logic Imagine you’re building an e-commerce platform. You have a shopping cart that can hold different types of items. Let’s keep it simple and say you have Book and Electronics items.

Solved: java.lang.NoClassDefFoundError: org/hibernate/cache/CacheProvider

Encountering a java.lang.NoClassDefFoundError can be one of the most frustrating issues when working with Java applications. This particular error — org/hibernate/cache/CacheProvider — is a common stumbling block for developers upgrading or mixing Hibernate versions. Let's break down what it means and how to fix it. Understanding the Error The NoClassDefFoundError occurs when the JVM tries to load a class by its fully qualified name but cannot find its definition at runtime — even though the class existed at compile time. In this case, org.hibernate.cache.CacheProvider was the standard interface for Hibernate second-level cache integration in Hibernate 3.x. It was deprecated in Hibernate 4 and completely removed in Hibernate 5+, replaced by org.hibernate.cache.spi.RegionFactory.

Setting the Classpath from the Command Line in Java

When you compile or run a Java program that depends on classes from other JAR files or locations, the Java runtime needs to know where to find those classes. The classpath is the list of paths that Java checks for classes and resources. In this guide we’ll explore how to set the classpath in a few different ways—via the java and javac commands, through the CLASSPATH environment variable and by using the -cp / -classpath switch. What Is the Classpath? The classpath is a logical list of directories, JAR archives, and other resources that the Java Virtual Machine (JVM) searches for class files. When the JVM loads a class, it looks through the entries in this list in order until it finds the class. If the class isn’t found, a ClassNotFoundException (compile time) or NoClassDefFoundError (runtime) is thrown. Example of a classpath for a simple project might look like this: /home/user/project/bin:/home/user/lib/commons-io-2.8.0.jar

Handling Exceptions in JAX-RS Jersey with ExceptionMapper

When building RESTful web services, proper exception handling is crucial. Unhandled exceptions can lead to ugly stack traces being sent to the client, exposing internal server details and providing a poor user experience. The JAX-RS specification provides an elegant solution for this: the ExceptionMapper. In this tutorial, we’ll explore how to use Jersey’s implementation of ExceptionMapper to create centralized, custom, and consistent error responses for our API. We’ll build a simple Spring Boot application with Jersey to demonstrate the concepts. What is an ExceptionMapper? An ExceptionMapper is a JAX-RS component that “maps” a Java exception to a javax.ws.rs.core.Response object. When an exception is thrown from a JAX-RS resource method, the framework checks if there’s a registered ExceptionMapper for that specific exception type (or any of its superclasses). If a mapper is found, its toResponse() method is called. This gives you complete control over the HTTP response sent back to the client, including: The HTTP Status Code (e.g., 404 Not Found, 400 Bad Request, 500 Internal Server Error) The Response Body (e.g., a structured JSON error object) Custom HTTP Headers

Deep Dive into Java’s PriorityBlockingQueue

Let's explore a powerful and often-underutilized concurrent collection in Java: the PriorityBlockingQueue. If you’re building multi-threaded applications where task prioritization and producer-consumer patterns are crucial, understanding this class is a game-changer. The PriorityBlockingQueue is part of Java’s java.util.concurrent package. As its name suggests, it combines the features of a PriorityQueue and a BlockingQueue. Let’s break down what that means. What is PriorityBlockingQueue? At its core, PriorityBlockingQueue is an unbounded blocking queue (meaning it doesn’t have a fixed capacity, though memory limits apply) that orders its elements according to their natural ordering, or by a Comparator provided at queue construction time. Elements with higher priority (as defined by their comparison) are retrieved first.

Java 8 Default Methods: Evolving Interfaces Without Breaking Code

Before Java 8, interfaces were a rigid contract. If you had an interface implemented by dozens of classes across multiple projects, adding a new method to that interface was a developer’s nightmare. Why? Because every single implementing class would instantly break, requiring you to manually add an implementation for the new method. This made evolving APIs incredibly difficult and risky. Enter Java 8 default methods. This powerful feature changed the game by allowing us to add new, fully-implemented methods directly to interfaces without breaking existing code. Let’s dive into how they work, why they’re essential, and how to handle the complexities they introduce. What Are Default Methods? The “Why” and “How” A default method is a method in an interface that has a body. It is declared using the default keyword. If a class implements the interface but does not override the default method, it automatically inherits the default implementation. Think about the java.util.Collection interface. Imagine the chaos if adding the stream() or forEach() method in Java 8 had broken every single List and Set implementation in the world! Default methods were the elegant solution that allowed the Java API to evolve.

Integrating Gson with JAX-RS (Jersey) for Seamless JSON Handling

JSON has become the de-facto standard for data exchange in web services, and for Java developers, Gson is a highly popular library for converting Java objects to JSON and vice-versa. When building RESTful APIs with JAX-RS (specifically Jersey), integrating Gson can significantly streamline your development process. This post will guide you through setting up a Jersey project to leverage Gson for automatic JSON serialization and deserialization. Why Gson with JAX-RS? While JAX-RS implementations like Jersey often come with their own default JSON providers (like Jackson), Gson offers a lightweight and often more intuitive API for many developers. Its simple approach to serialization and deserialization, along with features like custom type adapters and versioning, makes it a compelling choice for many projects.