ADOxxWEB Simulation

EXTEND: ADOxxWEB Simulation

( Details  Use  -  Extend )

In the following we explain how you can integrate/adopt the ADOxxWEB Simulation, customize it for your needs, and finally deploy it on a server of your choice.


1. Setup of Development Environment

The proposed development environment consist of the following tools and technologies:

  • Eclipse IDE for Java EE Developer: as an integrated development environment we propose to use the Eclipse EE environment, necessary plugins are listed as technologies below. The version used for this documentation is "Mars".
  • Maven: as a build and dependency management environment. In case you are new to Maven, have a look a the brief introduction online here (Maven in 5 minutes). The necessary plugin for Eclipse is available here.
  • Java: as the baseline technology for realizing the building block. The tested/used version is Java JDK 7.
  • SVN: the source code of this building block is maintained in the ADOxx.org SVN Repository. Make sure to have the SVN plugin for Eclipse installed to check-out and commit directly from within your IDE.

As a prerequesite to get started, make sure to have the Eclipse IDE up and running and the necessary connectors/plugins for Maven and SVN installed.


2. Check-out 'ADOxxWEB Simulation' Project from SVN

The ADOxxWeb Simulation consists of one Maven project.

The project is accessible in the SVN: 
https://www.adoxx.org/svn/devtools/2%20ADOxx%20Building%20Blocks/4%20ADOxxWEB%20Simulation/simulation/

For importing the Project please follow the steps below:

A. Right-click in the project explorer, select "Import" -> "Import project from SVN"

B. Enter the URL of the project (as listed above). Since the ADOxx.org SVN is public, no username or password is needed.

C. Click on Next and Finish to trigger the checkout (in the next steps you can configure the name of the project in Eclipse, in case you want to update, please use the respective wizard steps).

READY! Your have the projects in your workspace and you can start your extension work.

3. Perform an Initial Build/Resolve Dependencies

As a preparation action, make sure that the project is installed in the local Maven repository. The steps for installation are performed by:

A. Right-click on the project -> "Run as" -> "Maven build..."

In the "Goals" field enter "clean install". Click on "Run" to trigger the clean-up of the project first and then installation the projects (installing implies the resolution of dependencies).

B. Review the console log. In case of error statements, you can re-run the build and add -X to have a full log of all activities.


4. Validate Debug/Development Deployment

For local validation and debugging, you can start the modeldocu only in a Apache Jetty Container.

A. Create a New Tomcat Server: "File" -> "New" -> "Server"

B. Right-click the ADOxxWeb Simulation project and select "Run as" -> "Run on Server" -> Select the new created Server

The block is deployed on the server and is accessible at http://localhost:8080/simulation.

An important aspect is that this allows to debug a block directly, the wrapper web application should be used for productive deployment (e.g. WAR file on Apache Tomcat).

C. Create a WAR file for Productive Deployment

To create a deployable WAR file, right-click on the ADOxxWeb Simulation project, select "Run as" and "Maven build ...". Enter "clean install" in the "Goals" field and hit "Run".

This creates a new WAR file in the "target" folder of the project. Use this WAR file to deploy it in a e.g. Apache Tomcat container.

In case you receive error messages for step 3 or 4 in the following message "No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?", make sure that you have a JDK installed and on the build path.

EVERYTHING READY FOR SIMULATING YOUR MODELS!

Extension points

 

In the following, we will explain the available extension points:

 

Model Import

Add the import from a new model type can be easily achieved implementing the interface org.adoxx.pn.input.ImporterI and adding the new created class to the constructor of the ImporterManager (org.adoxx.pn.input.ImporterManager). The interface define a method used to evaluate if the current class can be used with the provided model (isCompliant), and a method that perform the conversion and return an array of PetriNet object (generatePetriNet). Inside this method it is possible to use the MappingHelper class (org.adoxx.pn.input.mapping.MappingHelper) in order to simplify the mapping procedure. This class give the possibility to separate the mapping logic from the parsing logic of the model. In this way, it is possible to use the same mapping for BPMN semantic with two or more different BPMN file format like the OMG standard and the ADOxx format.

In order to achieve this, the MappingHelper class give the possibility to define mapping rules to apply at every element. This mapping rule follow the following syntax:

 

Formula = MapRules ";" InputRelations ";" OutputRelations

MapRules = elementTypeList ":" RuleList

InputRelations = "in :" relationList

OutputRelations = "out :" relationList

elementTypeList = ElementTypeName [ "|" elementTypeList ]

ElementTypeName: the type name of the object you want to map

RuleList = Rule [ "," RuleList ]

Rule = from ">" to | from

from: name of the PN element you want to create/use for connection with the "to" element;
this name have to start with "p" in order to refer to a place or with "t" in order to refer to a transition.
In case of place is it possible to specify the number of token between parenthesis "(numtoken)".

to: name of the PN element you want to create/use for connection with the "from" element;
this name have to start with "p" in order to refer to a place or with "t" in order to refer to a transition.
In case of place is it possible to specify the number of token between parenthesis "(numtoken)".

relationList = relation [ "," relationList]

relation = RelationType "=" PNElementName

RelationType: name of the relation type you want to map

PNElementName: name of the PN element defined in the from/to you want to use for the relation

 

Es:

Start: p(1)>t ; in:message=p ; out: sequence=t

Task|Intermediate: p>t ; in: sequence=p, message=t ; out: sequence=t, message=t

End: p ; in: sequence=p ; out:

msgEnd: p>t,t>p1 ; in: sequence=p ; out: message=t

 

Once the mapping rules has been defined, you will need to parse your document, and for every relevant element, call the execution of the respective mapping rule. The same will be made later with the relations. When you process a relation, the mapper automatically fix its connections, so if a relation is trying to connect a place with another place, it automatically put a transition in the middle (and the opposite for the connection between two transitions). Post processing on generated elements and relations can be also performed (look the class org.adoxx.pn.input.impl.ImporterOMGBPMN as example). At the end, calling the method generatePN of the MappingHelper, the PetriNet object is returned.

 

Measures

Measure indexes and any kind of data resulting of a simulation can be produced adding a listener to the simulation event. The listener is called on every simulation started and fired transition. In order to define the listener you should create a class that implement the SimulationListenerI interface (org.adoxx.pn.simulation.handlers.SimulationListenerI). That class must then be added to the listener list in the SimulationEngine (org.adoxx.bpmn.SimulationEngine) in order to be processed. This give the possibility to define a general reusable system where some listener use as example also the partial results of other listeners (look as an example at the WaitingTimeCalculator listener which depend on the ExecutionTimeCalculator).

Once a measure index has been produced at the end of a simulation, you should decide where to store it. In this context, you can choose to associate the measure to a trace, adding the index to TraceCollector (org.adoxx.pn.simulation.TraceCollector), or to a path adding the index to PathCollector (org.adoxx.pn.simulation.PathCollector). The choice depends on the nature of the index. If the index measure can change when parallel activities are executed in different order, so you must choose to associate the measure to the Trace while if the measure can change only in presence of concurrent activities you must opt for path association.

A single Trace in fact represent the exact execution step by step of the process, by a single executor. In such a case the executor has the limit to perform only one task a time so parallel activities are executed sequentially and potentially in any order. The trace enable you to reflect this order.

A Path instead is only defined by the choice between concurrent activities and represent a single flow of the process, independent from the executor.

Paths and Traces are related. A Trace is uniquely associated with its Path (while a path can include multiple traces, depending on the task parallelism), so adding an index to the Trace enable you to get information also on the Path of that Trace.

At the end you have to adapt the xml results generator in the SimulationEngine (method formatResults) in order to return your new measure.

 

Transition Choice

The last extension point is the Transition Choice system.  This part is responsible at each simulation step, to decide which petri net transition execute, between the enabled ones.

The definition of such a mechanism is possible through the implementation of the TransitionSelectorI interface (org.adoxx.pn.simulation.handlers.TransitionSelectorIand the definition of this implementation in the SimulationEngine using the setTransitionSelector method of the Simulation class (org.adoxx.pn.simulation.Simulation).

An abstract class that implement this interface and contain useful methods for a Transition Selector definition, has been provided (org.adoxx.pn.simulation.handlers.TransitionSelectorA).

The current default implementation (org.adoxx.pn.simulation.TransitionSelectordDefault) extends the abstract class TransitionSelectorA and is valid for single user execution. In such a case, the logic is to randomly choice between transitions of parallel activities and make a choice based on user-defined probability for concurrent transitions.

An extension of this default implementation is also provided in the TransitionSelectorAdoxx (org.adoxx.pn.simulation.TransitionSelectorAdoxx) that give the possibility of dynamically evaluate probabilities through their definition in javascript format.

Extension Example

Extending the Simulation service: add support for BPMN Terminate End events

In the following, we provide a tutorial on how to extend the simulation service in order to add support for the BPMN Terminate End Event that is currently missing in the mapping.

The BPMN Terminate End Event give the possibility to instantly terminate all the started activities in the process. In order to support this, we need to apply the following steps, explained in details below: Identify the TerminateEvent in the parsing function, add it as additional info of the relative petri net place, create a simulation listener that manage the termination event execution deleting all the token in the process.

 

  1. In BPMN2 standard, the Terminate Event is specified with the XML tag terminateEventDefinition under the end event tag. If the tag is present, the end event is a terminate end event. In order to recognize it we have to modify the end event parsing section in the BPMN Importer class ImporterOMGBPMN in the following way:

    NodeList endEventNodeList = (NodeList) XMLUtils.execXPath(…
    for(int i=0;i<endEventNodeList.getLength();i++){

    boolean isTerminate = ((NodeList) XMLUtils.execXPath(endEventNodeList.item(i),
    "./*[local-name()='terminateEventDefinition']", XPathConstants.NODESET))
    .getLength() !=0 ? true : false;

    for(PL place:ge.placeList){
    place.addInfo("poolId", poolId);
    place.addInfo("terminateAll", ""+isTerminate);


    The property is stored as an additional info of the place in the petri net.
     
  2. Once we have the information in the petri net we can use it in the simulation inside our simulation handler. First, a class TerminateEventHandler that implement the SimulationListenerI interface, must be created. This class, in order to manage the execution of a terminate event, must delete all the token present in the process, in order to force it to stop.

    PetriNet petriNet = null;
    @Override
    public void simulationStarted(PetriNet petriNet) {
       this.petriNet = petriNet;
    }
    @Override
    public void transitionFiredEvent(TR transitionFired) throws Exception {
       for(PL nextPlace:transitionFired.nextList)
          if(nextPlace.additionalInfoList.get("terminateAll") == "true"){
             for(PL place:petriNet.getPlaceList())
                if(place.additionalInfoList.get("poolId") == nextPlace.additionalInfoList.get("poolId"))
                   if(!place.equals(nextPlace))
                      place.numToken = 0;
             return;
          }
    }

     
  3. This class must now be added as a listener in the SimulationEngine class:

    public SimulationEngine(){
       …
       simulation.addSimulationListener(new TerminateEventHandler());
    }

     

Integration Example

Integration with ADOxx

In the following, we provide an example of ADOxx integration with the Simulation Service through the scripting language ADOScript.

  1. Import BPMN library:

The Simulation service currently work with a BPMN model, so the first step is to import the BPMN Library inside your ADOxx environment (Video tutorial here).

  1. Add required files to the library:

Add the simulate.asc script and the curl.exe files in the BPMN Library (Video tutorial here). The curl.exe is used to perform REST calls to the simulation service while the simulate.asc implements the logic that call the simulation.

  1. Implement the script into the library:

Change the BPMN library attributes ‘Add-ons'

  • Add under the ON_EVENT AppInitialized the following line:
    EXECUTE file:"db:\\simulate.asc"
  • Create a menu item that start the simulation:
    ITEM "Remote Simulation" simulation PERFORM_SIMULATION

 

Now accessing your modelling environment with the user associated to the BPMN Library, you will find under the Simulation view, the new menu Tools/Remote Simulation

Launching the simulation the script will ask you the URL of the Simulation service. If you deployed it locally you can leave the default value, else change it according to your deploy server.

 

The script then, ask for the number of simulation to perform and let you choose the model to simulate. In the end, it provide the simulation results in raw format.