Skip to content

This project aim is to provide a lightweight state machine library that allows to easily implement bean flows.

License

Notifications You must be signed in to change notification settings

alfonso-presa/restflow

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status

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
  • Sent

The 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:

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:

@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<Order> {
	@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:

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

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:

<dependency>
	<groupId>com.github.alfonso-presa.restflow</groupId>
	<artifactId>restflow</artifactId>
	<version>0.1.0</version>
</dependency>

You can also use snapshot builds by pointing to the sonatype snapshot repository

About

This project aim is to provide a lightweight state machine library that allows to easily implement bean flows.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages