Blog

Articles, tutorials, and insights about functional programming in Java

Subscribe via RSS
ArticleLatest Post

Stream Gatherers: Custom Intermediate Operations in Modern Java

For a decade the Stream API let you write your own terminal operation with Collector — but the middle of the pipeline was a closed shop of filter, map, and a handful of others. Gatherers, final since Java 24, open it up: a standard way to write stateful, short-circuiting, even concurrent intermediate operations. Here is how they work and when to reach for one.

Latest Articles

Functional Concurrency: Structuring Parallel Work Without Shared State

Concurrency's bad reputation is really shared mutable state's reputation. Structure parallel work the functional way — immutable inputs, pure tasks, outcomes as values, and a join step that combines results instead of threads fighting over an accumulator — and most of the classic hazards stop being representable.

Where to Put Validation: At the Boundary, Not in the Core

Scattered validation is a symptom of a missing decision: nobody agreed where checking ends and trust begins. Validate once, at the edge of the system, and convert raw input into types that carry the proof — so the core never has to check again. Here is the architecture, and the line between input validation and domain rules that makes it work.

Functional Programming in Java Without Losing Pragmatism

Adopting functional programming in Java goes wrong when you try to turn Java into Haskell. Done pragmatically, it is a handful of concrete habits that fit the language you already have — records, sealed types, the JDK — and pay off on the first bug they prevent. Here is how to get the benefits without the dogma.

Why 'Just Use Exceptions' Persists, and When It Is Actually Right

Every functional programming pitch eventually collides with a senior engineer saying 'just use exceptions.' That advice is not ignorance — exceptions win real trade-offs, and there are cases where they are genuinely the right tool. Here is an honest map of where each belongs.

Functional Thinking for Backend Engineers

Functional thinking is not about monads or category theory. For backend engineers it is a practical shift: model the things a service actually deals with — missing rows, failed calls, invalid input, side effects — as ordinary values you can pass, compose, and let the compiler check.

Domain-Driven Design and Functional Programming: Allies or Rivals?

DDD is often taught with rich objects and mutable aggregates, while functional programming preaches immutability and pure functions. The tension is real on the surface — but the tactical patterns of DDD and the tools of FP turn out to be the same idea from two directions. Here is where they meet.

dmx-fun 0.2.0 — Reactive, and One Year Old

0.2.0 is dmx-fun's first-anniversary release: two new reactive modules — fun-reactor (Project Reactor interop) and fun-spring-webflux (Spring WebFlux adapters) — plus a year of 17 releases building a functional programming ecosystem for Java backends.

Validated: Accumulating Errors in a Functional Way

Most error handling reports the first failure and stops. A registration form, an API request, a config file — these need every problem at once, not one round-trip per mistake. Validated is the type that collects all errors instead of short-circuiting, and the reason it works comes down to one deep idea: independent checks compose differently from dependent ones.

Closures and Variable Capture Explained for Java Developers

Java developers use closures every time they write a lambda that references a variable from the surrounding method — usually without naming what they are doing. This post explains what a closure actually is, what 'effectively final' really means and why the rule exists, and the capture pitfalls that bite people in loops and shared state.