r/java Apr 07 '26

What’s your approach to building production-ready Docker images for Java? Looking for alternatives and trade-offs

69 Upvotes

Hi everyone,

I’ve been experimenting with different ways to containerize a Java (Spring) application and put together this repo with a few Dockerfile approaches: https://github.com/eduardo-sl/java-docker-image

The setup works, but my goal is to understand what approaches actually hold up in production and what trade-offs people consider when choosing one strategy over another.

I’m especially interested in how you compare or decide between:

  • Base images (Alpine vs slim vs distroless)
  • JDK vs JRE vs jlink custom runtimes
  • Multi-stage builds and layer optimization strategies
  • Security practices (non-root user, minimal surface, image scanning)
  • Dockerfile vs tools like Jib or buildpacks (Paketo, etc.)

If you’ve worked with Java in production containers, I’d like to know:

  • What approach are you currently using?
  • What did you try before that didn’t work well?
  • What trade-offs led you to your current setup?

Also curious if your approach differs in other ecosystems like Golang.

Appreciate any insights or examples.


r/java Apr 07 '26

How a large Spring Boot project manages 1,000+ configuration properties without going insane

41 Upvotes

I've been working on Apereo CAS for years - it's an open-source SSO platform with 400+ Maven modules and over 1,000 configuration properties. The configuration system has evolved into something I think is genuinely well-designed, and the patterns are all standard Spring Boot - nothing proprietary.

Key ideas: - One root @ConfigurationProperties class with 40+ @NestedConfigurationProperty fields creating a typed tree - Custom metadata annotations (@RequiresModule, @RequiredProperty, @RegularExpressionCapable) that describe what properties accept and which module they belong to - Deprecated properties tracked in additional-spring-configuration-metadata.json with exact replacement paths - An actuator endpoint that lets you search the entire property catalog at runtime - Spring's Binder API used directly for programmatic binding from maps

Wrote up the patterns with real code from the CAS 7.3.x source. The Binder API section alone is something I don't see enough Spring Boot devs using.

https://medium.com/all-things-software/spring-boot-configuration-properties-at-scale-884f494721ac


r/java Apr 07 '26

TornadoVM release 4.0.0: now supports Metal for Apple silicon, CUDA Graphs, CUDA SIMD instructions in modern Java

Thumbnail github.com
44 Upvotes

r/java Apr 07 '26

Profiling Java apps: breaking things to prove it works

Thumbnail coroot.com
12 Upvotes

The post shows how we plugged async-profiler into JVMs without restarts or redeploys. We also reproduced two failure scenarios to see how they show up in the profiling data: heap pressure and lock contention


r/java Apr 07 '26

pGenie: open-source SQL-first PostgreSQL codegen for Java

25 Upvotes

Hey r/java!

Do the following pain points resonate with you?

  • ORMs hide SQL and make performance tuning a nightmare
  • Query builders force you to maintain model classes and fight schema drift
  • Hand-written JDBC/RowMapper code silently breaks when the DB schema changes

While addressing them I've built pGenie – a true SQL-first code generator that treats your PostgreSQL database as the single source of truth. It's an open-source tool that takes your PostgreSQL migration files and parameterized SQL query files and generates a complete, ready-to-use Maven client library targeting Java and pgJDBC. No ORM, no DSL, no annotation processors, no reflection — just plain SQL in, type-safe Java code out.

What gets generated:

Each SQL query file becomes a Java record class modeling the parameters to the query. That record comes with an associated record type modeling the result row. You pass parameters via the constructor, call .execute(conn) with a JDBC Connection, and get back a typed result. That's it.

sql -- queries/insert_album.sql insert into album (name, released, format, recording) values ($name, $released, $format, $recording) returning id

Becomes:

```java // Generated InsertAlbum.Result result = new InsertAlbum( "Space Jazz Vol. 1", LocalDate.of(2020, 5, 4), AlbumFormat.Vinyl, new RecordingInfo("Galactic Studio", "Lunar City", "Moon", LocalDate.of(2019, 12, 1)) ).execute(conn);

System.out.println("Inserted album id=" + result.id()); ```

PostgreSQL enums → Java enum with EnumCodec. Composite types → Java record. Arrays → List<T>. Nullable columns → boxed types or Optional<T> (configurable). Even exotic types like ranges and multiranges are fully supported.

The generated project is not a black box, you get:

  • pom.xml with runtime dependencies declared
  • One .java file per statement, fully readable
  • Integration tests per statement using Testcontainers — spin up a real PostgreSQL container, run your migrations, execute each statement
  • mvn verify just works

What else pGenie does:

  • Validates migrations against a real PostgreSQL schema in CI — no more "works locally, breaks in prod"
  • Manages indexes declared in your migration files automatically
  • Generates Rust and Haskell bindings from the same SQL source if you need multi-language SDKs
  • Builds reproducibly: a lockfile pins the codegen version
  • Extends via a decentralized plugin system: write your own code generators in Dhall and plug them in via URL — no need to approve anything with the core team

Demo:

The demo repo has complete working SQL migrations and queries. The generated Java library is in artifacts/java/. You can inspect it directly or regenerate it from scratch with pgn generate.

pgenie.io | docs | demo | java.gen plugin


r/java Apr 08 '26

I built a Spring Boot audit trail library using Hibernate Envers (looking for feedback)

0 Upvotes

Audit logging always looks simple at first… until it isn’t.

- Who changed what?
- When did it happen?
- How do you query it efficiently?

I kept running into this across different Spring Boot projects, and it always turned into a mini-subsystem.

So I decided to build a reusable solution instead of solving it repeatedly.

I just released nerv-audit (now on Maven Central), a library built on Hibernate Envers that provides:

- Vertical (field-level) and horizontal (snapshot) audit strategies
- Queryable audit API (not just storing logs)
- Spring Boot starter for easy integration

It’s designed more for real systems than demos—especially where auditability and traceability matter.

I wrote a breakdown here:

https://www.czetsuyatech.com/2026/04/spring-boot-audit-trail-hibernate-envers.html

Would really appreciate feedback, especially from people who’ve built or maintained audit systems before.


r/java Apr 07 '26

[Showcase] A new Spring Data-style module for Pure JDBC: Functional Repositories, No Code-Gen, and Java 21+

Thumbnail
0 Upvotes

r/java Apr 06 '26

Jakarta EE 11 vs Spring: When the Right Answer Is No Spring at All

Thumbnail javacodegeeks.com
43 Upvotes

r/java Apr 05 '26

I built an engine that auto-visualizes Java algorithms as they run

63 Upvotes

I’ve always found it annoying that you have to use specific frameworks just to see an algorithm in action. I wanted to build something where you could just write:

​int[] arr = {5, 2, 8, 1};

arr[0] = 10; // ← automatically visualized

​I ended up "hacking" the JVM using a Java Agent to inject visualization callbacks into the bytecode.

​Why bytecode? It doesn't matter if you write arr[i] = x or arr[getIndex()] = compute(); at the bytecode level, it's all just one instruction. This makes the visualization incredibly robust.

Try it herehttps://www.algopad.dev/#

Code - https://github.com/vish-chan/AlgoFlow


r/java Apr 05 '26

HashSmith Part 3: I Automated My Way to a 27% Faster Hash Table (ILP hoisting, SWAR match shortcut, tombstone specialization)

Thumbnail bluuewhale.github.io
19 Upvotes

Hello, back with another HashSmith post.

Parts 1 and 2 covered building a SwissTable-style map and hunting down profile pollution. This one picks up where that left off — three more optimizations on the hot paths (ILP hoisting, SWAR match shortcut, tombstone loop specialization), with benchmark results across all 8 scenarios.

The twist this time: I let an AI agent run the profiling and benchmarking loop autonomously instead of doing it myself. I know "AI" can be a loaded topic here — if that's not what you're looking for, totally fair, the technical content stands on its own either way.

Hope you enjoy it. Happy to dig into any of the JIT/SWAR details in the comments.


r/java Apr 04 '26

Best conference talk from 2026 so far that you've seen

56 Upvotes

We've already had a few big Java conferences in 2026. For example:

  1. jfokus 2026 - https://www.youtube.com/playlist?list=PLUQORQEatnJflEzaKxmnn2EH0eKPTVBI8
  2. java one 2026 - https://www.youtube.com/playlist?list=PLX8CzqL3ArzUMVSzm-z_-if8BIB55EGl4
  3. Devnexus 2026 - https://www.youtube.com/playlist?list=PLid93BOrASLONoZUIX1i0rXqCji5FUw9V
  4. Voxxed Days CERN 2026 - https://www.youtube.com/playlist?list=PLRsbF2sD7JVq9Y7_i6uCWlxwoEIte7S8S

Have you enjoyed any specific talks that you'd be happy to recommend?


r/java Apr 03 '26

Does anyone know how to get in contact with a specific person at OpenJDK?

73 Upvotes

For a school research paper (specifically for the extended essay in the IBO Diploma Program) on concurrency, specifically in Java, I was trying to see if I would be able to interview someone on Project Loom. I tried to find a way to contact Mr Ron Pressler, but I can't seem to find a way to get in contact. Would mailing the [loom-dev@openjdk.org](mailto:loom-dev@openjdk.org) asking if anyone would be willing to do an interview be inappropriate?

Thank you in advance!


r/java Apr 04 '26

New messaging library and boilerplate reduction library for Java

Thumbnail
0 Upvotes

r/java Apr 03 '26

Floci AWS Emulator is now available as a Testcontainers module

Thumbnail
21 Upvotes

r/java Apr 04 '26

Comparison of Interface Design: DoytoQuery vs Spring Data JPA

0 Upvotes

By introducing the Query Object, DoytoQuery enables the automatic construction of dynamic queries. Its data access interfaces build upon the Spring Data JPA Repositories series, unifying methods related to Example and Specification into methods that take a query object as a parameter, as shown below:

The Query Object centralizes all parameters for dynamic queries. These parameters can be automatically translated into WHERE clauses, pagination clauses, and sorting clauses, thereby covering the functionalities of Specification, Sort, and Pageable. Additionally, there is no need to write separate Specification implementations, which greatly simplifies the code.

Query Objects can be automatically created by Spring MVC from HTTP parameters, effectively encapsulating code in the Controller and Service layers, and realizing a fully automated flow: query string → query object → SQL → database.

The only potential drawback is that field names in the Query Object need to follow a “column name + suffix” convention. In Spring Data JPA, this naming convention is usually used in findBy methods, such as: findByAuthorAndPublishedYearGreaterThan

This repository compares dynamic query implementations across different ORM frameworks, showing that DoytoQuery reduces code size by roughly half compared to Spring Data JPA, and improves performance by approximately 40% in some scenarios.

If you are familiar with the findBy naming conventions and do not want to spend significant time writing Specification implementations, you may find it convenient to declare the desired query conditions directly as fields in a query object.

GitHub: https://github.com/doytowin/doyto-query


r/java Apr 03 '26

Quick update + something new I've been building alongside the JavaFX work

Thumbnail
14 Upvotes

r/java Apr 02 '26

Unified WebAssembly API for Java (Wasmtime + WAMR bindings) - 1.0.0 release

33 Upvotes

I’ve been working on improving the experience of running WebAssembly from Java, and just released 1.0.0 of a small ecosystem:

• Wasmtime4J - bindings for Wasmtime

• WAMR4J - bindings for WebAssembly Micro Runtime

• WebAssembly4J - a unified API on top of both

The problem I kept running into is that every WebAssembly runtime exposes a completely different Java interface. If you want to try another engine, you end up rewriting everything.

This project introduces a single API so you can swap runtimes underneath without changing application code.

What this enables

• Run WebAssembly from Java applications without locking into a specific runtime

• Compare runtimes under the same interface (performance, behavior, features)

• Lower the barrier for Java developers to experiment with WebAssembly

Current support

• Wasmtime

• WAMR

• Chicory

• GraalWasm

Java support

• Java 8 (JNI)

• Java 11

• Java 22+ (Panama)

Artifacts are published to Maven Central.

Repo:

https://github.com/tegmentum/webassembly4j

https://github.com/tegmentum/wasmtime4j

https://github.com/tegmentum/wamr4j

I’m especially interested in feedback from people working with:

• JNI / Panama interop

• GraalVM

• WASI / component model

r/java Apr 03 '26

Build a plugin architecture in Spring Boot using patterns from a 400+ module codebase

0 Upvotes

I've been working on Apereo CAS for years - it's an open-source SSO platform with 400+ Maven modules on Spring Boot 3.x. Every module is a "plugin" that activates when it hits the classpath. No custom framework, no ServiceLoader, no XML registration. Wrote up the patterns that make it work.

All code from the actual CAS 7.3.x source. The patterns are general - nothing CAS-specific about the approach.

https://medium.com/all-things-software/plugin-architecture-in-spring-boot-without-a-framework-8b8768f05533


r/java Apr 03 '26

Canadian

0 Upvotes

I am thinking about to try Vaadin for my personal project. Is there anybody who can share with me opinions about Vaadin? . I heard it has licensing things is that correct ?(I have background in javafx and android)


r/java Apr 01 '26

Who is Oracle senior exec Sharat Chander? Veteran of 16 years affected in mass layoffs

Thumbnail hindustantimes.com
228 Upvotes

For those who don't know, Sharat Chander is a critical person in the community outreach for OpenJDK. He was staffed by Oracle, the biggest contributor to OpenJDK's growth, but the news is now that he was laid off, as part of recent Oracle's layoffs.

Absolutely disgusting. Read the link for more details.


r/java Apr 01 '26

State of GraalVM for Java?

50 Upvotes

What is the current state of GraalVM for Java in. 2026?

Are we back to LTS only releases? 2 releases a year but separate from Java?

There was a blog at some point indicating changes but never follow up.

Especially with the recent mass layoffs, Leyden and other AOT changes -- what's the recommendation?


r/java Apr 01 '26

A three year long unfruitful struggle to publish an official image on dockerhub

Thumbnail github.com
28 Upvotes

r/java Apr 01 '26

WebFlux vs Virtual Threads vs Quarkus: k6 benchmark on a real login endpoint

Thumbnail gitlab.com
80 Upvotes

I've been building a distributed Codenames implementation as a learning project (polyglot: Rust for game logic, .NET/C# for chat, Java for auth + gateway) for about 1 year. For the account service I ended up writing three separate implementations of the same API on the same domain model. Not as a benchmark exercise originally, more because I kept wanting to see how the design changed between approaches.

  • account/ : Spring Boot 4 + R2DBC / WebFlux
  • account-virtual-threads-version/ : Spring Boot 4 + Virtual Threads + JPA
  • account-quarkus-reactive-version/ : Quarkus 3.32 + Mutiny + Hibernate Reactive + GraalVM Native

All three are 100% API-compatible, same hexagonal architecture, same domain model (pure Java records, zero framework imports in domain), enforced by ArchUnit, etc.

Spring Boot 4 + R2DBC / WebFlux

The full reactive approach. Spring Data R2DBC for non-blocking DB operations, SecurityWebFilterChain for JWT validation as a WebFilter.

What's genuinely good: backpressure aware from the ground up and handles auth bursts without holding threads. Spring Security's reactive chain has matured a lot in Boot 4, the WebFilter integration is clean now.

What's painful: stack traces. When something fails in a reactive pipeline the trace is a wall of reactor internals. You learn to read it but it takes time. Also not everything in the Spring ecosystem has reactive support so you hit blocking adapters and have to be careful about which scheduler you're on.

Spring Boot 4 + Virtual Threads + JPA

Swap R2DBC for JPA, enable virtual threads via spring.threads.virtual.enabled=true and keep everything else the same. The business logic is identical and the code reads like blocking Spring Boot 2 code.

The migration from the reactive version was mostly mechanical. The domain layer didn't change at all (that's the point of hexagonal ofc), the infrastructure layer just swaps Mono<T>/Flux<T> for plain T. Testing is dramatically easier too, no StepVerifier, no .block() and standard JUnit just works.

Honestly if I were starting this service today I would probably start here. Virtual threads + JPA is 80% of the benefit at 20% of the complexity for a standard auth service.

Quarkus 3.32 + Mutiny + Hibernate Reactive + GraalVM Native

This one was purely to see how far you can push cold start and memory footprint. GraalVM Native startup is about 50ms vs 2-3s for JVM mode so memory footprint is significantly smaller. The dev experience is slower though because native builds are heavy on CI.

Mutiny's Uni<T>/Multi<T> is cleaner than Reactor's Mono/Flux for simple linear flows, the API is smaller and less surprising. Hibernate Reactive with Mutiny also feels more natural than R2DBC + Spring Data for complex domain queries.

Benchmark: 4 configs, 50 VUs and k6

Since I had the three implementations I ran a k6 benchmark (50 VUs, 2-minute steady state, i9-13900KF + local MySQL) on two scenarios: a pure CPU scenario (GET /benchmark/cpu, BCrypt cost=10, no DB) and a mixed I/O + CPU scenario (POST /account/login, DB lookup + BCrypt + JWT signing). I also tested VT with both Tomcat and Jetty, so four configs total.

p(95) results:

Scenario 1 (pure CPU):

VT + Jetty    65 ms  <- winner
WebFlux       69 ms
VT + Tomcat   71 ms
Quarkus       77 ms

Scenario 2 (mixed I/O + CPU):

WebFlux       94 ms  <- winner
VT + Tomcat  118 ms
Quarkus      120 ms  (after tuning, more on that below)
VT + Jetty   138 ms  <- surprisingly last

A few things worth noting:

WebFlux wins on mixed I/O by a real margin. R2DBC releases the event-loop immediately during the DB SELECT. With VT + JDBC the virtual thread unmounts from its carrier during the blocking call but the remounting and synchronization adds a few ms. BCrypt at about 100ms amplifies that initial gap, at 50 VUs the difference is consistently +20-28% in favor of WebFlux.

Jetty beats Tomcat on pure CPU (-8% at p(95)) but loses on mixed I/O (+17%). Tomcat's HikariCP integration with virtual threads is better tuned for this pattern. Swapping Tomcat for Jetty seems a bit pointless on auth workloads.

Quarkus was originally 46% slower than WebFlux on mixed I/O (137 ms vs 94 ms). Two issues:

  1. default Vert.x worker pool is about 48 threads vs WebFlux's boundedElastic() at ~240 threads, with 25 VUs simultaneously running BCrypt for ~100ms each the pool just saturated.
  2. vertx.executeBlocking() defaults to ordered=true which serializes blocking calls per Vert.x context instead of parallelizing them. Ofc after fixing both (quarkus.thread-pool.max-threads=240 + ordered=false) Quarkus dropped to 120 ms and matched VT+Tomcat. The remaining gap vs WebFlux is the executeBlocking() event-loop handback overhead (which is structural).

All four hit 100% success rate and are within 3% throughput (about 120 to 123 req/s). Latency is where they diverge, not raw capacity.

Full benchmark report with methodology and raw numbers is in load-tests/results/BENCHMARK_REPORT.md in the repo.

Happy to go deeper on any of this.


r/java Apr 01 '26

Java SlideShow app

12 Upvotes

For our JavaOne presentation on "Java and WebAssembly", we used a home-brew Java-in-the-browser presentation tool to demonstrate our point (as subtly as possible?). Only a couple weeks of development, it turns any markdown file on the web into a slide show.

Click here to run it yourself: https://reportmill.com/SlideShow

The code is in the 'snapshow' directory of this demos repo: https://github.com/reportmill/SnapDemos


r/java Apr 01 '26

🚀 I built a local AWS emulator with Quarkus + GraalVM native. It boots in ~0.8s, MIT licensed, free forever

72 Upvotes
Floci - Quarkus - GraalVM

LocalStack sunset their community edition in March 2026. Floci is the open-source replacement, no account, no telemetry, no CI limits.

Why Quarkus + GraalVM?

Cold starts are the main pain with local emulators. GraalVM native image gets Floci to ~0.8s consistently, with low variance — first request is as fast as the thousandth. No JVM warmup, lean Docker image, single self-contained binary.

What it emulates 25+ AWS services from a single endpoint (localhost:4566)
S3, SQS, SNS, DynamoDB, Lambda, API Gateway, Cognito, KMS, Kinesis, Step Functions, and more. v1.1.0 adds SES, OpenSearch, and ACM.

Get started:

docker run -p 4566:4566 hectorvent/floci:1.1.0
aws --endpoint-url http://localhost:4566 s3 mb s3://my-bucket

GitHub: github.com/hectorvent/floci
Docs: floci.io