Work through the "Hello World" example to familiarize yourself with a example of installing, running, and extending a simple Service Building Block (SBB). Procedures for Multiple FSMs per SBB describes the creation of a Rhino service which hosts multiple POJO FSMs in a single SBB. For anything but simple applications this is the recommended this option is used in combination with FSMs hosted in other SBBs. |
Development tasks
To develop a component with FSM Tool:
-
write the FSM specification — use the FSM DSL to write a text file defining states, actions, transitions, inputs, and outputs
-
generate an SBB — use the spec you’ve written to generate SBB code
-
extend the generated SBB — deploy runtime classes, extend the class, map events to inputs, unset durable inputs, and implement action methods
-
compile, package, and deploy — use standard methods to deploy the completed SBB
-
document — use FSM Tool’s features to automatically document the SBB.
-
trace — use FSM Tool’s runtime tracing.
Specify the state machine
First, write the specification for component state machines. In a simple application there may only be one state machine, but in more complex applications there can be many state machines in a hierarchy.
FSM Tool uses the FSM Domain Specific Language (DSL) to specify state machines. The FSM DSL syntax includes:
-
state definitions and descriptions
-
exit, and entry actions associated with each state
-
input actions associated with each state, with conditions that must be met before executing
-
transitions, with conditions that must be met before transitioning
-
an input dictionary, declaring all inputs referenced in transition and input action conditions
-
an action dictionary, declaring all actions that are occurring as input, entry, or exit actions
-
endpoint declarations, naming all the endpoints which are used in conditional expressions and the input dictionary to express where inputs are received from.
For an example of an FSM specification, see the "Definition" tab in the Sample Application. For the full FSM DSL syntax, see the FSM Language Reference. |
Generate the FSM SBB Java class
FSM Tool uses the FSM specification to generate an FSM SBB Java class. To correctly generate the code, you need to:
-
Set properties for FSM Tool’s FSM SBB code-generation template.
-
Set up the Ant
build.xml file
to use the FSM Tool Ant task (see Configuring Code Generation):-
Add a
<fsmtool:generate-fsm>
task to the build file, and set the properties of the task for the component under development. -
Run Ant on the target that includes the
<fsmtool:generate-fsm>
task. -
Look for errors that the FSM Tool reports when parsing the specification — correct them, and re-run the Ant target.
-
Extend the generated SBB
The FSM specification defines the abstract behaviour of the component. To make it work, you must extend the generated FSM StateMachine SBB Java class with an SBB class that:
-
maps received events to raised inputs, and executes the state machine
-
defines, creates and registers an implementation of the actions interface (defined by the StateMachine SBB class) which contains implementations for the FSM’s action methods.
Follow these steps to extend the SBB:
1 |
Deploy runtime classes FSM Tool has a small runtime environment. The generated FSM SBB implements the |
||
---|---|---|---|
2 |
Extend the class The developer-defined SBB class extends the state-machine SBB class that FSM Tool generated, as follows:
|
||
3 |
Map events to state machine inputs
When using FSM Tool, you only use an SBB’s event handlers to map events to state-machine inputs, and to call the state machine. The following snippet shows the typical pattern of usage in an SBB event-handler method:
You can directly reference the inputs, which are kept internally in the generated state-machine SBB class. For example, if the declared input is hello and received on endpoint tcp, the service calls the If you need to set more than one input before executing the state machine, simply add more Finally, trigger the FSM execution cycle by calling |
||
4 |
Unset durable inputs Inputs are transient by default, in the state machine specification input dictionary. (FSMs automatically clear transient inputs after one execution cycle.) If you need to use durable inputs, you will need to manually unset them within an action method, as follows:
|
||
5 |
Implement actions interface Each action defined in the state machine specification renders into a method declaration in an actions interface, which is declared as an inner interface of the state-machine SBB class.
The actions interface must be implemented in the extended SBB, and an instance must be registered with the state machine execution class (best to do this in the
|
XDoclet
We recommend using OpenCloud’s XDoclet tool to generate deployment descriptors for the SBB (as the generated SBB class declares CMP fields using XDoclet tags). If you don’t use XDoclet, you’ll need to maintain deployment descriptors for the extended SBB by hand. |
Compile, package, and deploy the SBB
Follow standard procedures
Once you’ve finished the steps to implement an SBB, use the |
Generate documentation
To create a graphic illustration of the state machine, configure a <fsmtool:generate-dot>
task to generate the Graphviz dot file format (see the "Hello World" example for details).
FSM Tool uses code-generation templates to specify details of the implementation that a state-machine specification generates. The output of code generation does not depend on the FSM Tool directly — by changing only the templates, completely different output formats can be produced. This means that you can use FSM Tool to generate many different types of output file from the specification. For example, FSM Tool comes with the following templates for generating javadocs and graphics from the state machine specification:
-
fsm-for-multi-per-sbb.stg
— to generate a POJO FSM when multiple FSMs are required in a single SBB -
multi-fsm-sbb.stg
— to generate an SBB Java class used to host one or more POJO FSMs -
fsm.stg
— to generate an FSM SBB Java class supporting a single FSM -
dot.stg
— to generate a GraphViz dot file.
The Javadoc of the generated SBB makes reference to the Graphviz state-machine image. You can also reference the state-machine image in the Javadoc of the SBB that extends the generated class, by including the image there. |
FSM Tool can use the templates provided, use enhanced templates to meet specific requirements, or use templates created from scratch. The templates are written in StringTemplate
template group format (see the StringTemplate documentation for details of file syntax). Any code generation template group used by FSM Tool must implement the full set of template names used in the fsm.stg
template group file. This set of template names is the interface between the template group and the FSM Tool. The template implementations can generate any text output or empty strings that the final output format requires (.java
, .dot
, .html
, and so on).
See also Configuring Code Generation. |
Enable runtime tracing
The generated FSM SBB can be configured to produce state-transition tracer messages, by setting the tracer level for the deployed SBB to "Fine". Either the "" ({root})
tracer name or the "fsm"
tracer name for the SBB can be used.
Once the tracer is set, trace messages such as following are written to the rhino logging subsystem:
2010-08-18 10:38:16.340 Fine [trace.HelloWorldService_0_1.fsm] <jr-2> [HelloWorldService/FSM1_Sbb] pkey=101:182573003122:0 FSM[transition=CheckParam->PrintHW, InputRegister[scheduled=[], execution=[local_printHW]], Endpoints[Endpoint[name="local,aci=[not-set,sbb-not-attached],eventContext=[not-set],endpointInterface=[not-set],activityContextInterfaceFactory=[not-set],sbbLocalObject=[not-set]],Endpoint[name="ep,aci=[set,sbb-attached],eventContext=[not-set],endpointInterface=[not-set],activityContextInterfaceFactory=[not-set],sbbLocalObject=[not-set]]]]
Action tracing (as well as transition tracing) can be enabled by setting the trace level of the SBB to "Finest". Here is an example of action logging output:
2010-08-18 10:40:44.081 Finest [trace.HelloWorldService_0_1.fsm] <jr-3> [HelloWorldService/FSM1_Sbb] pkey=101:182573003122:0 FSM[action=checkParams, state=CheckParam, result=executed successfully] 2010-08-18 10:40:44.081 Fine [trace.HelloWorldService_0_1.fsm] <jr-3> [HelloWorldService/FSM1_Sbb] pkey=101:182573003122:0 FSM[transition=CheckParam->PrintHW, InputRegister[scheduled=[], execution=[local_printHW]], Endpoints[Endpoint[name="local,aci=[not-set,sbb-not-attached],eventContext=[not-set],endpointInterface=[not-set],activityContextInterfaceFactory=[not-set],sbbLocalObject=[not-set]],Endpoint[name="ep,aci=[set,sbb-attached],eventContext=[not-set],endpointInterface=[not-set],activityContextInterfaceFactory=[not-set],sbbLocalObject=[not-set]]]] 2010-08-18 10:40:44.082 Finest [trace.HelloWorldService_0_1.fsm] <jr-3> [HelloWorldService/FSM1_Sbb] pkey=101:182573003122:0 FSM[action=printHelloWorld, state=PrintHW, result=executed successfully]