Skip to main content

Leveraging Virtual Threads in Spring Boot 3.4+: Building High-Throughput Services

I've been shipping Java services for over a decade. I've tuned Tomcat thread pools, profiled connection leaks, and once reluctantly rewrote a critical service in WebFlux because blocking threads were killing us at scale. So when Java 21 landed with virtual threads baked in, I didn't just read the JEP — I immediately threw it at a production-like load test. The results were not subtle. This post is what I wish existed back then: an honest, methodical walkthrough of enabling virtual threads in Spring Boot 3.4, with real benchmark methodology, the gotchas that will actually bite you in production, and a clear-eyed take on when virtual threads won't help at all.

Spring Boot RestTemplate with Basic Auth: A Modern Guide

Communicating between microservices is a fundamental aspect of modern application development. Often, these services need to be secured. One of the simplest and most widely supported methods for securing REST APIs is Basic Authentication. In this guide, we’ll walk through how to configure and use Spring Boot’s RestTemplate to consume a REST API protected with Basic Auth. We’ll cover the modern, recommended approach using Spring Security’s component-based configuration, updating older patterns you might find in other tutorials. Project Setup First, ensure your Spring Boot project includes the spring-boot-starter-web dependency. This starter conveniently bundles everything we need, including Spring MVC for creating the REST service, Tomcat as the embedded server, and RestTemplate support. <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> You’ll also need the spring-boot-starter-security dependency to enable security features. <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>

8086 Assembly Program for Bitwise Operations: AND, OR, XOR, and NOT

This blog post will walk you through a simple 8086 assembly program designed to perform bitwise operations: AND, OR, XOR and NOT on 8-bit numbers. While these operations have a straightforward purpose, they are foundational when working at low level, manipulating bits, flags and registers. Let’s get started! data segment a db 0Ah ; first 8-bit operand (10 decimal) b db 05h ; second 8-bit operand (5 decimal) res_and db ? ; result of a AND b res_or db ? ; result of a OR b res_xor db ? ; result of a XOR b res_not db ? ; result of NOT a data ends code segment assume cs:code, ds:data start: mov ax, data mov ds, ax ; load operands into registers mov al, a mov bl, b ; AND operation: AL = AL AND BL and al, bl mov res_and, al ; reload operands for next operation mov al, a mov bl, b ; OR operation: AL = AL OR BL or al, bl mov res_or, al ; reload operands for next operation mov al, a mov bl, b ; XOR operation: AL = AL XOR BL xor al, bl mov res_xor, al ; NOT operation on first operand: AL = NOT AL mov al, a not al mov res_not, al int 3 ; breakpoint / stop for debug code ends end start

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?

Mastering the Core of TypeScript: A Practical Guide to Types

If you’ve spent any time with JavaScript, you’ve likely encountered the infamous undefined is not a function error. It’s a rite of passage. These runtime errors happen because JavaScript is dynamically typed, meaning it only figures out the “type” of a variable (like a string, number, or object) when the code is actually running. TypeScript changes the game by adding a layer of static types on top of JavaScript. Think of it as a super-smart linter that understands the shape of your data. By defining types *before* you run your code, you can catch a huge class of bugs right in your editor. This is the core promise of TypeScript, and it all starts with understanding its type system. Let’s dive into the essential TypeScript types you’ll use every day, moving from the simple to the more complex. The Basics: Type Annotation Syntax First, how do you even tell TypeScript about a type? You use a colon : after a variable or function parameter name, followed by the type. let framework: string = "React"; let version: number = 18; let isAwesome: boolean = true; // This will now cause an error in your editor! // version = "eighteen"; // Error: Type 'string' is not assignable to type 'number'.

Why You Should Never Use == to Compare Floats and Doubles in Java

Picture this: you’ve written a piece of Java code that performs some calculations. The logic seems flawless. You have an if statement that checks if two double or float values are equal. But for some reason, the check keeps failing, even when you’re sure the numbers should be identical. What’s going on? Welcome to one of the most common pitfalls in programming: comparing floating-point numbers. If you’ve ever written code like if (myDouble == 0.3), you might be in for a surprise. Let’s dive into why this is a bad idea and how to do it correctly. The Hidden Problem with Floating-Point Numbers The root of the issue lies in how computers store fractional numbers. Both float and double types in Java use a binary representation format (specifically, the IEEE 754 standard). The problem is that just like the fraction 1/3 cannot be perfectly represented as a finite decimal (it’s 0.33333…), many decimal fractions cannot be perfectly represented in binary. For example, the number 0.1 in decimal is an infinitely repeating fraction in binary. Because the computer has to truncate this at some point, the value it stores is not exactly 0.1, but a very, very close approximation. When you perform arithmetic with these approximations, the tiny precision errors can add up, leading to unexpected results.

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.

A Practical Guide to TypeScript Logical Operators

In programming, we constantly need to make decisions. Should this code run? Is this user allowed to see that page? To make these decisions, we evaluate conditions, and the fundamental tools for this are logical operators. They are the building blocks of control flow in any language, including TypeScript. Logical operators work with boolean values (true and false) to produce a single boolean result. Let’s dive into the three core logical operators you’ll use every day: Logical AND (&&), Logical OR (||), and Logical NOT (!). 1. Logical AND (&&) The Logical AND operator, represented by &&, returns true only if both of its operands are true. If either operand is false, the result will be false. Think of it like this: “I will go to the park if it is sunny and I have finished my work.” Both conditions must be met. Truth Table for AND (&&) Operand AOperand BA && Btruetruetruetruefalsefalsefalsetruefalsefalsefalsefalse

8086 Assembly Program to Compute the Greatest Common Divisor (GCD) of Two 16-bit Numbers Using Euclidean Algorithm

In this blog post, we’ll explore an 8086 assembly program that computes the Greatest Common Divisor (GCD) of two numbers using the classic Euclidean Algorithm. The Euclidean method is an efficient and elegant way to find the largest number that divides both inputs without leaving a remainder. The principle is simple:GCD(A, B) = GCD(B, A mod B) This process repeats until the remainder becomes zero. At that point, the divisor is the GCD. Let’s dive into the code and understand how it works! Program Code data segment a dw 0012h ; First number (18 decimal) b dw 000Ah ; Second number (10 decimal) gcd_result dw ? ; Variable to store the GCD data ends code segment assume cs:code, ds:data start: mov ax, data mov ds, ax ; Initialize data segment mov ax, a ; Load A into AX mov bx, b ; Load B into BX cmp bx, 0000h ; Check if B is zero jz store_result gcd_loop: mov dx, 0000h ; Clear DX before division div bx ; AX = AX / BX, remainder in DX cmp dx, 0000h ; If remainder = 0, GCD found je store_result_bx mov ax, bx ; A = B mov bx, dx ; B = remainder jmp gcd_loop ; Repeat loop store_result_bx: mov ax, bx ; Move GCD into AX store_result: mov gcd_result, ax ; Store final result int 3 ; Stop execution code ends end start

Understanding LinkedHashMap in Java

Let's dive into a fascinating corner of Java’s Collections Framework: the LinkedHashMap. You might already be familiar with HashMap for its speedy key-value pair storage and LinkedHashSet for maintaining insertion order in a set. Well, LinkedHashMap is the best of both worlds, offering the familiar map interface with the added benefit of predictable iteration order. Let’s break down what makes LinkedHashMap so special and when you should consider using it. What is LinkedHashMap? In simple terms, LinkedHashMap is a hash table and a linked list implementation of the Map interface. It inherits all the goodness from HashMap (fast lookups, insertions, and deletions) but adds an internal doubly-linked list that runs through all of its entries. This linked list defines the iteration order, which can either be: Insertion Order: The default behavior, where elements are iterated in the order they were first inserted into the map. Access Order: Elements are iterated in the order they were last accessed (read or written). This is particularly useful for implementing LRU (Least Recently Used) caches. Like HashMap, LinkedHashMap allows one null key and multiple null values. Interface Hierarchy LinkedHashMap implements the following interfaces and extends the following class: java.io.Serializable java.util.Map java.lang.Cloneable And it extends java.util.HashMap.