The Fluxtion compiler generates an event processor from a model supplied by the client. A model represents the set of user classes
that are bound into the event processor. This section documents the various ways the model can be created by the developer.
EventProcessorConfig is the class that acts as the model,
a number of options are available for adding user classes to an EventProcessorConfig instance:
Imperative api
Functional dsl api
Spring based
Yaml based
These examples use Fluxtion.interpret which executes the event processor as an in-process interpretation, the
available output types of the generated event processor are described in Processor generation.
The source project for the examples can be found here
Imperative model building
Call one of the static Fluxtion Fluxtion build methods with a
Consumer<EventProcessorConfig>. User classes are bound into the model by invoking methods on the supplied
EventProcessorConfig instance in the consumer. Fluxtion implicitly creates the EventProcessorConfig instance, which is then passed into the generator.
Only nodes in the model that are annotated with a fluxtion annotation are bound into an event processor
Imperatively add a node
Bind an instance of MyNode into the supplied EventProcessorConfig using Fluxtion.interpret(cfg -> cfg.addNode(new MyNode())).
Output
Imperatively add multiple nodes
Bind multiple object instances into the model.
Output
Implicitly adding nodes
imperatively added instances are root nodes for the model. The references of a node are recursively analysed, if a
reference points to an instance that has a fluxtion annotation that node is added to the model implicitly. Any implicitly
added node will be analysed for implicitly adding more nodes, and so on recursively.
Output
Varargs adding nodes
Add root nodes to the model using the varargs derivative of Fluxtion builder method. Can be useful if no customisation
of the model is needed and only nodes need to be included in the generated processor.
Output
Adding shared references
If two nodes point to a shared instance, that instance will only be added once to the model. The shared node will
trigger both children when propagating event notification.
Output
Adding references that are equal
The model acts like a set, checking equality when a node is added imperatively or implicitly. If the instance to add is
equal to a node already in the model it is substituted so only one instance is in the model. References to the duplicate
will be re-directed to point at the existing node.
Output
Naming nodes
Nodes can be given a name when they are added to the graph, if a node has been previously added with the same name the
generation process will fail with a name clash. A node can be accessed by calling EventProcessor.getById. There are
two ways to give a node an addressable identifier:
Implement the Named interface on a bound node
Call EventProcessorConfig.addnode with a name as the second argument
Output
Using name as equality
The string name can be used as the equality test removing the need for users to implement custom equals and hashcode
methods. A utility class SingleNamedNode can be extended to
simplify implementation. As equals, hashcode and getName are all synchronised name clashes are avoided and single instance
is in the model. This allows user building code to use name as a key to create a shared reference when building.
Output
Inject a reference
Fluxtion supports injecting a reference with the @Inject annotation, a new instance will be created by the model
with the default constructor and added implicitly to the model. The injected instance will analysed for implicit
nodes to add to the model.
Output
Inject a singleton
Fluxtion supports injecting a singleton reference with the @Inject(singleton = true) annotation, the same reference
is used throughout the model so only one instance is present in the generated processor.
Output
Inject from factory
A factory can supply the injected instance to the model. A user implements the NodeFactory
and returns the instance to the model. Factories can be registered programmatically with EventProcessorConfig but the
easiest method is to use the ServiceLoader pattern to register factories. In this example the google auto service
annotation to remove all the boiler plate code @AutoService(NodeFactory.class).
Configuration key/values can be supplied at the inject site e.g.
@Config(key = "filter", value = "red")
Tuples are wrapped in a map and passed to the NodeFactory.createNode as an argument, the factory creates
custom instances using the map as required.
Output
Add an auditor
An Auditor can be bound into the generated event processor. An
auditor receives meta-data callbacks that allows tracking of the event processing as notifications propagate through
the event processor. Implement the Auditor interface and bind it in the processor with:
cfg.addAuditor(new MyAuditor(), "myAuditor")
Output
Exclude a node from binding
A user node can be excluded from binding into the model by adding the annotation @ExcludeNode on a user class. An
excluded class can be used as a holder for complex construction logic when the user does not want to use a NodeFactory.
Output
Inject runtime instance
Instances can be injected at runtime to a node using the @Inject(instanceName = "startData") annotation on a
InstanceSupplier data member. The instance has to be injected at
runtime to a built event processor before calling init with:
Instances can be updated once the processor is running by injecting a new instance with the same name.
Output
Functional model building
Fluxtion supports binding functions into the event processor using functional programming. The DataFlow class
provides static method that subscribe to events. Once a flow has been built map/filter/grouping functions can be applied
as chained calls. The flow must be built within the Fluxtion build method,
DataFlow will add all the functions and classes to the model automatically.
Bind functions to events
To bind functions to a flow of events the subscription must first be created with:
DataFlow.subscribe([event class])
A lambda or a method reference can be bound as the next item in the function flow. A full description of the functional
api is in Functional programming
Output
Bind instance functions
Instance functions can be bound into the event processor using method references
Output
Combining imperative and functional binding
Both imperative and functional binding can be used in the same build consumer. All the user classes and functions will
be added to the model for generation.
Output
Build with spring configuration
Spring configuration is natively supported by Fluxtion. Any beans in the spring ApplicationContext will be bound into
the model and eventually the generated event processor. Pass the spring ApplicationContext into fluxtion with