Ask HN: What is a modern Java environment?
132 points| smorgusofborg | 3 years ago
I used Java a very long time ago, like 1.6, and I'm wondering what using Java at work in ~web backend looks like today.
What elements of your stack would you consider most important? Do most projects lean heavily on Spring Boot or something else? Which IDE? Pointers to refreshers or concise introductions you might give a new hire would be handy too.
exabrial|3 years ago
We're fans of CDI, it's a more polished Spring framework without the legacy weight. We're developing in Quarkus, MicroProfile, and bigger monoliths in Apache TomEE. We use ActiveMQ extensively for scaling. ( And I mean extensively... on a modest 512m server, we can push several thousand messages/s reliably to a _lot_ of topics and queues, all with delivered-exactly-once guarantees)
We avoid the fanfare of Docker, as really it's not needed for Java apps; they're somewhat self-contained anyway and it created more problems than it solved. For true isolation, we use systemd to create cgroups and chroots and prevent application escapes. For deployment, apps are one-jar'd down to a single executable, then packaged up in a .deb using the jdeb maven plugin. We stick with the unix philosohpy of using /etc/default for env variables that help the app locate their database or LDAP cluster.
gavinray|3 years ago
I did a project using GraalVM's polyglot abilities and needed an API.
Tried Spring, Micronaut, Helidon, Ktor and Quarkus.
Quarkus is the best web framework I've ever used, in any language. Can't go back now.
It's so well-architected that I was able to contribute an extension for Scala 3 support within a month, and the Redhat employees have answered every question + issue I've raised.
Being built on top of the Microfile spec and using Vert.x is a hell of a combo. Vert.x is the best thing since sliced bread too.
Can't recommend Quarkus enough, whether you write Java or Kotlin or Scala (I'm a big Kotlin fan myself).
ActorNightly|3 years ago
If you use a language that doesn't require OOP, you can do the same isolated unit tests without DI.
metaltyphoon|3 years ago
Since dotnet core started this has been front and center in C#. So there are other stacks doing this.
thedougd|3 years ago
If it takes too much effort to write that anonymous inner class, then the Interface may be too big and need broken up. Or maybe you're hiding too much state and need to rethink the API.
edmcnulty101|3 years ago
This makes it super portable.
Just something to think about.
I personally think the win's from Containerization are greater than the challenges.
lloydatkinson|3 years ago
It's exactly the same in the .NET space
omgitsabird|3 years ago
What does this mean?
matsemann|3 years ago
Which of course means all the old discussions: Jetty/Tomcat/JBoss/GlassFish, GSON/Jackson, Hikari/C3PO/etc, etc are now mostly moot, since most just use the Boot defaults until they need something else. Kinda nice, actually. Less bikeshedding, can get a project up and running without taking a stand on all these things.
Most clients use maven, a few gradle, some used gradle and moved back when no one could understand their config. Gradle might get a second chance now that it can be written using kotlin.
jillesvangurp|3 years ago
If you feel more adventurous. Ktor is also quite nice and a lot more lightweight than spring. They have a pretty big 2.0 release coming up for that with a lot of nice improvements. Ktor is also a nice alternative for doing http clients. Kotlinx serialization is the way to for serialization; especially if you are interested in multiplatform. Spring supports that as well since a few releases.
If you use Kotlin, stick with Gradle and use the kotlin scripting variety. Maven is very much a second class citizen in that ecosystem. It's supported (grudgingly) but not that actually that widely used. A lot of older Spring projects might still use it because they started out as maven/java projects and only later added Kotlin. However, if you start from scratch, just use gradle and take the path of the least amount of resistance. You'll have an easier time and essentially all of the Kotlin documentation assumes you use gradle. For things like kotlin multi-platform, maven is an afterthought. I'd be surprised it works at all actually for that.
luciusdomitius|3 years ago
If you want to go full hipster, there is Micronaut (also Quarkus) and if you'd like to go a bit off-charts, there is Dropwizard. I don't think that they offer anything extra over SB though.
joshenberg|3 years ago
sylens|3 years ago
Pick up Kotlin first, then Spring Boot? Or the reverse? And is the free version of IntelliJ good enough? I noticed on the features list that Spring support wasn't listed
davidjfelix|3 years ago
* Try to use Kotlin where allowed (Maybe unpopular and bad faith response given that you asked about Java, but I don't care -- kotlin's Java interop is way more seamless than Scala or Clojure to the point that its often not even noticable) https://kotlinlang.org/
* IntelliJ
* Spring is pretty popular, I've seen a lot of people using Vertx
* Square libraries like Okio, okhttp, retrofit, wire https://github.com/square
* If you're not using spring, use Dagger for DI https://dagger.dev/dev-guide/
* Overlook netflix abandonware (another unpopular opinion, I'm sure)
* Use gradle, not maven. Use kotlinscript as the config language, not groovy
jillesvangurp|3 years ago
sk5t|3 years ago
oauea|3 years ago
If you want a slow build and code that is fun to write but hell to read, that is good advice.
> Use kotlinscript as the config language
Extremely slow, that is.
ojhughes|3 years ago
* Testcontainers - seamless support for using Docker in integration tests [1]
* Project Reactor - nice framework for reactive programming [2]
* Executable Jars - No need to deploy a War file to a servlet container anymore. Build an executable Jar with an embedded container. Spring Boot makes this very easy
1. https://www.testcontainers.org
2. https://projectreactor.io
mooreds|3 years ago
I don't write too much code nowadays, but read a lot. From what I can see, here's the stack:
* intellij for an ide (with tons of plugins)
* prime MVC (https://github.com/prime-framework/prime-mvc) for the framework
* mybatis for SQL/queries
* java 17
I've also used dropwizard and spring. If it was a greenfield development with emphasis on developer productivity, I'd go with spring any day. Big dev community, tons of doco, a solution for any problem if you can find it.
kitd|3 years ago
For something a bit lighter weight, Vert.x [3] is a good option (Quarkus is based on it).
[1] - https://quarkus.io/
[2] - https://micronaut.io/
[3] - https://vertx.io/
You'll need Java 1.8+, and Maven or Gradle for the toolchain (I prefer the former). Intellij is the best IDE but I get by with VSCode.
isbvhodnvemrwvn|3 years ago
splix|3 years ago
The most common: - Kotlin for most of the backend code, but Java for shared libs. We still use Java 8 for some libs which may be used in Android, that's an unfortunate reality
- Gradle for build config
- Spring for application architecture
And few things that may significantly improve your dev process, but are not so common:
- Spring Reactor (and Webflux) for processing data and requests. Takes a time to learn, but it worth it
- Thymeleaf for UI
- Spock for testing. Highly recommended for designing tests
- Testcontainers for integration tests
- Micrometer to see what's going on with your app. I.e., to export all internal metrics to use with Prometheus/Grafana/etc
For the environment
- SDKMan to manager the environment
- Gradle Application plugin or Google's Jib to pacakge your app. First prepares a Zip with all binaries, second a Docker container
- IntelliJ IDEA
- Github Actions - turns out to be the most usable CI. Though the Jetbrains TeamCity may be better for a large team
farmerbb|3 years ago
Considering Kotlin is a supported, first-class language on Android, why not write your shared libs in Kotlin as well?
gavinray|3 years ago
- API Layer: Quarkus (most projects https://github.com/quarkusio/quarkus), Vert.x (small projects https://vertx.io/)
- DB: Postgres, in-memory H2 for simple stuff
- Testing: JUnit 5, Testcontainers to automatically start + stop DB Docker containers with tests (https://www.testcontainers.org)
- Mocking: Mockito (https://github.com/mockito/mockito) or Mockk (Kotlin, https://mockk.io)
- Dependency Injection: CDI (built into Quarkus, for Vert.x you can initalize Weld when the app starts https://weld.cdi-spec.org)
- Build tool: Gradle with Kotlin DSL
- Other tools:
stickfigure|3 years ago
* IDEA
* Deploy on Google App Engine, Digital Ocean App Platform, Heroku, Elastic Beanstalk, etc - get out of the ops business entirely.
* Guice as the backbone, no Spring/Boot. I wrote a tiny dropwizard-like "framework" to make this easier: https://github.com/gwizard/gwizard but there's a laughable amount of code here, you could build it all from scratch with minimal effort. This is about as lightweight as "frameworks" get because Guice does the heavy lifting.
* JAX-RS (Resteasy) for the web API. IMO this is the best part of Java web development. HTTP endpoints are simple synchronous Java methods (with a few annotations) and you can test them like simple Java methods.
* Lombok. Use @Value heavily. Cuts most of the boilerplate out of Java.
* Junit5 + AssertJ. (Or Google Truth, which is almost identical to AssertJ).
* Use functional patterns. Try to make all variables and fields final. Use collection streams heavily. Consider vavr.io (I'll admit I haven't used it in anger yet, but I would in a new codebase).
* StreamEx. Adds a ton of useful stream behavior; I don't even use basic streams anymore.
* Guava. There's just a lot of useful stuff here.
* For the database, it really depends on what you're building. Most generic business apps, postgres/hibernate/guice-persist/flyway. Yeah, folks complain about hibernate a lot but it's a decent way to map to objects. Use SQL/native queries, don't bother with JPQL, criteria queries, etc.
* Hattery for making http requests (https://github.com/stickfigure/hattery). This is another one of mine. I make zillions of http requests, functional/immutable ergonomics really matter to me.
* Github actions for CI.
* Maven for the build. Yes, it's terrible, except for every other build system is worse. Gradle seems like it should be better but isn't. I'd really love some innovation here. Sigh.
smorgusofborg|3 years ago
On guice/gwizard/maven, if I understand correctly I would be defining new guice DI for something like a message broker (and gwizard's solutions for similar modules might serve as a template) while probably just using direct dependencies in maven for something that doesn't need to be mocked in unit tests or replaceable in production?
ta988|3 years ago
That would be a "modern" stack for me. If you can't use Kotlin, Java has improved a lot since 1.6 you will be pleasantly surprised.
I recommend you start an intellij (Free edition if you want to, even if I still recommend the paid one) and follow the springboot kotlin tutorial below. That will give you a good idea of what the ecosystem looks like these days.
https://spring.io/guides/tutorials/spring-boot-kotlin/
ta988|3 years ago
MockObject|3 years ago
* IntelliJ
* Standard enterprise Java JEE 9.1 (JSP, JPA, EJB)
* Payara app server
* Twitter Bootstrap
* Maven
* Test driven development using TestNG + AssertJ
* Postgres + Liquibase for schema management
Code samples now come from https://www.baeldung.com/
ytdytvhxgydvhh|3 years ago
PaulHoule|3 years ago
I haven’t been paid to work with Spring since 2013, every project I’ve worked on since has used Guice, maybe Dropwizard.
JAX-RS is the dominant paradigm for web back ends these days, particularly if you are writing single page applications.
jbellis|3 years ago
mhaberl|3 years ago
This is the opposite of my experience. I worked with Java a lot for the last 10 years or so. In the last 3 years literally each request I got for implementing stuff in Java also required Spring (Spring Boot) - and that was dozens of clients.
shaman1|3 years ago
Lombok
Gradle, Guava
JUnit 5, testcontainers, WireMock
Logback, Slf4j
Okhttp, Open Feign, RestTemplate
Micrometer
OpenApi, swagger
Liquidbase, jooq - db stuff
This is your run of the mill stack
Dropwizard, Vert.X seem to be less used nowadays, Spring has mostly won the show
Heard people using Kotlin, Quarkus, Micronaut but that's niche stuff
AtlasBarfed|3 years ago
IntelliJ for IDE (Community edition is free). #1 reason is it supports Kotlin and Groovy very well out of the box. Eclipse is still a plugin disaster, and the language support aside from Java is pretty bad, although I haven't bothered to check in a few years since IntelliJ CE was released.
Gradle for builds. It is still copy and paste setup, but at least you can do a lot more things than rigid Maven.
Groovy + CompileStatic (personally) for the actual JVM language but admittedly I haven't tried Kotlin yet. Even with closures and other improvements, base Java can't compete with either of those.
Spring Boot for your enterprisey stuff/REST services which you are likely using it for. It's such a standard at this point.
Unit tests: Spock. Spock is awesome. And very well supported by IntelliJ for autoformat, another BIG reason to use IntelliJ.
Man, web frameworks on Java that don't just use it for an AJAX service layer? Who knows.
soco|3 years ago
AssertErNullNPE|3 years ago
biehl|3 years ago
manishsharan|3 years ago
mhaberl|3 years ago
For context I do a lot of contract work mostly in banking, ecommerce and insurance.
arez|3 years ago
kyawzazaw|3 years ago
smallerfish|3 years ago
If I was starting a new project I'd look at Jooby, which looks pleasant and does very well on TechEmpower benchmarks.
icedchai|3 years ago
jbellis|3 years ago
ETA: actually if you haven't used it since 1.6 you'd want to find an article on Java 8 as well that covers Streams.
vollmond|3 years ago
* Latest JDK
* Spring Boot
* JQuery/Bootstrap
* Eclipse (with Vim keybindings plugin)
Caveats:
* If it was a personal project or only a very small team, I'd start with Kotlin
* I haven't tried IntelliJ in quite a while and would give it a shot to see if I wanted to switch off Eclipse now
luciusdomitius|3 years ago
nigerian1981|3 years ago
throwaway4good|3 years ago
So maybe the frontend and deployment has changed. The rest probably not so much.
Java versions 8 and 11 are by far the most common.
Lambdas were introduced in version 8.
throwaway4good|3 years ago
cimi_|3 years ago
fulafel|3 years ago
The years long constant stream of deserialization vulnerabilities, like yesterday's Spring RCE, are also largely absent from other JVM languages.
rvcdbn|3 years ago
KronisLV|3 years ago
Nothing else seems to come close, they have a Community version, nowadays Eclipse and NetBeans both feel slow but Visual Studio Code with Java plugins lacks refactoring abilities one might expect in an IDE for non-trivial projects. Also, if you get the Ultimate package of their tools, you get all sorts of other useful tools, personally i also enjoy WebStorm and DataGrip for developing front end stuff and working with databases in a separate tool.
JDK: whatever the LTS release of JDK is at the time, based on the kind of work that i do (so JDK 17 now) https://adoptium.net/
As long as you're not stuck with JDK 8, you should be fine in regards to this. But you can definitely enjoy some speed improvements across the releases as well as new language features as well as things like helpful NullPointerException messages. Personally, i'd sometimes also look towards OpenJ9 as an alternate runtime (due to lower memory usage), but that project's future isn't very clear (at least in regards to available container images) last i checked.
As for frameworks, pick one of the following:
In practice, you're most likely to see Spring Boot in existing projects since it's so boring and dependable, though perhaps sometimes you'll also run into the legacy Spring framework (which can be a pain to deal with) or even some of the other ones.Here's a rough performance comparison if you care about that sort of stuff: https://www.techempower.com/benchmarks/#section=data-r20&hw=...
Build tools: personally, i just use whatever Docker images to base the apps on when available and something like Ansible when not. For the actual toolchain, Maven is still pretty dependable, i guess Gradle is also okay. You might occasionally run into tools like Bazel or Jib, experiences there might vary.
App servers: if you need an application server for some reason (e.g. deploy app as .war), Tomcat is still a good option. If you need the EE functionality (e.g. Java EE which is now Jakarta Java), you might need to reach for something like TomEE or Payara Server, though i haven't needed to do that for a few years at this point, since Spring Boot embeds Tomcat and that is good enough for almost all projects.
tralarpa|3 years ago
After not using Eclipse for 10 years, I had to use it again last month for a very large existing project. I was pleasantly surprised. It felt faster than IntelliJ.
mnkmnk|3 years ago
valbaca|3 years ago
Anything new is at least on 11 and 17 where possible.
itpragmatik|3 years ago
- Java 17
- SpringBoot 2.6.x
- Hibernate
- Maven
- MySQL or Postgres
- Liquibase
- Swagger/OpenAPI
- Docker
seymon|3 years ago
omgmajk|3 years ago
sgt|3 years ago
watwut|3 years ago
darksaints|3 years ago
Hardik_Shah|3 years ago
soco|3 years ago
ActorNightly|3 years ago
The standard ecosystem setup is to use all the major 3p libraries for all your functionality (Jaxrs, swagger, log4j, jersey, e.t.c) While this generally works, the ecosystem is full of holes (like log4j), and crappy behavior. You get things like "javax.ws.rs.ProcessingException: Already connected", exceptions which mask underlying issues like not being able to find the endpoint, or SSL certificate error, mainstream clients for things like Redis having issues with multiple connections and unable to switch to master nodes, and so on.
The core language itself is very "dirty" (Integer vs int, requiring a class for the main function, e.t.c). The standard way annotation processors add functionality is to basically write out java files, (or in the case of the ever so popular Lombok, they hack the AST). Because of how annotation processors are run, often times an error during annotation processing with dependency injection will result in very cryptic errors, often about things that were working before that you didnt change.
And on top of everything, jdb debugger is pure garbage, forcing you to use bloated software like IntelliJ for any decent functionality.
Yes, you can learn the ecosystem and its idiosyncrasies, or you could just write the thing in Python or Node with a much more efficient workflow. Network latencies dominate the processing speed these days, and infrastructure is cheap compared to developer time.
haveyoubeen|3 years ago
dgb23|3 years ago
I want to see data on this. It gets repeated over and over but this doesn't match my experience at all. Am I crazy?