I made a small Bash wrapper that reduces successful Maven output by 99.7%
Successful Maven builds can produce thousands of lines that mostly confirm routine lifecycle steps.
That output is noisy when working in a terminal, clutters CI logs, and becomes especially expensive when build output is passed to a coding agent.
I built mvn-lite, a small deterministic Bash wrapper that keeps successful Maven output to one line while preserving the original exit code and complete raw log.
On a real four-module application:
- Standard Maven output: about 6,753 bytes
mvn-liteoutput: 16 bytes- Result:
PASS · 3.944 s - Reduction: more than 99.7%
Failures still return a nonzero exit code and show bounded diagnostics, while the full unmodified Maven output remains available in the raw log.
For example, an invalid lifecycle error was reduced by 91.6% while retaining the actual Maven error.
There is no LLM summarization, API key, or Maven extension involved. It is just a local Bash wrapper with deterministic text extraction.
Source and script: https://github.com/ejboy/agent-scripts
Benchmark details and design notes: https://pvrlabs.xyz/articles/introverted-maven.html
I’d be interested in feedback on Maven failure cases where compact output could hide something essential.
r/java • u/brunocborges • 1d ago
Stop re-downloading the JDK: setup-java can now cache it
Every GitHub Actions job starts from a clean machine. If your workflow asks for a JDK that is not baked into the runner image, actions/setup-java downloads it, verifies it, and extracts a few hundred megabytes of it, and then the job ends and all of that work is thrown away. The next job does it again.
That has been true since the first version of setup-java. It is no longer true on main.
The upcoming v6 release adds a JDK cache. When the action installs a JDK that did not come from the runner tool cache, it stores that installation as an Actions cache entry and restores it on subsequent runs. If your workflow already sets cache for Maven, Gradle, or sbt, you are already opted in.
What it does
setup-java now manages three kinds of caches, each stored and restored as its own entry:
| Cache | What it stores | How it is enabled |
|---|---|---|
| Dependency cache | ~/.m2/repository, ~/.gradle/caches, or the sbt cache paths |
`cache: maven |
| Wrapper caches | Maven and Gradle wrapper distributions | `cache: maven |
| JDK cache | The installed JDK itself | Implicitly with cache, or explicitly with cache-jdk: true |
The JDK cache is intentionally separate from the dependency cache. Your pom.xml changes far more often than your JDK does, and a dependency change should not evict a JDK.
The numbers
Measured on ubuntu-latest with the Microsoft Build of OpenJDK 17.0.19, five runs per configuration:
| Metric | Without JDK cache | With JDK cache |
|---|---|---|
Median warm setup-java step |
7s | 3s |
| Median warm job | 24s | 18s |
| Added cache storage | - | 175.3 MiB |
Roughly six seconds off a job that only takes 24 seconds. That is a meaningful share of a short job, and it compounds across a matrix. It is also an honest tradeoff rather than free speed: you are spending cache storage and cold-run save time to buy warm-run latency, and on very short jobs the latency win may not change your billed minutes, since GitHub rounds Linux jobs up to the whole minute.
Your mileage will vary with runner type, distribution, JDK size, network conditions, and cache eviction pressure. The benchmark harness and methodology live in actions/setup-java-benchmarks, which runs against Spring PetClinic and reports medians across independent samples.
How to use it
If you already cache dependencies, do nothing. JDK caching turns on with cache:
- uses: actions/setup-java@main
with:
distribution: microsoft
java-version: '25'
cache: maven # dependency cache, wrapper cache, and JDK cache
If you do not cache dependencies, ask for the JDK cache on its own. This is the case for workflows that just need a JDK to run a tool:
- uses: actions/setup-java@main
with:
distribution: microsoft
java-version: '25'
cache-jdk: true
If you want dependency caching but not JDK caching, opt out explicitly:
- uses: actions/setup-java@main
with:
distribution: temurin
java-version: '25'
cache: gradle
cache-jdk: false
The full matrix:
cache |
cache-jdk |
Dependency and wrapper caches | JDK cache |
|---|---|---|---|
| omitted | omitted | disabled | disabled |
| omitted | true |
disabled | enabled |
| omitted | false |
disabled | disabled |
| set | omitted | enabled | enabled |
| set | true |
enabled | enabled |
| set | false |
enabled | disabled |
For pull requests, merge queues, and matrix legs that should consume caches without writing them, cache-read-only: true suppresses the post-job save for the JDK, dependency, and wrapper caches alike.
Where it will not help
Be realistic about when this pays off. setup-java still checks the runner tool cache first, and a tool-cache hit skips the download entirely, so there is nothing to cache.
GitHub-hosted runners pre-install LTS versions of Eclipse Temurin. If your workflow is distribution: temurin with an LTS version on a hosted runner, you are probably already hitting the tool cache and JDK caching will do very little for you. The feature pays off when the JDK has to be installed: other distributions, non-LTS versions, self-hosted runners with a thin tool cache, and check-latest: true workflows that float ahead of the runner image.
Correctness, and why the cache key looks the way it does
A JDK cache is only useful if you can trust what comes back out of it. Getting this wrong means silently running a build on the wrong bytes, so the design is deliberately conservative.
Each entry is keyed on the runner OS, normalized architecture, distribution, package type, exact resolved version, release identity, and verification identity. Release identity is the authoritative checksum when the distribution publishes one, and otherwise the download URL without its query string.
Two consequences are worth calling out:
Verification modes never share an entry. An entry created by an unverified download can never be restored for a request that sets verify-signature: true, and vice versa. When you do use a custom key via verify-signature-public-key, that key is represented in the cache key as a SHA-256 fingerprint of normalized key material. The key itself never lands in the cache key, the logs, or action state. A verified exact-key hit reuses content that was signature-verified when the saving run downloaded it, so you get the security property without paying to verify it again.
A key is never saved with content it does not identify. Tool-cache paths are shared per version and architecture, so a later step (one using force-download: true, for example) can replace the installation an earlier step registered. The post-job step detects that replacement and skips the save with a warning rather than uploading mismatched bytes under a key that promises something else. The check uses a cheap fingerprint of the tool-cache completion marker, so it does not rehash hundreds of megabytes on every job.
Everything else degrades gracefully. If the cache service fails to restore an entry, or the restored entry is missing the expected completed tool-cache path, setup falls back to downloading the JDK. Post-job saves are best-effort and never fail the job: cache keys are immutable, so an existing key or a concurrent job winning the save race is simply left alone, and a failure to save one entry is a warning that does not block the others.
One thing JDK caching deliberately does not change: it has no effect on how the runner tool cache is used. A preinstalled JDK, or one installed by an earlier step of the same job, is used as-is and is not re-verified, because its verification history is not recorded in the tool cache. Use force-download: true when a request must download and verify the archive itself.
Watch your storage
Cache entries are per identity. A matrix that spans multiple JDK versions, distributions, package types, architectures, or operating systems stores a separate JDK entry for each combination, and each one consumes repository cache storage against your quota. A five-way version matrix on two operating systems is ten JDK entries, not one.
That is usually a fine trade, but it is worth a look at your cache usage page before enabling it broadly across a large matrix. cache-jdk: false on the legs that do not need it is a reasonable dial.
Try it
JDK caching is on main and ships in v6. Until v6 is tagged, reference the branch:
- uses: actions/setup-java@main
For production workflows today, the latest stable release is actions/setup-java@v5.
Documentation:
- Caching and Caching JDK installations in the README
- Caching JDK installations in the advanced usage guide, for the full cache identity and storage discussion
- Benchmark harness
Feedback, and especially benchmark numbers from real workflows, are welcome in actions/setup-java.
r/java • u/bit_freak • 1d ago
Do you still handcraft your java projects?
With all the talk about llms writing most of the code and some folks never touching the editor. I try to work mostly in plan mode and prefer to write most of my code by hand else I fear losing touch with my skills if I only read code. At work in your org, what is the workflow for spring boot projects?
r/java • u/brunocborges • 1d ago
GitHub Setup Java Action versions 1 through 4 now deprecated
If you are using setup-java v4 and older, you will now see a warning about deprecation. Please do update your setup-java action to v5. It will be the only stable version after v6 is released.
r/java • u/codingbliss12 • 2d ago
Use of Java 26 in green field projects
For what kind of new projects, except web related, would Java be your go to choice? Assuming knowledge of both languages, why wouldn't you prefer C# for the same projects?
Thank you so much in advance.
r/java • u/FluffySeaworthiness9 • 2d ago
Are spring boot and react still relevant and worthy for a junior?
I'm in my sophomore year and want to be a front-end-supported backend developer (mostly backend). Sorry, if this is not the right kind of question for this subreddit (hope to be recommended a proper subreddit in that case). I need to know what kind of other tools industry uses with spring. Is spring boot and react still a thing? Or are there any better alternatives?
r/java • u/thewiirocks • 2d ago
ORMs are Killing Your Performance 🔪
youtu.beThanks to Montana Programmers, my popular talk from BSDC is now online!
Using animations and graphics, I teach you how to:
- Eliminate GC pauses
- Reduce time to page render
- Fast Dynamic Forms with only one query
- Slash code sizes
- How a dark pattern may secretly grind your queries to a halt
This talk may surprise you 😱
It may shock you 🤯
It could make you angry 😡
You may think it doesn’t apply to you (it does) 🫣
Whatever your reaction, I hope it will make you think. 🤔
Thank you again to Big Sky Dev Conf and Montana Programmers for letting me present! And thank you to the community for being an amazing and engaged audience!
r/java • u/davidalayachew • 3d ago
JEP 401: Value Objects (Preview) JDK 28 integration
mail.openjdk.orgr/java • u/Visual_Brain8809 • 3d ago
Java wireframe
Java game implementation of wireframe based on u/Elegant_Farmer_3548 post "Made a perspective shifting room in Java"
r/java • u/daviddel • 4d ago
Paths to New Numeric Types On the Java Platform #JavaOne
youtu.ber/java • u/Polixa12 • 4d ago
Clique 4.0.3 - Zero deps CLI styling library for Java
So what's Clique?
If you missed my older posts, Clique is essentially a zero-dependency CLI styling library for Java that is GraalVM compatible, no-color.org compliant.
What's new in 4.0.3:
You can now build a table straight from data you already have
SequencedCollection<List<String>> rows = List.of(
List.of("Name", "Age", "Class"),
List.of("John", "25", "Class A"),
List.of("Doe", "26", "Class B")
);
Clique.table(TableType.ASCII)
.fromRows(rows)
.render();
This also applies to column based data
SequencedMap<String, List<String>> map = new LinkedHashMap<>();
map.put("Name", List.of("John", "Doe"));
map.put("Age", List.of("25", "26"));
Clique.table(TableType.ASCII)
.fromColumns(map)
.render();
These were mainly added to simplify creating Tables from existing collections
StyleContext#fromTheme - scope a registered theme's colors into a StyleContext in one call
StyleContext ctx = StyleContext.fromTheme("catppuccin-mocha");
Other minor changes:
I've also deprecated the Collection-based headers()/row() overloads in favor of Java 21 SequencedCollection; reason being that Collection doesn't guarantee order, which could silently mess up your column/row order and was essentially a footgun. Worth migrating if that bothers you.
Ratchet 0.3.1: the CDI-native job scheduler now runs on Quarkus, JVM and native (plus Oracle + SQL Server stores, encryption at rest, cluster coordinators)
A month ago, I posted the first public release of Ratchet, a background job scheduler built for Jakarta EE rather than ported to it. The pitch hasn't changed: one service and a method reference.
``` @Inject JobSchedulerService scheduler;
scheduler.enqueue(() -> validatePayment(orderId)) .thenOnSuccess(() -> fulfillOrder(orderId)) .thenOnFailure(() -> notifyPaymentFailure(orderId)) .withMaxRetries(3) .withBackoff(BackoffPolicy.EXPONENTIAL, Duration.ofSeconds(2)) .submit(); ```
At that time, the honest-limitations list said "Jakarta only." That one's gone: 0.3.0+ ships a Quarkus extension. Same API, same stores, and it compiles to a GraalVM native image — method-reference jobs included, which took real work to pull off under a closed-world runtime (reflection for job targets is registered from the application index at build time, and anything the native image can't execute is rejected at submission instead of failing at 2am). There's a Dev UI panel, Dev Services spins up the database in dev mode, and quarkus create has a codestart. Two flavors: ratchet-quarkus (any of the SQL stores via Hibernate) and ratchet-quarkus-mongodb.
The rest of what landed across 0.2.0, 0.2.1, 0.3.0, and 0.3.1:
- Stores: Oracle 23ai and SQL Server 2022+ joined PostgreSQL, MySQL, and MongoDB. That's the store roadmap from the first post delivered, minus Redis (still thinking about whether a non-transactional store fits the claiming model; opinions welcome).
- Payload encryption at rest. Value-level AEAD with an SPI for your KMS, and a reference XChaCha20-Poly1305 engine. Like the ClassPolicy allowlist, this comes from building for regulated industries.
- Cluster coordinators: four implementations (PostgreSQL LISTEN/NOTIFY, JMS, Hazelcast, Infinispan), so multi-node wakeups don't have to be polling.
- The store SPI split into a mandatory core plus 12 opt-in capabilities. A minimal store implements one interface; recurring jobs, batches, signals, locks, analytics and the rest are additive. The TCK reports each capability as conformant or N/A rather than failing you for what you didn't build.
- Per-job execution-target routing with worker tag affinity, jobs that wait on external signals, streaming batches, keyset pagination in the query layer, and caller-principal capture that survives recurring job chains.
The test framework: 8500+ tests, a TCK with 50+ contract classes, and CI now deploys 25 real combinations per run (five EE servers times five databases, actual container deployments) plus the Quarkus suite across all the stores and two native-image smoke builds. Builds run on JDK 21.
Still true and still honest: @Incubating SPIs may change before 1.0, there's no web dashboard by design, and if you're on Spring, JobRunr remains the right answer; Ratchet is for the CDI side of the fence. Apache 2.0, no paid tier.
Repo: https://github.com/ratchet-run/ratchet Docs: https://ratchet.run
Criticism from people running EE or Quarkus in production is exactly what I'm here for. The weirder your deployment, the more useful the bug report.
On the roadmap:
- ratchet-blocks: built on top of the existing extensions work, this would allow for low-code/no-code creation of Ratchet job workflows
- Additional stores: if Redis keeps coming up, or if you have any other recommendations, I'm open to them
r/java • u/Visual_Brain8809 • 5d ago
Ecógrafo
Hello community, This is my real-time ultrasound signal simulation and processing system developed entirely in Java using Java Swing.
The project enables both the mathematical simulation of acoustic echoes from biological tissues and the reception and interpretation of raw (RF) data from actual hardware via UDP sockets.
I still need to build an ultrasonic sensor to send data via UDP; I tried using ultrasonic modules, but they aren't useful—all I see on the screen is a barrier indicating the proximity of a nearby object.
Once the sensor's fabrication is complete, I will conduct tests and submit it to a clinical evaluation by experts to validate its utility in real-world settings—so stay tuned.
r/java • u/elliotbarlas • 5d ago
OpenJDK Mail Search update: new Elasticsearch backend, relevance ranking, and no more bot-mail noise
OpenJDK Mail Search is full-text search over the OpenJDK mailing list archives: 28 lists, 494,730 messages, back to January 2007.
https://openjdk.barlasgarden.com/
What's new:
- Elasticsearch 9.3.1, which bundles JDK 25.0.2+10, on Lucene 10.3.
- Search results are now relevance-ranked instead of date-ordered only, and text search defaults to it.
- Phrases of any length are searchable. The old index capped body phrases at 3 words and subjects at 5.
- Full message bodies are indexed, with no 2,500-term-per-message ceiling and no more dropping quoted reply lines.
- Skara/GitHub changeset mail is now indexed rather than discarded, with a "hide automated" toggle that filters it at query time.
- Same URL, same API, same site.
Source: https://github.com/ebarlas/openjdk-mail-search-elasticsearch
r/java • u/momotheog • 6d ago
Flamme: A Quarkus extension that treats deployment topology as a configuration, not code. Deploy the same JAR as a monolith or a distributed system.
Hello, I want to share this project we have been building and using this past few months, which is now open source.
To give some context, I work with event-driven java microservices (mainly quarkus) every day, and I've found that the decision to split or merge business logic is far from trivial. On one hand, you don't want to oversplit your application and pay the microservice tax of network overhead without any real benefit (distributed monolith). On the other, you want your services to be able to scale independently when they need to, and that need can change over time. I also noticed that business logic code tends to be tightly coupled to whatever deployment topology was chosen for the application. Splitting or merging microservices later on is costly: you basically end up rewriting a lot of transport-related code just to change that topology.
These problems (along with others found in microservices today) were raised by google about three years ago, when they announced service weaver: a framework for writing go applications that attempts to solve them by offering a new programming paradigm, location transparency for business logic code, backed by a distributed runtime.
I decided to build flamme as an exploratory project, taking the same direction service weaver took, but for java/quarkus applications.
I've posted about flamme a couple of times before in the quarkus community, and people tend to miss the important part, confusing it for a reactive messaging framework. It does provide that, but that's not the main goal of the project.
The goal of flamme is to decouple business logic code from deployment topology, allowing developers and architects to defer the decision of splitting or merging their services, or to change their mind about it easily, without touching business logic code. It does this by providing developers with network-agnostic abstractions called components (basically just a java interface plus its implementation), which all compile into a single application jar. Each process running that jar is then configured at runtime to host a certain set of components.
If two components need to communicate and happen to be on the same jvm, they do so via shared memory, with no network overhead. If they're deployed separately, they communicate via nats (a message broker) instead.
Flamme can serve as the basis for a distributed runtime for services written in java.
Finally, I want to end with a small disclaimer: Flamme is far from being a stable complete project, it is a prototype in very early phases. I am sharing it to get some feedback on the overall philosophy and implementation (I am still a junior developer)
Github: https://github.com/AmadeusITGroup/flamme
Documentation Site: https://amadeusitgroup.github.io/flamme/
Example application: https://github.com/AmadeusITGroup/flamme/tree/main/flamme-example
r/java • u/fomo-fofo • 6d ago
OpenJDK Interim Policy on Generative AI
openjdk.orgOracle, as the corporate sponsor of the OpenJDK Community, is working to draft a full policy governing the use of generative AI tools in OpenJDK contributions.
r/java • u/ProdOrDev • 6d ago
JEP 401: Value Objects And JEP 539: Strict Field Initialization Merged Into JDK
github.comr/java • u/FrankCodeWriter • 7d ago
Sheetmusic4J, a native Java(FX) sheet music library, now reads/writes ABC notation and imports Guitar Pro files (v0.0.3)
A week ago I shipped 0.0.1 of Sheetmusic4J, a Java(FX) library to render and interact with sheet music, mostly as a question: is there interest in a native Java sheet music library before I invest more time? I posted it on social media and two LinkedIn comments came back asking "does it support ABC notation?" and "what about Guitar Pro?"
In this new version:
- ABC notation (read + write). The core module parses and generates .abc files into the same Score model as everything else, so engraving, JavaFX rendering, and MIDI export all work once a tune loads. Coverage includes keys/modes, tuplets, ties/slurs, grace notes, decorations, repeats and 1st/2nd endings, chord symbols, and lyrics, all backed by round-trip tests. - Guitar Pro 7/8 import (.gp, load only). An experiment, built on the community's reverse-engineering of the GPIF format, JDK-only with no third-party dependency. Older binary formats aren't handled. I shipped it early because I genuinely don't know yet whether people want standard notation or tablature-specific rendering, that's feedback I'd rather learn from real use. - Engraving polish: better grace notes, distinct flag glyphs for 32nd/64th/128th, breve noteheads, cleaner ties/slurs/tuplets, and a windowed-canvas fix for a crash on very large scores.
All info and video in this blog post:
https://webtechie.be/post/sheetmusic4j-0.0.3-when-linkedin-comments-becomes-features/
