Flexible and lightweight pipeline implementation for Java 11+, inspired by ASP.NET middleware design.
- Fluent API to build conditional and nested middleware pipelines
- Supports synchronous, asynchronous, and unified task consumers
- Zero-overhead design suitable for high-performance scenarios
- Clear separation between middleware (TaskConsumer) and terminal tasks (Task)
- Conditional branching with
addWhen
(like ASP.NET UseWhen) andmapWhen
(like ASP.NET MapWhen) - Easy integration with Java CompletableFuture for async execution
- Java 11 or higher
- Maven or Gradle build system
dependencies {
implementation group: 'com.github.romanqed', name: 'jconv', version: '2.0.0'
}
<dependency>
<groupId>com.github.romanqed</groupId>
<artifactId>jconv</artifactId>
<version>2.0.0</version>
</dependency>
import com.github.romanqed.jconv.TaskBuilders;
public class Main {
public static void main(String[] args) throws Throwable {
var builder = TaskBuilders.<Integer>linked();
var pipeline = builder
.add((c, next) -> {
System.out.println("{ - 1");
next.run(c);
System.out.println("} - 4");
})
.add((c, next) -> {
System.out.println(c + " - 2");
next.run(c - 1);
})
.add((c, next) -> {
System.out.println(c + " - 3");
})
.build();
pipeline.run(10);
}
}
Output:
{ - 1
10 - 2
9 - 3
} - 4
import com.github.romanqed.jconv.TaskBuilders;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws Throwable {
var builder = TaskBuilders.<Object>linked();
var pipeline = builder
.add((ctx, next) -> {
try {
next.run(ctx);
} catch (IOException e) {
System.out.println("Caught IOException:");
e.printStackTrace();
}
})
.add((ctx, next) -> {
throw new IOException("Simulated I/O error");
})
.build();
pipeline.run(null);
}
}
Output:
Caught IOException:
java.io.IOException: Simulated I/O error
at Main.lambda$main$1(Main.java:...)
...
import com.github.romanqed.jconv.TaskBuilders;
public class Main {
public static void main(String[] args) throws Throwable {
var builder = TaskBuilders.<Integer>linked();
var pipeline = builder
.add((c, next) -> {
if (c > 0) {
next.run(c);
} // else short-circuit: do nothing, next tasks won't run
})
.add((c, next) -> {
System.out.println("Processed: " + c);
})
.build();
pipeline.run(5); // Prints "Processed: 5"
pipeline.run(0); // Prints nothing
}
}
var pipeline = TaskBuilders.<String>linked()
.addWhen(s -> s.startsWith("admin"), b -> {
b.add((s, next) -> {
System.out.println("Admin branch: " + s);
next.run(s);
});
})
.add((s, next) -> {
System.out.println("Common branch: " + s);
})
.build();
pipeline.run("adminUser"); // Prints both Admin branch and Common branch messages
pipeline.run("guestUser"); // Prints only Common branch message
var pipeline = TaskBuilders.<String>linked()
.mapWhen(s -> s.startsWith("admin"), (s) -> {
System.out.println("Admin mapped branch: " + s);
})
.add((s, next) -> {
System.out.println("Common branch: " + s);
})
.build();
pipeline.run("adminUser"); // Prints only Admin mapped branch message
pipeline.run("guestUser"); // Prints only Common branch message
Note: mapWhen
replaces the pipeline if condition is true, short-circuiting subsequent middleware.
- Task — terminal unit of work (sync, async or unified)
- TaskConsumer — middleware consumer that can delegate downstream
- TaskConfigurer — fluent interface for building pipeline steps
- TaskBuilder — interface to assemble and build pipelines
- TaskBuilders — factory for creating pipeline builders (e.g., linked)
- Gradle - Dependency management
- jfunc - Functional interfaces and utilities
- jsync - Async functional interfaces and helpers
- juni - Unified sync/async interfaces
- RomanQed - Main author
See also the list of contributors who participated in this project.
This project is licensed under the Apache License 2.0 — see the LICENSE file for details