An exploration of modern Java API development by building a non-trivial app with DDD-esque structuring.
Explores:
- Micronaut web framework
- OpenApi
- Gradle
- Subprojects
- Configuring dependency constraints
- Lombok for immutable data structures
- Functional Java for some FP data structures (
Either
) - MapStruct for compile-time-safe mapping between data types
- Gaal native image generation
- Spotless for enforcing style
- JaCoCo for test coverage
- OpenApi at localhost:8080/swagger-ui
- RapiDoc at localhost:8080/rapidoc
The are various ways to run this (consult the Micronaut docs), but I've verified the following 2.
./gradlew check run
./gradlew build assemble && ./docker-build.sh
docker run -p 8080:8080 todddo-openapi-java
(marvel at the sub 100ms start time)
- Haven't benchmarked, but seems to be quite quick to boot and comes with support for a lot of things:
- OpenAPI
- DI
- GraalVM
- A decent attempt at nice immutable data types, but still, not quite close to modern languages like Scala or Kotlin.
- Generally better than what I remember it to be from doing Java 10+ years ago
- Micronaut does a great job of trying to make sure things are safe, but:
- Things still break at runtime with certain injections and runtime-reflection based tooling, especially when running them in Graal Native
- Java still has a ways to go when it comes to making types ergonomic (unchecked types...)
- It took a lot of trial and error to get things like reflection-based tools (Jackson, DI) working just right, and to
figure out how to get Swagger resources working (refer to the
native-image.properties
file).
- Jackson is still yucky compared to any modern JSON tool in Scala, Rust, Haskell, etc. In fact, it's even worse than Go because the tooling is all reflection based, which means you really have to be careful when trying to use it with Graal. It took me quite a while to figure out how to appease it.
- Java is still pushing me to use Exceptions for error control flow, but you can get around it with libs like Functional Java.