Skip to main content

Java

Understanding JUnit 5 @AfterEach Annotation with Practical Examples

In the world of Java development, writing a test is only half the battle. The real challenge lies in ensuring those tests are isolated, repeatable, and clean. If your first test leaves a database connection open, a locked file in the filesystem, or a messy entry in a shared cache, your second test might fail—not because of a bug in your production code, but because of a "dirty" environment. These "flaky tests" are the bane of modern CI/CD pipelines, leading to wasted developer time and decreased confidence in the build. This is where the JUnit 5 @AfterEach annotation becomes your best friend. In this comprehensive guide, we will dive deep into how to use this lifecycle callback to manage resource cleanup, maintain test integrity, and ensure that every test runs in a pristine environment. What is @AfterEach? The @AfterEach annotation marks a method that should be executed after every individual @Test method in the current class. Think of it as the "janitor" of your testing suite; no matter if your test passes, fails, or throws an unexpected exception, the @AfterEach method steps in to sweep the floor and reset the stage for the next performer. Unlike its counterpart @AfterAll (which runs once after the entire class is finished), @AfterEach is granular. It ensures that the state is reset immediately after each logic check, preventing "leakage" where the side effects of Test A interfere with the assertions of Test B.

Compact Strings in Java 9: How They Save Memory and Boost Performance

Starting with Java 9, the JVM quietly adopted a new internal representation for the java.lang.String class. The feature is called Compact Strings and, unless you went looking, you probably never noticed the change—yet it can shrink your application’s heap by 10-30% and speed up operations on text-heavy workloads. This post explains what compact strings are, how this subtle change delivers massive performance wins, and how you can measure the benefit on your own code. Get ready to reclaim your RAM! The Memory Drain Java 9 Tried to Solve Prior to JDK 9, every character inside a String was stored as a 16-bit char, using the UTF-16 encoding. The problem? For common languages like English, or text data formats like XML, JSON, log messages, and HTTP headers, most characters fall within the Latin-1 (ISO-8859-1) set, which perfectly fits into a single 8-bit byte. This meant that for a vast majority of applications, half of every character array was filled with redundant zeroes. That silent waste translated directly to: Larger Heap Footprint: Your application demands more RAM. More GC Pressure: The Garbage Collector has to work harder and longer. Lower CPU-Cache Locality: Data is scattered, slowing down processing. While developers could manually pack bytes, it came at the cost of code clarity and API compatibility. Clearly, a JVM-level fix was needed to make string handling efficient by default.

Java Stream API: How to Get the Last Element

Java Streams provide elegant ways to process collections, but retrieving the last element isn't as straightforward as calling a getLast() method. Since streams are designed for sequential processing without inherent indexing, developers need specific techniques to fetch the final element efficiently. This guide explores practical approaches to solve this common programming challenge. Whether you're processing large datasets or building concise functional pipelines, understanding these methods will help you write cleaner, more maintainable code. The Core Challenge Unlike List or Deque collections, Java Streams don't maintain bidirectional iteration or direct index access. Once elements pass through the pipeline, they're consumed. This design makes operations like stream().last() impossible without workarounds. However, several clever techniques leverage stream reduction and size information to achieve the desired result. Approach 1: Using reduce() Method The reduce() operation processes each element while retaining only the last one seen. This approach works beautifully for both sequential and parallel streams. import java.util.Optional; import java.util.stream.Stream; public class LastElementWithReduce { public static void main(String[] args) { Stream fruitStream = Stream.of("apple", "banana", "cherry", "date"); Optional lastElement = fruitStream.reduce((first, second) -> second); lastElement.ifPresent(element -> System.out.println("Last fruit: " + element) ); } }

Get Year, Month, Day from Date in Java

Extracting individual date components like year, month, and day is a common requirement in Java applications. Whether you're working with legacy Date objects or modern date-time APIs, this guide will show you multiple approaches to accomplish this task efficiently. 1. Using Calendar Class (Legacy Approach) Before Java 8, the Calendar class was the standard way to extract date fields from a Date object. While it's still supported, this approach is considered outdated and less intuitive than modern alternatives. import java.util.Calendar; import java.util.Date; public class DateExtractor { public static void main(String[] args) { Date currentDate = new Date(); Calendar calendar = Calendar.getInstance(); calendar.setTime(currentDate); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) + 1; // Months are 0-based int day = calendar.get(Calendar.DAY_OF_MONTH); System.out.println("Year: " + year); System.out.println("Month: " + month); System.out.println("Day: " + day); } } Note: The Calendar.MONTH field returns values from 0 (January) to 11 (December), so you need to add 1 to get the standard 1-12 month numbering.

Building Native Images of Spring Boot Applications with GraalVM: A Step-by-Step Guide

In the ever-evolving landscape of cloud-native development and serverless architectures, the demand for applications with lightning-fast startup times and minimal memory footprints is greater than ever. Java, traditionally known for its "write once, run anywhere" philosophy, has sometimes faced criticism regarding these very aspects. However, with the advent of GraalVM and Spring Boot's dedicated support, Java is now a formidable contender in this space. This post will guide you through the process of building GraalVM native images of your Spring Boot native applications (specifically Spring Boot 3.x), demonstrating how to unlock significant optimizations in startup time and memory consumption, perfect for serverless Java and general cloud native Java deployments. Why Native Images? The GraalVM Advantage Traditional Java applications run on the Java Virtual Machine (JVM). While the JVM offers incredible runtime optimizations through its Just-In-Time (JIT) compiler, there's an inherent overhead: the JVM itself needs to start, classes need to be loaded, and code needs to be JIT-compiled at runtime. GraalVM Native Image technology compiles your Java application ahead-of-time (AOT) into a standalone executable. This executable includes the application code, required libraries, and a minimal runtime environment (the Substrate VM) – all compiled into a single binary. The benefits are substantial: Blazing Fast Startup: Native images typically start in milliseconds, making them ideal for serverless functions, microservices, and environments where rapid scaling is crucial. Reduced Memory Footprint: By eliminating the JVM overhead and only including the necessary code paths, native images use significantly less memory. Smaller Deployment Size: The resulting binary is often much smaller than a traditional JAR file bundled with a JRE. Lower Resource Consumption: Less CPU and memory usage translates to lower operational costs in cloud environments. Spring Boot 3.x has embraced GraalVM native image compilation with first-class support, making the process more seamless than ever.

Solved: Bean property ‘configurationClass’ is not writable or has an invalid setter method

Every developer has those moments where a seemingly simple task turns into a head-scratching puzzle. This error, encountered while trying to configure a custom LocalSessionFactoryBean in Spring Boot, is a perfect example of a subtle type mismatch causing a cryptic failure. The Scenario and the Error The goal was to set up a custom SessionFactory bean using Spring's LocalSessionFactoryBean. The initial, problematic configuration was: @Configuration public class HibernateConfig { @Bean public LocalSessionFactoryBean sessionFactory() { LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); // … set data source, hibernate properties … // This line caused the error! sessionFactory.setConfigurationClass(org.hibernate.cfg.Configuration.class); return sessionFactory; } } This configuration resulted in the following exception upon application startup: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Bean property 'configurationClass' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

Demystifying Thread Safety in Java: A Practical Guide

Imagine you’re collaborating on a Google Doc. You write a sentence, and at the exact same moment, your colleague deletes the paragraph it’s in. The result? Chaos. A corrupted document, lost work, and confusion. This is precisely what can happen inside your Java application when multiple threads—independent paths of execution—try to access and modify the same data simultaneously. Welcome to the world of concurrency and the critical concept of thread safety. An object or a piece of code is considered “thread-safe” if it continues to function correctly, without causing data corruption or unexpected behavior, even when accessed by multiple threads at the same time. Getting this right is the difference between a robust, predictable application and one that suffers from mysterious, hard-to-reproduce bugs. The Villain of Our Story: The Race Condition The most common concurrency problem is the race condition. It occurs when multiple threads “race” to access and change a shared resource, and the final outcome depends on the unpredictable order in which they execute.

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.

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.

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.