A Java library of functional types that make failures, absence, and validation explicit in the type system — without ceremony.
Option<T>, Result<V, E>, Try<V>, Validated<E, A>, Either<L, R>, Lazy<T>, Tuple2/3/4, NonEmptyList<T>, NonEmptyMap<K, V>, NonEmptySet<T>, Guard<T>, Resource<T>, and Accumulator<E, A> — each designed to compose cleanly with the others and with the Java standard library.
All modules are published to Maven Central. Add only what you need.
Replace LATEST_VERSION with the version shown in the badge above.
Import fun-bom once and omit the version from every individual module declaration.
Maven
<dependencyManagement>
<dependencies>
<dependency>
<groupId>codes.domix</groupId>
<artifactId>fun-bom</artifactId>
<version>LATEST_VERSION</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>codes.domix</groupId>
<artifactId>fun</artifactId>
</dependency>
<dependency>
<groupId>codes.domix</groupId>
<artifactId>fun-jackson</artifactId>
</dependency>
</dependencies>Gradle (Kotlin DSL)
dependencies {
implementation(platform("codes.domix:fun-bom:LATEST_VERSION"))
implementation("codes.domix:fun")
implementation("codes.domix:fun-jackson") // no version needed
}Maven
<dependency>
<groupId>codes.domix</groupId>
<artifactId>fun</artifactId>
<version>LATEST_VERSION</version>
</dependency>Gradle
implementation("codes.domix:fun:LATEST_VERSION")Serializers and deserializers for all dmx-fun types.
Maven
<dependency>
<groupId>codes.domix</groupId>
<artifactId>fun-jackson</artifactId>
<version>LATEST_VERSION</version>
</dependency>Gradle
implementation("codes.domix:fun-jackson:LATEST_VERSION")Transaction support for Result, Try, Option, and Validated — use dmx-fun idiomatically without giving up @Transactional. Spring Framework is declared as compileOnly; bring your own Spring dependency.
Maven
<dependency>
<groupId>codes.domix</groupId>
<artifactId>fun-spring</artifactId>
<version>LATEST_VERSION</version>
</dependency>Gradle
implementation("codes.domix:fun-spring:LATEST_VERSION")Fluent custom assertions for all dmx-fun types.
Maven
<dependency>
<groupId>codes.domix</groupId>
<artifactId>fun-assertj</artifactId>
<version>LATEST_VERSION</version>
<scope>test</scope>
</dependency>Gradle
testImplementation("codes.domix:fun-assertj:LATEST_VERSION")Automatic counters, timers, and failure metrics for Try and Result operations. Micrometer is declared as compileOnly; bring your own version (1.5.x – 1.16.x) and backend.
Maven
<dependency>
<groupId>codes.domix</groupId>
<artifactId>fun-micrometer</artifactId>
<version>LATEST_VERSION</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.16.5</version>
</dependency>Gradle
implementation("codes.domix:fun-micrometer:LATEST_VERSION")
implementation("io.micrometer:micrometer-core:1.16.5")Validates objects and returns Validated<NonEmptyList<E>, A> instead of throwing ConstraintViolationException — all constraint violations accumulate in a single return value. Jakarta Validation is declared as compileOnly; bring your own version (tested: 3.0.x – 3.1.x) and provider.
Maven
<dependency>
<groupId>codes.domix</groupId>
<artifactId>fun-jakarta-validation</artifactId>
<version>LATEST_VERSION</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.1.1</version>
</dependency>
<!-- A Jakarta Validation provider, e.g. Hibernate Validator: -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>9.1.0.Final</version>
</dependency>Gradle
implementation("codes.domix:fun-jakarta-validation:LATEST_VERSION")
implementation("jakarta.validation:jakarta.validation-api:3.1.1")
implementation("org.hibernate.validator:hibernate-validator:9.1.0.Final")Adapters for Retry, CircuitBreaker, RateLimiter, and Bulkhead that return Try or Result instead of throwing exceptions. Resilience4J is declared as compileOnly; bring your own version (tested: 2.0.2–2.4.0).
Maven
<dependency>
<groupId>codes.domix</groupId>
<artifactId>fun-resilience4j</artifactId>
<version>LATEST_VERSION</version>
</dependency>
<!-- Add the Resilience4J artifacts you use, e.g. (replace RESILIENCE4J_VERSION with the actual version): -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-retry</artifactId>
<version>RESILIENCE4J_VERSION</version>
</dependency>Gradle
implementation("codes.domix:fun-resilience4j:LATEST_VERSION")
// Add the Resilience4J artifacts you use, e.g. (replace RESILIENCE4J_VERSION with the actual version):
implementation("io.github.resilience4j:resilience4j-retry:RESILIENCE4J_VERSION")| Type | Tag | When to use |
|---|---|---|
Option<T> |
Nullability | A value that may or may not be present. The null-safe alternative to @Nullable. |
Result<V, E> |
Error handling | An operation that can succeed or fail with a typed error. |
Try<V> |
Exception handling | Wraps a computation that may throw. Turns exceptions into values. |
Validated<E, A> |
Validation | Like Result but accumulates all errors instead of failing on the first. |
Either<L, R> |
Disjoint union | A value that is one of two types with no success/failure semantics. |
Lazy<T> |
Deferred computation | A value computed at most once, on first access. Thread-safe memoization. |
Tuple2/3/4 |
Product types | Typed heterogeneous tuples without a dedicated class. |
NonEmptyList<T> |
Collections | A list guaranteed to have at least one element at compile time. |
NonEmptyMap<K,V> |
Collections | A map guaranteed to have at least one entry at compile time. Insertion order preserved. |
NonEmptySet<T> |
Collections | A set guaranteed to have at least one element at compile time. No duplicates, insertion order preserved. |
Guard<T> |
Validation | A composable, named predicate that produces a Validated result — the reusable building block for validation pipelines. |
Resource<T> |
Resource management | A composable managed resource: acquire, use, and release with a guaranteed cleanup. |
Accumulator<E, A> |
Tracing | A value paired with a side-channel accumulation (log, metrics, audit trail). Threads cross-cutting concerns through pure computation chains without shared mutable state. |
import dmx.fun.Result;
import dmx.fun.Try;
import dmx.fun.Validated;
import dmx.fun.NonEmptyList;
// Wrap a legacy API that throws
Try<RawUser> raw = Try.of(() -> externalService.fetchUser(id));
// Convert to Result for typed error handling
Result<User, RegistrationError> user = raw
.toResult(e -> RegistrationError.fetchFailed(id, e))
.flatMap(this::parseUser)
.flatMap(this::enrichWithDefaults);
// Validate all fields at once — accumulate every error, not just the first
Validated<NonEmptyList<String>, ValidUser> validated = user
.map(this::validate)
.getOrElse(Validated.invalidNel("user could not be loaded"));
validated
.onValid(userRepository::save)
.onInvalid(errors -> log.warn("Registration rejected: {}", errors));Full developer guide, API reference, and composition patterns: https://domix.github.io/dmx-fun/
- Java 25 or later
Bug reports, feature requests, and pull requests are welcome. Please open an issue before submitting a large change.
Apache License 2.0 — see LICENSE for details.