Skip to content

domix/dmx-fun

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

709 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

dmx-fun

image

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.


Installation

All modules are published to Maven Central. Add only what you need.

Module Latest version Description
fun-bom Maven Central Bill of Materials — import once to manage all dmx-fun versions in one place.
fun Maven Central Core library. Option, Result, Try, Validated, Either, Lazy, Tuple, NonEmptyList/Map/Set, Guard, Resource, Accumulator.
fun-jackson Maven Central Jackson serializers and deserializers for all dmx-fun types.
fun-assertj Maven Central Fluent AssertJ assertions for all dmx-fun types. Use in test scope.
fun-spring Maven Central @Transactional support for Result, Try, Option, and Validated.
fun-spring-boot Maven Central Spring Boot auto-configuration for dmx-fun. Registers beans automatically when dependencies are on the classpath.
fun-resilience4j Maven Central Resilience4J adapters (Retry, CircuitBreaker, RateLimiter, Bulkhead) that return Try/Result instead of throwing.
fun-micrometer Maven Central Counters, timers, and failure metrics for Try and Result via Micrometer.
fun-jakarta-validation Maven Central Jakarta Validation adapter — returns Validated<NonEmptyList<E>, A> instead of throwing ConstraintViolationException.

Replace LATEST_VERSION with the version shown in the badge above.

Using the BOM (recommended when using multiple modules)

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
}

Core library

Maven

<dependency>
    <groupId>codes.domix</groupId>
    <artifactId>fun</artifactId>
    <version>LATEST_VERSION</version>
</dependency>

Gradle

implementation("codes.domix:fun:LATEST_VERSION")

Jackson integration (optional)

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")

Spring integration (optional)

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")

AssertJ integration (optional, test scope)

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")

Micrometer integration (optional)

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")

Jakarta Validation integration (optional)

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")

Resilience4J integration (optional)

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")

Types

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.

Quick example

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));

Documentation

Full developer guide, API reference, and composition patterns: https://domix.github.io/dmx-fun/


Requirements

  • Java 25 or later

Contributing

Bug reports, feature requests, and pull requests are welcome. Please open an issue before submitting a large change.


License

Apache License 2.0 — see LICENSE for details.

About

dmx-fun is a Java library that makes failures, absence, and validation explicit in the type system.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Packages

 
 
 

Contributors