Component State Machines: Tutorial

263 views
Skip to first unread message

Oliver Rolle

unread,
Nov 22, 2014, 9:51:50 AM11/22/14
to vertx-...@googlegroups.com
Why using state machines in vertigo?
In distributed systems its hard to manage side-effects and race-conditions of atomic component. As race-conditions are no problem with verticles, side-effects still remain. One way to reduce side-effects is to design components as state machines. State machines handle their states and state transitions explicit and therefore less prone to side-effects. Not modelled state-transitions (side-effects) will fail immediately and not at some point in time in the future. A second pro argument is their high performance. Disadvantages are that you have to learn SMC-modelling language.

In business process management state machines allow to separate state related logic from business logic, leading to cleaner code, better reusability and testability.
(https://today.java.net/pub/a/today/2006/01/05/business-object-state-management-using-smc.html)

How to use SMC within a maven project?
Add SMC runtime library to execute the state machine at runtime:
<dependency>
 
<groupId>com.github.orolle</groupId>
 
<artifactId>smc-lib-java</artifactId>
 
<version>6.4.0</version>
</dependency>

Oliver Rolle

unread,
Nov 22, 2014, 9:52:22 AM11/22/14
to vertx-...@googlegroups.com
Add smc-maven-plugin to compile a state machine (sm) file (/source/main/smc/example.sm) to java source (add /target/generated-sources/smc/smc/ to your build path) during development. see also http://mojo.codehaus.org/smc-maven-plugin/howto.html
<project>
  <build>
   
<plugins>
     
<plugin>
       
<groupId>com.github.orolle</groupId>
       
<artifactId>smc-maven-plugin</artifactId>
       
<version>6.4.0</version>
       
<executions>
         
<execution>
           
<goals>
             
<goal>smc</goal>
           
</goals>
         
</execution>
       
</executions>
       
<configuration>
         
<verbose>true</verbose>
          <!-- <serial>true</serial> -->
         
<!-- <sync>true</sync> -->
       
</configuration>
     
</plugin>
   
</plugins>
  </build>
</project>

Create a visualizations (transition table as html, graph as png) of your state machines with "mvn smc:smcreports". Generated report files are in /target/site/smc
<project>
     <reporting>
        <plugins>
            <plugin>
                <groupId>com.github.orolle</groupId>
                <artifactId>smc-maven-plugin</artifactId>
                <version>6.4.0</version>
                <configuration>
                    <verbose>true</verbose>
                    <glevel>1</glevel>
                </configuration>
            </plugin>

        </plugins>
   
</reporting>
</project>

Oliver Rolle

unread,
Nov 22, 2014, 9:53:07 AM11/22/14
to vertx-...@googlegroups.com
Define a state machine in /source/main/smc/Turnstile.sm (more details in http://smc.sourceforge.net/slides/SMC_Tutorial.pdf) and compile with "mvn smc:smc"
// use a Turnstile java interface instead of a class; much more flexible!
%class Turnstile

// Package in which the generated state machine source lies
%package turnstile

// Import stuff you need
%import org.vertx.java.core.json.JsonObject

// Initial State of the state machine
%start MainMap::Locked

//
MainMap Transition Table; SMC supports multiple TT
%map MainMap
%%
// State   Transition [guard]    End State    Action(s)
Locked
{
           coin(amount: double) [ctxt.isSufficient(amount)]
                                
Unlocked     { unlock(); }

           coin(amount: double) [!ctxt.isSufficient(amount)]
                                 nil
         { unlock(); }
           pass                  nil          { alarm(); }
}

Unlocked
{
           pass                  Locked       { lock(); }
           coin
(amount: double)  nil          { thankyou(); }
}
%%

The state machine compiler generate TurnstileContext.java in turnstile package (/target/generated-sources/smc/smc/). Create an "Turnstile" interface in your main source dir (/source/main/java) in the turnstile package. Add the missing methods to the interface: unlock, alarm, lock, thankyou. The following code shows the implementation of TurnstileComponent.java with the TurnstileContext state machine and SimpleTurnstile (state-dependent behavior) implementation:
package turnstile;

import net.kuujo.vertigo.java.ComponentVerticle;

import org.vertx.java.core.Handler;

public class TurnstileComponent extends ComponentVerticle {
  private Turnstile businessObject = new SimpleTurnstile();
  private TurnstileContext fsm = new TurnstileContext(businessObject);
 
  @Override
  public void start() {
    super.start();
   
    input.port("coin").messageHandler(new Handler<Double>() {
      @Override
      public void handle(Double money) {
        fsm.coin(money);
      }
    });
   
    input.port("pass").messageHandler(new Handler<Object>() {
      @Override
      public void handle(Object event) {
        fsm.pass();
      }
    });
  }
 
  class SimpleTurnstile implements Turnstile {

    @Override
    public void unlock() {
      System.out.println("UNLOCK");
    }

    @Override
    public void alarm() {
      System.out.println("ALARM");
    }

    @Override
    public void thankyou() {
      System.out.println("THANKS");
    }

    @Override
    public void lock() {
      System.out.println("LOCK");
    }

    @Override
    public boolean isSufficient(double money) {
      return money > 2;
    }
  }
}

Any suggestions / feedback? Should I share the turnstile tutorial project on github?

Jordan Halterman

unread,
Nov 25, 2014, 1:49:53 PM11/25/14
to vertx-...@googlegroups.com
Hey, sorry I've been out a bit for a few days. Pushing through a project at work before vacation, but I'll be back at it later tonight and have a week off.
--
You received this message because you are subscribed to the Google Groups "vertigo" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx-vertig...@googlegroups.com.
To post to this group, send email to vertx-...@googlegroups.com.
Visit this group at http://groups.google.com/group/vertx-vertigo.
To view this discussion on the web visit https://groups.google.com/d/msgid/vertx-vertigo/d2711410-e683-4773-900e-8fcdfff4a5ad%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Oliver Rolle

unread,
Nov 26, 2014, 7:57:03 AM11/26/14
to vertx-...@googlegroups.com
no problem, first things first ;-)

On December 12th I am on an hackathon. I like to work with a friend on an Hadoop YARN (or Docker on Mesos) compatible vertigo version. The goal is to execute vertigo network on a 2 VM cluster as a fast proof of concept. After the hackathon we might use the poc or draft a new one. Should we use vertigo 0.7 or 1.0? The essential part is to get hazelcast instances communicating with each other within the cluster? I have read somewhere that vertx uses their own connections (not via hazelcast) to transfer messages between machines?

John Smith

unread,
Nov 27, 2014, 11:10:08 PM11/27/14
to vertx-...@googlegroups.com
Correct. Vertx only uses hazelcast for node discovery and it's own internal tcp/ip client for comms

Jordan Halterman

unread,
Nov 28, 2014, 2:45:40 AM11/28/14
to vertx-...@googlegroups.com
Sorry. Thanksgiving and what not.

John is right. Vert.x only uses Hazelcast for node discovery. The event bus is actually implemented on Vert.x NetClient and NetServer instances. When you start the Vert.x instance, the port and host you pass in is actually used for the event bus NetServer, and the Hazelcast configuration is used to locate other nodes and share cluster information via Hazelcast shared data.
Reply all
Reply to author
Forward
0 new messages