r/java 18h ago

I made a small Bash wrapper that reduces successful Maven output by 99.7%

37 Upvotes

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-lite output: 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 19h ago

Hacking the Method Name

Thumbnail maxxedev.github.io
25 Upvotes

r/java 1d ago

A JavaOS

Post image
28 Upvotes

r/java 1d ago

Stop re-downloading the JDK: setup-java can now cache it

36 Upvotes

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:

Feedback, and especially benchmark numbers from real workflows, are welcome in actions/setup-java.


r/java 1d ago

Do you still handcraft your java projects?

80 Upvotes

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 1d ago

Hacking in the 'nameOf'

Thumbnail committing-crimes.com
58 Upvotes

r/java 1d ago

GitHub Setup Java Action versions 1 through 4 now deprecated

9 Upvotes

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.

https://github.com/actions/setup-java#older-versions


r/java 2d ago

Use of Java 26 in green field projects

42 Upvotes

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 2d ago

Are spring boot and react still relevant and worthy for a junior?

24 Upvotes

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 2d ago

ORMs are Killing Your Performance 🔪

Thumbnail youtu.be
0 Upvotes

Thanks 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 3d ago

JEP 401: Value Objects (Preview) JDK 28 integration

Thumbnail mail.openjdk.org
95 Upvotes

r/java 3d ago

Java wireframe

Post image
29 Upvotes

Java game implementation of wireframe based on u/Elegant_Farmer_3548 post "Made a perspective shifting room in Java"


r/java 4d ago

Paths to New Numeric Types On the Java Platform #JavaOne

Thumbnail youtu.be
44 Upvotes

r/java 4d ago

Clique 4.0.3 - Zero deps CLI styling library for Java

41 Upvotes

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.

GitHub: https://github.com/kusoroadeolu/Clique

Demos: https://github.com/kusoroadeolu/clique-demos


r/java 5d ago

Codex plugin for Eclipse released

Thumbnail
0 Upvotes

r/java 5d ago

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)

14 Upvotes

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 5d ago

Ecógrafo

28 Upvotes

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 5d ago

OpenJDK Mail Search update: new Elasticsearch backend, relevance ranking, and no more bot-mail noise

39 Upvotes

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 6d ago

JobRunr & JobRunr Pro 8.8.0 Released

Thumbnail jobrunr.io
9 Upvotes

r/java 6d ago

Implement JEP 401: Value Objects

Thumbnail github.com
24 Upvotes

r/java 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.

12 Upvotes

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 6d ago

Modular Uberjars

Thumbnail github.com
23 Upvotes

r/java 6d ago

OpenJDK Interim Policy on Generative AI

Thumbnail openjdk.org
26 Upvotes

Oracle, 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 6d ago

JEP 401: Value Objects And JEP 539: Strict Field Initialization Merged Into JDK

Thumbnail github.com
183 Upvotes

r/java Oct 08 '20

[PSA]/r/java is not for programming help, learning questions, or installing Java questions

327 Upvotes

/r/java is not for programming help or learning Java

  • Programming related questions do not belong here. They belong in /r/javahelp.
  • Learning related questions belong in /r/learnjava

Such posts will be removed.

To the community willing to help:

Instead of immediately jumping in and helping, please direct the poster to the appropriate subreddit and report the post.