Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/alfonso-presa/restflow
This project aim is to provide a lightweight state machine library that allows to easily implement bean flows.
https://github.com/alfonso-presa/restflow
Last synced: 3 months ago
JSON representation
This project aim is to provide a lightweight state machine library that allows to easily implement bean flows.
- Host: GitHub
- URL: https://github.com/alfonso-presa/restflow
- Owner: alfonso-presa
- License: mit
- Created: 2015-08-19T14:32:47.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2018-12-06T16:36:22.000Z (about 6 years ago)
- Last Synced: 2024-04-15T00:44:12.509Z (9 months ago)
- Language: Java
- Size: 81.1 KB
- Stars: 10
- Watchers: 4
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[![Build Status](https://travis-ci.org/alfonso-presa/restflow.svg?branch=master)](https://travis-ci.org/alfonso-presa/restflow)
Simple annotation based FSM java library.
## Purpose
This project aim is to provide a lightweight state machine library that allows to easily implement bean flows.
## Features
* Simple one level state machine
* Annotation based flow configuration:
* Guards: prevents an state transition to be executed
* On: executes an action when a transition is executed
* OnState: executes an action when a transition to an state is completed
* Thread safe
* State is stored inside your own bean and never inside the state machine
* When ever you trigger an event you provide the bean over which the FSM should operate.## Sample
Let's say you have to build a REST end point to handle orders. You will like the orders to go through different states, for example:
* Placed
* Payed
* SentThe order should only be able to pass from one state to the next one and only if it satisfies some conditions:
* Placed: it will only be placed if the products and the customer are provided.
* At this point the price should be calculated depending on the products.
* Payed: it can only get payed if a valid payment recipe is provided.
* Sent: it can only be marked as sent if a TrackingInfo object is provided.The bean supporting the information of an order could be something like this:
```java
class Order {
@StateReference
OrderStatus status = OrderStatus.INITIAL;
Object[] products;
Float price;
Object customer;
Object track;
}enum OrderStatus{
INITIAL,
PLACED,
PAYED,
SENT
}
```This library provides a way of implementing a flow class to handle this flow in the following manner:
```java
@Flow(OrderStatus.class)
@Transitions({
@Transition(event = "PLACE", from="INITIAL", to = "PLACED"),
@Transition(event = "PAY", from="PLACED", to = "PAYED"),
@Transition(event = "SEND", from="PAYED", to = "SENT")
})
public class OrderFlow extends AbstractBeanFlow {
@Guard("PLACE")
private boolean checkParams(Order order, @EventParam("products") Object[] products, @EventParam("customer") Object customer){
return products != null && customer != null;
}@On("PLACE")
private void fillOrderData(Order order, @EventParam("products") Object[] products, @EventParam("customer") Object customer){
order.products = products;
order.customer = customer;
}@OnState("PLACED")
private void calculatePrice(Order order){
order.price = 10f; //this should be calculated depending on the products
}@Guard("PAY")
private boolean checkPayment(Order order, @EventParam("payment") String recipe){
return recipe != null;
}@Guard("SEND")
private boolean checkPayment(Order order, @EventParam("tracking") Object track){
return track != null;
}@On("SEND")
private void fillOrderTracking(Order order, @EventParam("tracking") Object track){
order.track = track;
}
}```
Then by running the following you should be able to make an order pass through the bean flow:
```java
Order o = new Order();
OrderFlow flow = new OrderFlow();flow.raise(Event.build("PLACE").param("products", new Object[]{"pid"}).param("customer", "customer"), o);
flow.raise(Event.build("PAY").param("payment", "123"), o);
flow.raise(Event.build("SEND").param("trancking", "UPS-ABC"), o);
```Of course you can persist the bean and recover it later on between each step.
To see this sample inside a persisted web application go to the [restflow-spring-web-sample](https://github.com/alfonso-presa/restflow-spring-web-sample)
Look at src/text/java/com/apresa/restflow/samples for more examples.
## Download
With gradle:
```
compile group: 'com.github.alfonso-presa.restflow', name: 'restflow', version: '0.1.0'
```With maven:
```
com.github.alfonso-presa.restflow
restflow
0.1.0```
You can also use snapshot builds by pointing to the
[sonatype snapshot repository](https://oss.sonatype.org/content/repositories/snapshots)