ADOxxWEB Simulation

EXTEND: ADOxxWEB Simulation

( Details  Use  -  Extend )

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

1. Setup of Development Environment

The proposed development environment consists 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 Plug-ins 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 here (Maven in 5 minutes). The necessary Plug-in 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 SVN Repository. Make sure to have the SVN Plug-in for Eclipse installed to check-out and commit directly from within your IDE.

As a pre-requesite to get started, make sure to have the Eclipse IDE up and running and the necessary connectors/Plug-ins 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:

For importing the Project, please follow these steps:

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

B. Enter the URL of the project (as listed above). Since the 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 can start your extension work.

3. Perform an Initial Build/Resolve Dependencies

As a prepatory 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 an 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 the debugging of 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 click "Run."

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

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


Extension points


In this section, we will explain the available extension points:


Model Import

Adding the import from a new model type can be easily achieved by implementing the interface and adding the new created class to the constructor of the ImporterManager ( The interface defines a method used to evaluate if the current class can be used with the provided model (isCompliant), and a method that performs the conversion and returns an array of PetriNet objects (generatePetriNet). Inside this method, it is possible to use the MappingHelper class ( in order to simplify the mapping procedure. This class gives 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 semantics with two or more different BPMN file formats, like the OMG standard and the ADOxx format.

In order to achieve this, the MappingHelper class gives the possibility to define mapping rules to apply at every element. This mapping rule follows 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



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 have 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 relations. When you process a relation, the mapper automatically fixes its connections. Therefore, if a relation is trying to connect a place with another place, it automatically puts 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 at the class as an example). At the end, calling the method generatePN of the MappingHelper, the Petri Net object is returned.



Measure indexes and any kind of data resulting from a simulation can be produced by 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 implements the SimulationListenerI interface ( That class must then be added to the listener list in the SimulationEngine (org.adoxx.bpmn.SimulationEngine) in order to be processed. This gives the possibility to define a general reusable system where some listeners also use as example the partial results of other listeners (look for example at the WaitingTimeCalculator listener, which depends 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 (, or to a path adding the index to PathCollector ( The choice depends on the nature of the index. If the index measure can change when parallel activities are executed in a different order, you must choose to associate the measure to the Trace. While the measure can change only in presence of concurrent activities, you must opt for path association.

A single Trace in fact represents 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 at a time so parallel activities are executed sequentially, and potentially in any order. The trace enables you to reflect this order.

A Path instead is only defined by the choice between concurrent activities and represents 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), therefore adding an index to the Trace enables you to get information also on the Path of that Trace.

At the end you have to adapt the XML results generator to 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 to execute, between the enabled ones.

The definition of such a mechanism is possible through the implementation of the TransitionSelectorI interface ( the definition of this implementation in the SimulationEngine using the setTransitionSelector method of the Simulation class (

An abstract class that implements this interface and contains useful methods for a Transition Selector definition has been provided (

The current default implementation ( extends the abstract class TransitionSelectorA and is valid for single user execution. In such a case, the logic is to randomly choose 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 ( that gives the possibility of dynamically evaluating probabilities through their definition in JavaScript format.

Extension Example

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

In this section, 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 gives 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 the 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 manages the termination event execution, deleting all the tokens in the process.


  1. In the 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 of our simulation handler. First, a class TerminateEventHandler that implements the SimulationListenerI interface, must be created. This class, in order to manage the execution of a terminate event, must delete all the tokens present in the process in order to force it to stop.

    PetriNet petriNet = null;
    public void simulationStarted(PetriNet petriNet) {
       this.petriNet = petriNet;
    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"))
                      place.numToken = 0;

  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 works with a BPMN model, so the first step is to import the BPMN Library inside of your ADOxx environment (Video tutorial here).

  1. Add required files to the library:

Add the simulate.asc script and the curl.exe files into 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 calls the simulation.

  1. Implement the script into the library:

Change the BPMN library attributes ‘Add-ons'

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


Now when accessing your modelling environment with the user associated with 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, otherwise change it according to your deploy server.


The script then asks for the number of simulations to perform, and lets you choose the model to simulate. In the end, it provides the simulation results in raw format.