Skip to main content

Java

JUnit 6 Architecture Deep Dive: Platform, Engines, and Launchers

A deep dive into JUnit 6's three-pillar architecture: Platform, Jupiter, and Vintage. Learn how the TestEngine SPI, Launcher, and LauncherDiscoveryRequest work together, with code examples showing programmatic test execution and custom engine concepts.

JUnit 6 vs JUnit 5: Key Differences, Features, and Migration Guide

A detailed, side-by-side comparison of JUnit 6 and JUnit 5 — architecture, annotations, parameterized tests, extension model, and records support — plus a practical migration guide updated for Spring Boot 4.0, which makes JUnit 6 the default testing baseline.

JUnit 6 Project Structure and Best Practices

Learn how to structure your JUnit 6 test projects for scalability and long-term maintainability. Covers package layout, naming conventions, test base classes, test helpers, and real-world best practices used in production Java projects.

JUnit 6 with Maven and Gradle: Complete Setup Guide

A comprehensive guide to configuring JUnit 6 with Maven and Gradle. Covers Surefire plugin, Failsafe plugin, multi-module projects, test filtering, IDE integration, and common configuration mistakes to avoid.

Hibernate 7 get() vs getReference(): Four Calls, Four Outcomes

session.get() and session.getReference() look interchangeable at a glance, but the difference isn't "eager vs lazy" -- it's what you're telling Hibernate you need. This piece runs four calls against Hibernate 7.4.1.Final, builds the full same-session matrix, and pins down exactly where the proxy identity contract breaks -- including one same-session result that the usual L1-cache explanation gets wrong.

Hibernate 7 merge() vs refresh(): Which One Fails Loudly?

merge() and refresh() get described as opposite directions of the same tool -- one pushes, one pulls. Run them against a real @Version-ed entity and that framing misses the actual question: which one fails loudly when the state it's holding is stale? Three named experiments against Hibernate 7.4.1.Final, including a result that overturned the article's own original assumption.

Hibernate 7 Batch Inserts: How to Prove Batching Is Working

Setting hibernate.jdbc.batch_size is not the same as verifying batching happens. Two nearly identical entities, one GenerationType difference, and Hibernate's own statistics show a 30-vs-4 prepared-statement gap -- then two sweeps (allocationSize, batch_size) run the numbers instead of predicting them, including one off-by-one that reproduced across two separate full-suite runs.

Mastering Hibernate Validator 7: Seamless CDI Bootstrapping for Enterprise Java

Are you tired of manually instantiating validators or dealing with NullPointerException when your custom constraint validators try to @Inject a service? In the world of modern Jakarta EE and MicroProfile applications, manual plumbing is a relic of the past. If you are moving to Hibernate Validator 7, understanding CDI bootstrapping is the key to building decoupled, testable, and robust validation layers. The Problem: The Manual Validation Headache Validation logic often needs access to external resources — database repositories, configuration services, or security contexts. When you use the standard Validation.buildDefaultValidatorFactory(), you are operating outside the CDI (Contexts and Dependency Injection) container. Your @Inject annotations within custom ConstraintValidator implementations simply won't work. They return null, forcing you into anti-patterns like static lookups or manual dependency passing that make your code brittle and nearly impossible to unit test. Imagine writing a @UniqueUsername constraint. You need your UserRepository to check the database. Without proper CDI bootstrapping, Hibernate Validator instantiates your validator class using simple reflection — bypassing the container's dependency graph entirely. You end up with a validation layer that is "deaf" to your application's ecosystem.

Mastering Hibernate 7 Aggregate Functions: The Ultimate Guide for High-Performance Data Retrieval

Are you tired of pulling massive lists of entities into your Java application just to calculate a simple total or average? Data bottlenecks are the silent killers of enterprise applications. When you fetch thousands of rows only to perform math in memory, you aren't just wasting CPU cycles — you're suffocating your database and increasing latency. In modern development with Hibernate 7, leveraging aggregate functions is the solution that transforms sluggish data processing into lightning-fast database-level operations. By using COUNT, SUM, AVG, MIN, and MAX, you delegate the heavy lifting to the database engine, ensuring your application remains lean and responsive.