Skip to content

Fluxtion Quickstart

This guide introduces Fluxtion through a series of progressively more capable examples. Each example adds new behaviour while the amount of orchestration code stays almost constant.

Fluxtion infers the execution pipeline from the relationships between components at compile time, so developers only write the business logic.


Install JBang

Examples use JBang so they can run without creating a full project.

Install JBang:

# macOS / Linux
curl -Ls https://sh.jbang.dev | bash

# Windows (powershell)
iex "& { $(iwr https://ps.jbang.dev) }"

More details: https://www.jbang.dev


Generation is remote and needs an API key

Building a graph (DataFlowBuilder...build(), interpret(), Fluxtion.compile* / compileAot or the fluxtion-maven-plugin) sends the graph model - not your source files - to the hosted Fluxtion generator by default, and needs an API key. Without a key the build stops before sending anything ("Fluxtion API key is not configured"); a rejected key fails with HTTP 401/403. Put the key in ~/.fluxtion/fluxtion.apiKeyFile as apiKey=YOUR_KEY (the first build creates the file). A generated processor runs with fluxtion-runtime alone and makes no network call. How to get a key: Getting an API key (subscribe to "Fluxtion Source Generator" on RapidAPI).

1. Hello world

Create a simple event pipeline.

//REPOS mavencentral,fluxtion=https://repo.repsy.io/mvn/fluxtion/fluxtion-public
//DEPS com.telamin.fluxtion:fluxtion-builder:1.0.81
//JAVA 25

import com.telamin.fluxtion.builder.DataFlowBuilder;
import com.telamin.fluxtion.runtime.DataFlow;

void main() {
    DataFlow dataFlow = DataFlowBuilder
            .subscribe(String.class)
            .map(String::toUpperCase)
            .console("msg:{}")
            .build();

    dataFlow.onEvent("hello");
    dataFlow.onEvent("world");
}

Run:

jbang hello.java

Output:

msg:HELLO
msg:WORLD
Fluxtion automatically determines the execution order for the pipeline and generates the runtime event processor.


2. Streaming analytics

Compute a sliding window average from a real-time event stream.

//REPOS mavencentral,fluxtion=https://repo.repsy.io/mvn/fluxtion/fluxtion-public
//DEPS com.telamin.fluxtion:fluxtion-builder:1.0.81
//JAVA 25

import com.telamin.fluxtion.builder.DataFlowBuilder;
import com.telamin.fluxtion.runtime.DataFlow;
import com.telamin.fluxtion.runtime.flowfunction.helpers.Aggregates;

import java.util.Random;

record CarTracker(String id, double speed) { }

void main() throws InterruptedException {
    // 5 buckets of 200ms = 1 second sliding window
    DataFlow averageCarSpeed = DataFlowBuilder
            .subscribe(CarTracker::speed)
            .slidingAggregate(Aggregates.doubleAverageFactory(), 200, 5)
            .map(v -> "average speed: " + v.intValue() + " km/h")
            .sink("average car speed")
            .build();

    averageCarSpeed.addSink("average car speed", System.out::println);

    Random random = new Random();

    for (int i = 0; i < 100; i++) {
        averageCarSpeed.onEvent(
                new CarTracker("car-" + (i % 5), random.nextInt(100)));
        Thread.sleep(random.nextInt(100));
    }
}

Run:

jbang streamingAnalytics.java

Output:

average speed: 45 km/h
average speed: 41 km/h
average speed: 42 km/h
average speed: 45 km/h
average speed: 47 km/h
average speed: 55 km/h
average speed: 58 km/h
average speed: 63 km/h
average speed: 61 km/h
average speed: 56 km/h
average speed: 55 km/h

Fluxtion maintains the sliding window and automatically triggers downstream calculations.


3. Stateful node example

Fluxtion integrates directly with ordinary Java objects.

//REPOS mavencentral,fluxtion=https://repo.repsy.io/mvn/fluxtion/fluxtion-public
//DEPS com.telamin.fluxtion:fluxtion-builder:1.0.81
//JAVA 25

import com.telamin.fluxtion.builder.DataFlowBuilder;
import com.telamin.fluxtion.runtime.DataFlow;
import com.telamin.fluxtion.runtime.annotations.OnEventHandler;

void main() {
    DataFlow flow = DataFlowBuilder
            .subscribeToNode(new StatefulNode())
            .map(StatefulNode::getValue)
            .console("value:{}")
            .build();

    flow.onEvent("A");
    flow.onEvent("B");
    flow.onEvent("C");
    flow.onEvent("D");
    flow.onEvent("E");
    flow.onEvent("F");
}

public class StatefulNode {

    private String value;

    @OnEventHandler
    public boolean update(String input) {
        value = input;
        return true;
    }

    public String getValue() {
        return value;
    }
}

Run:

jbang statefulNode.java

Output:

value:A
value:B
value:C
value:D
value:E
value:F

Stateful objects participate directly in the event graph.


4. Multi‑feed event system

Real systems often combine multiple event streams. Fluxtion can also combine multiple event streams using joins.

//REPOS mavencentral,fluxtion=https://repo.repsy.io/mvn/fluxtion/fluxtion-public
//DEPS com.telamin.fluxtion:fluxtion-builder:1.0.81
//JAVA 25

import com.telamin.fluxtion.builder.DataFlowBuilder;
import com.telamin.fluxtion.builder.flowfunction.JoinFlowBuilder;
import com.telamin.fluxtion.runtime.DataFlow;
import com.telamin.fluxtion.runtime.flowfunction.groupby.GroupBy;
import com.telamin.fluxtion.runtime.flowfunction.helpers.Tuples;

import java.util.List;
import java.util.stream.Collectors;

public record Pupil(int year, String school, String name) {
}

public record School(String name) {
}

void main(String[] args) {
    var pupils = DataFlowBuilder.subscribe(Pupil.class).groupByToList(Pupil::school);
    var schools = DataFlowBuilder.subscribe(School.class).groupBy(School::name);

    DataFlow processor = JoinFlowBuilder
            .innerJoin(schools, pupils)
            .mapValues(Tuples.mapTuple(Helper::prettyPrint))
            .map(GroupBy::toMap)
            .console()
            .build();

    //register some schools
    processor.onEvent(new School("RGS"));
    processor.onEvent(new School("Belles"));

    //register some pupils
    processor.onEvent(new Pupil(2015, "RGS", "Bob"));
    processor.onEvent(new Pupil(2013, "RGS", "Ashkay"));
    processor.onEvent(new Pupil(2013, "Belles", "Channing"));
    processor.onEvent(new Pupil(2013, "RGS", "Chelsea"));
    processor.onEvent(new Pupil(2013, "Belles", "Tamsin"));
    processor.onEvent(new Pupil(2013, "Belles", "Ayola"));
    processor.onEvent(new Pupil(2015, "Belles", "Sunita"));
}

public static class Helper{
    public static String prettyPrint(School schoolName, List<Pupil> pupils) {
        return pupils.stream().map(Pupil::name).collect(Collectors.joining(",", "pupils[", "]"));
    }
}

Run:

jbang multiJoin.java

Output:

{}
{}
{RGS=pupils[Bob]}
{RGS=pupils[Bob,Ashkay]}
{Belles=pupils[Channing], RGS=pupils[Bob,Ashkay]}
{Belles=pupils[Channing], RGS=pupils[Bob,Ashkay,Chelsea]}
{Belles=pupils[Channing,Tamsin], RGS=pupils[Bob,Ashkay,Chelsea]}
{Belles=pupils[Channing,Tamsin,Ayola], RGS=pupils[Bob,Ashkay,Chelsea]}
{Belles=pupils[Channing,Tamsin,Ayola,Sunita], RGS=pupils[Bob,Ashkay,Chelsea]}

Fluxtion composes multiple streams while maintaining deterministic execution.


5. Robotics / defence example

Fluxtion is well suited for deterministic control systems such as drones or robotics.

This example reacts to altitude events and triggers a safety warning.

//REPOS mavencentral,fluxtion=https://repo.repsy.io/mvn/fluxtion/fluxtion-public
//DEPS com.telamin.fluxtion:fluxtion-builder:1.0.81
//JAVA 25

import com.telamin.fluxtion.builder.DataFlowBuilder;
import com.telamin.fluxtion.runtime.DataFlow;

record Altitude(double meters) {
}


void main(String[] args) {
    DataFlow droneSafety = DataFlowBuilder
            .subscribe(Altitude::meters)
            .filter(a -> a > 120)
            .map(a -> "WARNING: altitude limit exceeded " + a)
            .console("{}")
            .build();

    // sensor events
    droneSafety.onEvent(new Altitude(80));
    droneSafety.onEvent(new Altitude(95));
    droneSafety.onEvent(new Altitude(140));
}

Run:

jbang altitudeMonitor.java

Output:

WARNING: altitude limit exceeded 140.0

Because the execution graph is deterministic, behaviour can be analysed, tested, and replayed — an important property for safety-critical systems.


Next steps

Now that you have seen how Fluxtion coordinates logic, explore how to run it in a production runtime:

See the Why Fluxtion exists guide for a deeper look at the architecture.