27. Eclipse Modeling Support

Defining a state machine configuration with UI modeling is supported via Eclipse Papyrus framework.

From eclipse wizard create a new Papyrus Model with UML Diagram Language. In this example it’s named as simple-machine. Then you’ve given an option to choose various diagram kind’s and a StateMachine Diagram must be chosen.

We want to create a machine having two states, S1 and S2 where S1 is initial state. Then event E1 is created to do a transition from S1 to S2. In papyrus a machine would then look like something shown below.

simple machine

Behind a scenes a raw uml file would look like.

<?xml version="1.0" encoding="UTF-8"?>
<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_AMP3IP8fEeW45bORGB4c_A" name="RootElement">
  <packagedElement xmi:type="uml:StateMachine" xmi:id="_AMRFQP8fEeW45bORGB4c_A" name="StateMachine">
    <region xmi:type="uml:Region" xmi:id="_AMRsUP8fEeW45bORGB4c_A" name="Region1">
      <transition xmi:type="uml:Transition" xmi:id="_chgcgP8fEeW45bORGB4c_A" source="_EZrg4P8fEeW45bORGB4c_A" target="_FAvg4P8fEeW45bORGB4c_A">
        <trigger xmi:type="uml:Trigger" xmi:id="_hs5jUP8fEeW45bORGB4c_A" event="_NeH84P8fEeW45bORGB4c_A"/>
      </transition>
      <transition xmi:type="uml:Transition" xmi:id="_egLIoP8fEeW45bORGB4c_A" source="_Fg0IEP8fEeW45bORGB4c_A" target="_EZrg4P8fEeW45bORGB4c_A"/>
      <subvertex xmi:type="uml:State" xmi:id="_EZrg4P8fEeW45bORGB4c_A" name="S1"/>
      <subvertex xmi:type="uml:State" xmi:id="_FAvg4P8fEeW45bORGB4c_A" name="S2"/>
      <subvertex xmi:type="uml:Pseudostate" xmi:id="_Fg0IEP8fEeW45bORGB4c_A"/>
    </region>
  </packagedElement>
  <packagedElement xmi:type="uml:Signal" xmi:id="_L01D0P8fEeW45bORGB4c_A" name="E1"/>
  <packagedElement xmi:type="uml:SignalEvent" xmi:id="_NeH84P8fEeW45bORGB4c_A" name="SignalEventE1" signal="_L01D0P8fEeW45bORGB4c_A"/>
</uml:Model>
[Tip]Tip

When opening existing uml model defined as uml, you’ll have three files, .di, .notation and .uml. If model was not created in your eclipse’s session, it doesn’t understand how to open an actual state chart. This is a known issue in a Papyrus plugin and there is an easy workaround. In a Papyrus Perspective you’ll see Model Explorer for you model, double click Diagram StateMachine Diagram which will instruct eclipse to open this specific model in its proper Papyrus modeling plugin.

27.1 Using UmlStateMachineModelFactory

After uml file is in place in your project, it can be imported into configuration using StateMachineModelConfigurer where StateMachineModelFactory is associated with a model. UmlStateMachineModelFactory is a special factory which knows how to process Eclipse Papyrus generated uml structure. Source uml file can either be given as a Spring Resource or a normal location string.

@Configuration
@EnableStateMachine
public static class Config1 extends StateMachineConfigurerAdapter<String, String> {

    @Override
    public void configure(StateMachineModelConfigurer<String, String> model) throws Exception {
        model
            .withModel()
                .factory(modelFactory());
    }

    @Bean
    public StateMachineModelFactory<String, String> modelFactory() {
        return new UmlStateMachineModelFactory("classpath:org/springframework/statemachine/uml/docs/simple-machine.uml");
    }
}

As usually Spring StateMachine is working with Guards and Actions which are defined as bean, those need to be hooked into uml by its internal modeling structure. In a below sections you will see how customized bean references are defined within uml definitions. Thought it is also possible to register particular methods manually without defining those as beans.

If UmlStateMachineModelFactory is created as a bean its ResourceLoader is wired automatically to find registered actions and guards. It’s also possible to manually define a StateMachineComponentResolver which will then be used to find these components. Factory also have methods registerAction and registerGuard which can be used to register these components.

Uml model is relatively loose what comes for the implementation like Spring StateMachine itself. There are choices what implementation need to take for uml support as it leaves a lot of features and functionalities for an implementation to decide. Below sections go through how Spring StateMachine will implement uml model based on Eclipse Papyrus plugin.

27.2 Creating Model

Let’s start by creating an empty state machine model.

papyrus gs 1

You’ll start by creating a new model and giving it a name.

papyrus gs 2

Then you need to choose a StateMachine Diagram.

papyrus gs 3

You end up having an empty state machine.

In above sample named model you’ll end up three files, model.di, model.notation and model.uml which can then be used in any other eclipse instance and model.uml can be used by importing it into a Spring Statemachine.

27.3 Define States

State identifier is simply coming from a component name in a diagram. You must have initial state in your machine which is done by adding Initial and then drawing a transition to your own initial state.

papyrus gs 4

In above we added one state S1, initial state, and draw a transition between those two to indicate that S1 is an initial state.

papyrus gs 5

In above we added a second state S2 and added a transition between those two.

27.4 Define Events

To associate an event for a transition you need to create a Signal E1. Done from RootElement→New Child→Signal.

papyrus gs 6

And then SignalEvent with defined signal E1. Done from RootElement→New Child→SignalEvent.

papyrus gs 7

27.5 Define Transitions

Transition is simply created by drawing transition line between source and target states. In above we have states S1 and S2 and anonymous trasition between those two. We want to associate event E1 with that transition. We choose a transition, create a new trigger and define SignalEventE1 for that.

papyrus gs 8

This will give you something like shown below.

papyrus gs 9
[Tip]Tip

If SignalEvent is omitted for a transition it becomes an anonymous transition.

27.6 Define Timers

Transition can also happen based on timed events. Spring Statemachine support two types of timers, ones which fires continously on a background and ones which fires once with a delay when state is entered.

Add new TimeEvent child to Model Explorer, modify When as expression defined as LiteralInteger. Value of it is then timer as milliseconds. Is Relative is left to false making timer to fire continously.

papyrus gs 10

To define one timed based event when state is entered it’s exactly same as above but Is Relative is now defined as true.

papyrus gs 11

Then what is left for user is to pick these time events instead of signal event for a particular transition.

27.7 Define Actions

State entry and exit actions can be associated by using a behaviour, more about this in Section 27.9, “Define Bean Reference”.

27.8 Define Guards

Guard can be defined by first adding Constraint and then defining its Specification as OpaqueExpression which works in a same way than Section 27.9, “Define Bean Reference”.

27.9 Define Bean Reference

When there is a need to make a bean reference in any uml effect, action or guard, supported method to do that is via FunctionBehavior or OpaqueBehavior where defined language needs to be bean and language body having a bean reference id.

27.10 Define SpEL Reference

When there is a need to use a SpEL instead of a bean reference in any uml effect, action or guard, supported method to do that is via FunctionBehavior or OpaqueBehavior where defined language needs to be spel and language body having a SpEL expression.