Yep, I find it easier to think of a Spring (or any DI) Bean like a parameterized module that is applied at runtime, the code within each bean is pretty procedural.
It's getting better, it doesn't all have to be Spring Boot and JBoss.
There is quarkus, helidon and micronaut for slimmer more modern backend frameworks. jbang for scripting (think uvx, bunx), Tambo UI (https://tamboui.dev/) for terminal UIs, and more.
Along with all the new Java features that help you write much simpler code - eg. virtual threads, structured concurrency, stream gatherers, and performance / resource improvements.
It's not all there yet, but I think the next few years things will come together nicely (however a better build system is sorely needed - one of the things that Go / Rust did right).
I've found it quite satisfying compared to the other "new" ones.
As for the original topic, I just want to echo what others have said, and say that I am happiest in Java when writing it as if it were Golang code. That an the first-class runtime and performance and deep ecosystem make it a great choice in 2026.
It’s still very much an annotation festival in the code, making the framework quite lengthy to learn for newcomers (gotta learn Java and the whole quarkus annotation DSL with it).
Go is verbose, but it is much more explicit and only uses standard language things instead of a whole annotation DSL.
In my opinion Helidon is the most refreshing of these frameworks. It supports virtual threads from the ground up and comes with clean, function, mostly annotation free APIs. It really looks like a Java framework should look today.
There are non-DSL frameworks in Java. It's just that arguably the benefits of a DSL outweigh learning them.
Putting an annotation on a method is much easier than registering this method at n places in ordinary code, which could look any number of ways. If you move to a new project, in the first case can just immediately jump into framework-related stuff, while in the second all this logic has to be untangled first. And let's be honest, Spring/Quarkus probably got their abstraction right after n iterations, which is not necessarily true of a random team.
If someone reads this and wonders what JBoss is, the contemporary variety is called WildFly and it is actually rather easy to install and play around with.
As you’re familiar with the JBoss space, why would someone use an enterprise container over a simple HTTP server (Tomcat, Jetty, etc)?
Currently I’m trying to externalize as much as possible to the service mesh. I want teams to stand up a basic unencrypted HTTP server that accepts the company headers and just works with as minimal of a runtime as possible.
Yep, I'm using JBoss as a catch-all for older "big-iron" style Application Servers - modern Jakarta EE (10 onwards) is much more slimmed down, and a solid option.
unsure re Maven, 4.0.0 has been around the corner for years, but I think there is space for a modern alternative that is JPMS first, supports semantic versioning (i.e. tilde/carat notation) with lockfiles, and doesn't require a bunch of plugins out of the box for common use-cases. Maybe Mill (https://mill-build.org) - i've yet to try it.
Mill looks kind of nice on the surface but I haven't seen it in action in any serious project. I suspect the flexible DSL might come with a maintenance burden.
XML is nice, if your pom.xml is massive, just suck it in through JAXB and program against it, perhaps render it to a web page. XSLT can also be helpful. We're not supposed to look at XML as plain text.
Not really, no. It is similar but worse than Maven in that it requires quite a bit of time investment to configure, and shares the drawback of Gradle that it is configured in a programming language instead of a configuration language.
Switching out Maven for a larger maintenance burden might be reasonable in a large organisation that is swimming in competent employees, but most do not.
As for obvious contender, I'd say that would be Gradle, which is harder to get someone started with than Maven and due to the DSL allows you to invent weirder footguns.
Did everyone just agree to forget about Gradle? It was everywhere not too long ago. I think I even prefer it to Maven, in a choice between a rock and a hard place type of way.
Yeah, same, but Elixir gigs aren't as common as Java gigs. However, if one ends up in a Java role, chances are that Elixir would be a good porting target for the systems since it typically can replicate the architecture but with less fuss and has pretty good support for interfacing with Java.
Nobody ever wanted to wire up RPC endpoints, in the form of Enterprise JavaBeans(tm), using XML files. That is one for the history books of ridiculous technology.
XML files are bad. Invisible magic is worse. The sensible way to wire up a bunch of RPC endpoints is, like the sensible way to do most things, plain old code.
Having used micronaut for a few years now, I hate it.
Maybe it's innate to trying to use a a fully fledged server-style framework in a serverless context, but I don't think it's suitable. In fact I think the whole idea ("Hey, let's bludgeon spring-like metaphors into an entirely new setting") was a poor one.
Java itself I've enjoyed more and more over time as the language has evolved into something much more expressive, and without all the enterprise crap. My hope is that one day frameworks like Micronaut will end up discarded too.
Never done much Spring, so I don't have a lot to compare to. But ...
I'm not a massive fan of using annotations in concept, because they obfuscate what's taking place. Unlike in (say) Python, where annotations are effectively functions wrapping the function they annotate, in java they're more akin to a customisable preprocessor. Obviously I do use them, liberally, because that's the way things are done, but I'm not a big fan. And using any modern framework relies on these a lot.
Micronaut gripes -
1. It works great until it doesn't, and you have a special case, and then you have to dig into source to figure out what on earth is going on.
2. Keeping up with latest isn't always easy, micronaut 3->4 was a huge effort.
3. For all it's called micronaut, the produced packages are pretty huge.
Serverless-specific gripes -
1. What I'm receiving isn't really an http message over a socket. It's an AWS gateway event with everything already read and packaged up. So there's no reason that (for instance) I shouldn't access the message body in a request filter, because I don't give a crap about the jetty server-loop being non-blocking.
2. Startup time is terrible. And when I managed to get a native compiled version to actually run, it got worse. A lot of this seems to be down to hibernate, but there's a big gap between startup and any logging from the framework at all. We've tried a bunch of stuff to remediate, so far with little success.
In general I think that serverless is such a different paradigm from a long-running server that approaching it from the point of view of "how can we make this the same so developers who've never thought outside of the spring-like box can still be productive?" was wrong from the outset.
> Unlike in (say) Python, where annotations are effectively functions wrapping the function they annotate, in java they're more akin to a customisable preprocessor.
I find that Python decorators can do as much magic as an annotation processor - due to the dynamism of Python. Annotation processors, in most cases, produce a new class based on annotations on existing class / interface. The injection of that class is done by the DI container (unless it's a standalone annotation processor like mapstruct).
> And using any modern framework relies on these a lot.
To be fair to language designers, it's hard to avoid code generators. And they're a compelling thing compared to building proxy objects / DI / decorator / dataclass etc.. kind of functionality in language and getting it wrong.
> ... then you have to dig into source to figure out
Agree. It's not a "boring technology" yet.
> For all it's called micronaut, the produced packages are pretty huge.
How huge? And jlink or graal vm? Just curious.
> A lot of this seems to be down to hibernate,
With micronaut atleast, I remember using Micronaut Data JDBC. Anything is better than hibernate.
> In general I think that serverless is such a different paradigm from a long-running server.
> a better build system is sorely needed - one of the things that Go / Rust did right
Honestly there are only two reasons I wouldn't pick up Java for personal projects, difficult to build single executable (Graal is still very un-ergonomic), ridiculous build systems.
I can kind of live with former, but Gradle is so very extraordinarily terrible that I don't know where to begin. Problem is, it solves some real problems (in extremely bad way) that people keep using it.
I long of a cargo-style revolution in Java world. (No, the newly popped up alternatives haven't really cut it so far)
I've seen this concept a few times recently and am interested.
However, what's the benefit over just using the "Claude Code for Web" feature built into the Claude Code mobile app?
It clones your repo into a VM which has a bunch of dev tools installed, you can install additional packages, set env vars, and then prompt it remotely. The sessions can be continued from the web and desktop apps, and it can even be "teleported" into the terminal app when back at a laptop/desktop.
Would be great to understand what the differences / advantages of OP approach are.
I feel like there’s something special about connecting to a server to build and deploying on the same server. Claude Code on the web lets you connect to a repo, test the code, and deploy it, but then you have to host the app and data somewhere else to take it live. IMO the ideal is doing everything in one place and it seems like a lot of dev tools are going in that direction too (v0, val town, deno deploy).
I’ve only used web codex version but everything about it was slower than what’s described here, broken flows, more rate limited and impossible to “human in the loop” before a PR.
Yep, have seen this myself as previously a manager and now with a young family.
I can make incredible progress on side-projects that I never would have started with only 2-4 hours carved out over the course of a week.
There is a hopefully a Jevon's paradox here that we will have a bloom of side-projects, "what-if" / "if only I had the time" type projects come to fruition.
This is exactly the case. Businesses in the past wouldn't automate some process because they couldn't afford to develop it. Now they can! Which frees up resources to tackle something else on the backlog. It's pretty exciting.
I’m not convinced that “single binary” really matters in practice. What actually matters is how easy it is to install, run, and update an application, and that depends entirely on the target user.
For end-user apps, this is basically solved: use jpackage to ship an installable app with a bundled, trimmed JRE. Better yet, distribute via the OS app store so updates are handled for you (on Linux, Flatpak is probably the right answer today).
For CLI tools, you’re already assuming a more technical audience. At that point you have two real options:
- ship just the app and rely on a smart launcher/runtime manager (npx, bunx, uvx, jbang), and assume your technical audience can install that first
The real question isn’t "is it a single binary?", it’s "how do users install, run, and update it?". In practice, that’s already been solved by developer package managers like brew and scoop. All the Go and Rust CLIs on my machine are installed via brew, not manually downloaded from GitHub releases.
You also want CLIs on PATH or inside a dev environment (mise, direnv, etc.), so whether that executable is a true single binary or a symlink to a bundle is mostly irrelevant.
So the trade-off becomes, do you support `brew install foo-java-tool` with a bundled JRE, or do you ask users to `brew install jbang` and then `jbang install foo-tool`? Either way, the end result is the same, you run `foo-tool`.
Note, Claude Code for instance supports both options (curl | bash, brew cask, and npm -i), isn't a single binary, and that still hasn't stopped it from being the most popular CLI tool released this/last year.
There’s definitely room for improvement in Java’s packaging story, I just think the focus shouldn’t be on "single binary" as the primary goal.
Apologies for submitting before the project was perhaps ready for a wider audience. I'm a boring Spring developer these days but enjoy reading about wider JVM developments and thought this was cool and worth sharing.
I think it's a shame that the HN audience's AI debates tend to derail more interesting technical conversations.
From my perspective, there are many valid reasons to use AI to bring a project to fruition, including speed, project scope, time constraints, etc. If AI helps bring to life projects that would otherwise remain daydreams, especially open-source ones, that's a win imo.
It's also far-fetched to assume someone clearly an engineer, building a project of such scope, working with low-level Java, integrating io_uring, and generating tests to ensure contracts, is a "vibe-coder" in the pejorative sense. It's unfortunate that some HN users resort to name-calling and gatekeeping, and I think some newer community rules and guidelines for AI-enhanced submissions would be helpful.
Thanks @mands for you reply!
I am glad you did post it and really thanks for it. However, I echo your thoughts too - I was expecting a constructive engagement re FFM & io-uring, etc. but unfortunately the entire thread digressed into AI & vibe coding etc.
We've just moved to GraphQL after using REST and bog-standard RPC, and it's been a breath of fresh air. I was considering building my own HTTP RPC system, similar to json-rpc or open-rpc, but I would have ended up with a poorly-specified GraphQL clone.
I think GraphQL's biggest issue is a naming and positioning problem. I, along with colleagues, thought for a long time that it was tied to graphs, DB query languages, and heavy backend implementations.
It's actually a typed RPC system designed for Client UIs, including SPAs and mobile. We're using it with a monolith in a code-first manner, where the schema and client code are auto-generated from backend types.
I think the project could benefit from a `graphql-lite` / `graphql-full` split, where `-lite` includes a well-documented, leaner core featureset (RPC, simple resolvers), and full mode includes federation.
reply