https://github.com/digitalpetri/strict-machine
A declarative DSL for building asynchronously evaluated Finite State Machines on the JVM
https://github.com/digitalpetri/strict-machine
finite-state-machine fsm java state-machine
Last synced: 7 days ago
JSON representation
A declarative DSL for building asynchronously evaluated Finite State Machines on the JVM
- Host: GitHub
- URL: https://github.com/digitalpetri/strict-machine
- Owner: digitalpetri
- License: epl-2.0
- Created: 2018-12-01T02:34:01.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2024-11-08T23:50:10.000Z (5 months ago)
- Last Synced: 2025-03-28T11:35:03.516Z (24 days ago)
- Topics: finite-state-machine, fsm, java, state-machine
- Language: Java
- Size: 125 KB
- Stars: 30
- Watchers: 3
- Forks: 6
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Strict Machine
Strict Machine is a declarative DSL for building asynchronously evaluated Finite State Machines.
Release builds are available from [Maven Central](https://repo.maven.apache.org/maven2/) and SNAPSHOT builds are available from the [Sonatype OSS Snapshot Repository](https://oss.sonatype.org/content/repositories/snapshots/).
## Gradle
```
dependencies {
compile("com.digitalpetri.fsm:strict-machine:1.0.0")
}
```## Maven
```
com.digitalpetri.fsm
strict-machine
1.0.0
```
# What does it look like?
Given this simple ATM example:

Define the State and Event types:
```java
enum State {
Idle,
Loading,
OutOfService,
InService,
Disconnected
}enum Event {
Connected,
ConnectionClosed,
ConnectionLost,
ConnectionRestored,
LoadFail,
LoadSuccess,
Shutdown,
Startup
}
```Define the transitions:
```java
FsmBuilder fb = new FsmBuilder<>();/* Idle */
fb.when(State.Idle)
.on(Event.Connected)
.transitionTo(State.Loading);/* Loading */
fb.when(State.Loading)
.on(Event.LoadSuccess)
.transitionTo(State.InService);fb.when(State.Loading)
.on(Event.LoadFail)
.transitionTo(State.OutOfService);fb.when(State.Loading)
.on(Event.ConnectionClosed)
.transitionTo(State.Disconnected);/* OutOfService */
fb.when(State.OutOfService)
.on(Event.Startup)
.transitionTo(State.InService);fb.when(State.OutOfService)
.on(Event.ConnectionLost)
.transitionTo(State.Disconnected);/* InService */
fb.when(State.InService)
.on(Event.ConnectionLost)
.transitionTo(State.Disconnected);fb.when(State.InService)
.on(Event.Shutdown)
.transitionTo(State.OutOfService);/* Disconnected */
fb.when(State.Disconnected)
.on(Event.ConnectionRestored)
.transitionTo(State.InService);Fsm fsm = fb.build(State.Idle);
```Fire events to be evaluated asynchronously:
```java
fsm.fireEvent(Event.Connected);
```
or block waiting for the state that resulted from evaluating the event:
```java
State state = fsm.fireEventBlocking(Event.Connected);
```# Transition Guards
Guard conditions that prevent a transition from occurring unless they're met can be defined using `guardedBy`:```java
fb.when(State.Idle)
.on(Event.Connected)
.transitionTo(State.Loading)
.guardedBy(ctx -> ...guard condition here...);
```Where the guard provided to `guardedBy` is a `Predicate` that receives the `FsmContext`.
# Transition Actions
Of course, in order for your state machine to actually *do* something, you need to define actions that execute when events are evaluated and transitions occur.
This is accomplished using the `onTransitionTo`, `onTransitionFrom`, and `onInternalTransition` methods on `FsmBuilder`.
For example, logging a message on the transition from `Idle` to `Loading` might be defined in either of two ways:
```java
// define the action in the context of a transition away from Idle
fb.onTransitionFrom(State.Idle)
.to(State.Loading)
.via(Event.Connected)
.execute(ctx -> System.out.println("S(Idle) x E(Connected) = S'(Loading)"));
// define the action in the context of a transition to Loading
fb.onTransitionTo(State.Loading)
.from(State.Idle)
.via(Event.Connected)
.execute(ctx -> System.out.println("S(Idle) x E(Connected) = S'(Loading)"));
```# More Examples
See the full [AtmFsm](https://github.com/kevinherron/strict-machine/blob/master/src/test/java/com/digitalpetri/strictmachine/dsl/atm/AtmFsm.java) defined in the test suite.
Advanced examples from production code:
- [ChannelFsmFactory](https://github.com/digitalpetri/netty-channel-fsm/blob/master/src/main/java/com/digitalpetri/netty/fsm/ChannelFsmFactory.java) from [netty-channel-fsm](https://github.com/digitalpetri/netty-channel-fsm).
- [SessionFsmFactory](https://github.com/eclipse/milo/blob/master/opc-ua-sdk/sdk-client/src/main/java/org/eclipse/milo/opcua/sdk/client/session/SessionFsmFactory.java) from [Eclipse Milo](https://github.com/eclipse/milo).