Using a workflow engine, state machine engine or rolling my own?

Viewed 8609

I'm confused. I'm developing a grails based internal tool for my company. One component in this tool is a simple issue tracker (a Helpdesk feature). I have domain objects such as Problem, Question and NewFeature. Each of these domain classes have different workflows.

My initial idea was to roll my own state machine functionality inside the domain objects. I then googled for state machine engines and workflow engines. And now I'm lost.

I would like to have comments how other developers have solved this problem. Do you use Drools, Jbpm, Activiti? Or some simpler state machine engine?

I have been reading some documentation for the Drools, Jbpm. They look very nice. But it seems like I only need a small part of the features these libraries provide.

I'm using Grails for this but it's of course easy to use Java libraries as well.

3 Answers

'State machine' is common design pattern, so what drools actually gives you? I personally value drools for its 'query language', this is what makes it shine. You practically have something like 'SQL to query objects from your heap'. Just like SQL gives you 'declarative' way of programming, drools when block describes when to start state transition in declarative way. Drools was designed to be statefull by default and state is all facts (POJOs) which were inserted into drools session.

Let me propose you simple usecase. You have to write application for cellular phone company to manage phone calls:
If caller 1 is calling to callee 2 and he is not 'busy' at that MOMENT, connect them.
If callee is busy, continue calling for 7 seconds and if the callee dismiss his original call DURING that period of time, connect them at once.
if callee will not disconnect during 7 seconds, drop the caller with the message 'callee is busy'.

Simple triple-if statement business method quickly became quite complex and error prone technical task. I imagine background Timers' I've seen a lot 5 to 10 years ago or some newer, like ScheduledThreadPoolExecutor. And what if state changed DURING scheduled delay? Will you still wait until the end to recalculate the condition? If such condition is relatively often in your application or the period is relatively long will you keep 'context' in the memory? You would need to keep track of Futures and cancel them or use some BlockingQueue. One would need to maintain queue for each person for such cases because each person can be potentially called by somebody. Traditional OOP says 'you should keep behavior attached to your domain entities'. With this approach you'll start clutter your business entities with quite complex technical stuff even if you would use some patterns to simplify (encapsulate) complexity your 'state machine' start to spread between multiple components, it will be even worse if you'll use 'layered style' because you will start to produce data structures for the state stuff, like Map<Callee, BlockingQueue<Caller>>. Next day your customer come to you and say, 'hey, I have another simple use case for you around phone calls'.

Drools solves such problems 'naturally' because it uses totally different approach. It keeps track of all objects in the working memory (it keeps track of the rule condition) and when time comes, drools is just able to say whether your rule is eligible to be executed or not (rete algorithm back to 1979). If state changes, drools re-evaluates when condition for each rule in efficient way and put or remove respective rules from 'agenda' (execution queue). All objects you've inserted into 'working memory' form a 'state' which any rule can relay on. You can find some diagrams and tests for the usecase described above and actual drools rule implementation here

Use right tools for your tasks. If you need for loop on collection of entities with State object inside with 3-5 fields, don't put 'state machine' in the title. If you really face problems like 'continuous behavior change' or complex cause-effect dependencies between events in your system, then drools is good and time-proven open source rete algorithm implementation. Don't try to use everything advertised, dig into details, understand what suit your needs.

Related