download of Activiti in Action includes free access to a private web forum run by Man struction of a large PDF document, this may not be the desired behavior. Activiti in Action is a comprehensive tutorial designed to introduce developers to the world of Before diving into the nuts and bolts of Activiti, this book presents a solid introduction to BPMN . eBook $ pdf + ePub + kindle + liveBook. Rademakers & van Liempd / Activiti in Action. 1. BPMN what's in it for developers? This chapter covers. ▫ Introducing the world of BPM. ▫ Designing.
|Language:||English, Spanish, Portuguese|
|Distribution:||Free* [*Registration needed]|
Activiti in Action. EXECUTABLE BUSINESS PROCESSES IN BPMN TIJS RADE MAKE RS. MANNING. Shelter Island. This first part of the book provides an introduction to the Activiti framework and the To download their free eBook in PDF, ePub and Kindle formats, owners. of Activiti, which provide a way to implement BPMN processes with plain Java struction of a large PDF document, this may not be the desired behavior.
Tips: When you edit and save a model, you can choose for the changes to be saved as a new version. Previous versions can be accessed from the History popup, as can any commentary from the Comments popup, where you can add further comments. Other action buttons are self-explanatory such as deleting, starring favorites , sharing, and downloading the model. On the Apps page, click Create app definition. You can have an app without any process definitions linked to it, which lets you create a simple custom task list.
Save the app and select the option to publish the app in the Save dialog to return the Apps list view. You can do similar actions on an app in its Details page for all models, such as deleting and sharing. You can also publish the app directly instead of doing it via the Save dialog.
The Add app to landing page dialog appears. Choose the apps you want to add and click Deploy. A new tile will be added to your landing page.
Using My Tasks and Process Apps A process app is simply a collection of processes that you want to group together to make them available to yourself or other users you share it with. To access tasks and processes: Click on the new app tile that you just created and you will be taken to its Task page. This will only show the tasks created within this app or as part of the processes from the app.
Click on the hint box next to James to create a task and fill in some text. You will now have a task in your task list. Complete a task by clicking Complete. You can do a variety of things with a task, such as give it a due date or assign it to someone else. James also has some hints on adding reference documents, comments, and involving other people. When you involve someone else in a task, it will appear in their tasks list. This enables them to contribute to the task such as add comments, documents, and even involve more people.
However, only the person who is assigned the task with can actually complete it. Click Complete. If you wish to view that task again, you can click the Completed Tasks filter on the left pane. A list of available processes are displayed, which in our case will be only one. When you select it, the Start form we created above is displayed.
You can also change the name by clicking the title on the right panel. By default the current date is added to the name of the process. Fill in the form and click Start Process. You will be returned to the Processes page, showing the details of the newly started process in your process list.
You can always view a process to see what the current and completed tasks are, as well as add comments that will be available for anyone involved in the process at any stage. If you go to the Task page that we just created, you will see the first step in the process is that of a task to review the project, and accept or reject it. The task was assigned to you because it was set to the process initiator, and you started the process.
Before you fill in the review summary and choose accept or reject, you can still add people, documents, and comments by clicking on the Show details button in the task header area. You can get back to the form from there by clicking the Show form button.
If you click the Accept button, the Review Project task will disappear and instead a new task, Update Project List will appear. This is because you defined it as the next choice step in the Step Editor, if the choice was to accept the project. You can just click the Complete button to move to the next step, which is a task to show the details of the accepted project. When you complete this task, your task list and your process list will be empty.
If you prefer to see all your tasks and processes in one place rather than through different process apps, you can use the My Tasks tile to get your complete task and process lists.
When you first log in to Activiti, you will see your landing page. Each tile gives you tools for distinct sets of tasks. You can get back to your landing page at any time by clicking on the Alfresco Activiti logo on the header.
Your landing page is dynamic, and new tiles will appear when you create new process apps in the Kickstart App and deploy them in the Task App. Your Activiti buddy James appears below the tiles to help you with a list of shortcuts for tasks you might want to do next. He provides useful hints to help you design and share business processes, work with your tasks and processes, update your profile, and a link to the Getting Started Guide.
The Getting Started Guide is the tutorial embedded in the product that will help you learn the basics of working with Alfresco Activiti. If you are an administrator, your landing page is slightly different. All pages display the App Navigator icon in the far-right corner of the header. It provides useful 1-click shortcuts to various parts of the app. You can navigate instantly to all your process models, tasks, processes, stencils, forms, decision tables, quickly start any process, view the tasks and processes for a published and deployed app, or view and change your profile.
As you deploy process apps, the App Navigator will also show shortcuts for the newly created process apps. Kickstart app Use the Kickstart app to create process models, forms, app definitions, and share your models and definitions with others. As you create items, they appear as tiles on their respective page. The Last Modified drop-down on the top-right enables you to sort the display order ranging from last modified, oldest first, name order, or reverse name order.
Use the filter on the left to filter the list of displayed items. Additionally, if you are unable to find a specific process, use the search box to find more processes. If your processes require human input, then you will need forms to gather it. The filter name changes based on the tab you are in. For example, in case of the Forms tab, it changes to My reusable forms and to My App definitions when you are in the Apps tab. Shared with Me - View items shared by others with you.
Shared with Others - View items that you have shared with others. Favorited - View your favorite items. To allow someone else to use this model, it has to be shared first. The Kickstart panel includes the following tabs: Processes - Provide tools for creating new processes, modifying existing processes, and importing processes from outside Alfresco Activiti.
If you are not familiar with the BPMN 2. Forms - Provide tools for creating new forms, and modifying existing forms. Filter the list of displayed forms using the options on the left. You can view all your forms, or just those shared by others with you, or those you have shared with others, or just those you have favorited. Decision Tables - List decision tables that can be used across processes. Decision tables are an easy way to define business rules. Apps - Create new apps, modify existing apps, and import apps from outside Alfresco Activiti.
You create an app to group one or more of your processes, so you manipulate them as one unit. You can make an app available for yourself and share it with others. An app can contain no process at all, which allows you to create simple task list. Data Models - Enable you to map your business data with a relational database or a custom API such as a customer database, patient database, and so on.
You can create business objects to connect to an external database that can be accessed by all processes in your application. When you create a process or a form, you can specify a specific stencil or use the default for the editor you are using. Kickstart editor You can open the Kickstart editor by clicking a process definition, reusable form, reusable decision table, app definition, data models, or the stencils tab.
The Kickstart editor provides features such as copy, comment, delete, add to favorites, share with others, and export. You can also open the corresponding editor to make changes to the content, and perform actions specific to the item type.
For example, you can publish an app definition or edit a process. In the above example, the Kickstart editor was opened for an app definition called publisher. The editor always displays the details of the selected item on the top panel along with a set of buttons on the top right. The right-most button opens the editor corresponding to the item displayed.
So in the example, the right-most button opens the app editor. If a process definition created via the step editor is opened in the Kickstart editor, then the App Editor would open the step editor. Task App Use the Task App to access your task list and work on tasks assigned to you from the Processes tab.
This is also where you initiate new processes and tasks. The Task App menu bar has tabs for working with tasks, processes, reports, and a Start button, which is a shortcut to start a process using a published process definition. Tasks tab The Tasks tab is organized into three columns. The left column lets you filter the list of displayed tasks. There are four pre-defined filters and a New Filter control which lets you define and name your own filters.
Any filters you create are added to the list of displayed filters. The middle column provides tools for creating new tasks, and lists the tasks included by the current active filter. Click on the accordion icon above the list of tasks to change the default display order from Newest first to oldest first, Due last order, or Due first order.
The right column is displayed when you click on a task in the middle column. It displays the selected task details and also tools for completing open tasks and for viewing the audit log of a completed task. Note: The Audit log button is only available for a completed process instance or a completed task.
You can also change the default sort order. Process definition Select an active running process name, and display only those tasks that are associated with that process. State Choose to display tasks or processes based on its state. For tasks, select Completed or Open. Completed is selected by default. For processes, select Running, complete, or All. Running is selected by default. Assignment Select tasks in which you are involved, or tasks that have been assigned to you, or tasks where you are one of the several candidates.
This is only applicable to the Tasks tab. If you have no tasks or processes running, then James will appear with a shortcut to let you create a new task for yourself or start an existing process and track its progress. Processes tab Use the Processes tab to start a new process from a list of published process definitions. The Processes tab is organized into three columns similar to the Tasks tab except that instead of tasks, process details are displayed.
You can also create a new filter to filter by process definitions, process state, and by process name. Reports tab Use the Reports tab to generate reports based on the available parameters. You can view the reports that you saved in the Analytics App. For more information, see Analytics App. Profile management This tile will appear for you only if you are a user.
This is where you manage your personal information. Identity management This tile is only available if you are an administrator. This is where you manage your personal information, users and groups in your organization, and tenants in your Alfresco Activiti engine. The process instance will now continue to the next step. In this example, the next step allows the employee to complete a form that adjusts their original vacation request.
The employee can resubmit the vacation request which will cause the process to loop back to the start task. Suspending the process definition is done through the RepositoryService:. To reactivate a process definition, simply call one of the repositoryService. When suspended, the process cannot be continued e. Suspending a process instance can be done by calling the runtimeService.
Activating the process instance again is done by calling the runtimeService. We will expand these sections further in the future with additional coverage of the Activiti API.
Of course, as with any open source project, the best way to learn is to inspect the code and read the Javadocs! There are two ways of querying data from the engine: The query API and native queries. You can add various conditions to your queries all of which are applied together as a logical AND and precisely one ordering.
The following code shows an example:. Sometimes you need more powerful queries, e. For these cases, we introduced native queries, which allow you to write your own SQL queries.
The return type is defined by the Query object you use and the data is mapped into the correct objects, e. Since the query will be fired at the database you have to use table and column names as they are defined in the database; this requires some knowledge about the internal data structure and it is recommended to use native queries with care. The table names can be retrieved via the API to keep the dependency as small as possible.
Every process instance needs and uses data to execute the steps it exists of. In Activiti, this data is called variables , which are stored in the database. Variables can be used in expressions for example to select the correct outgoing sequence flow in an exclusive gateway , in java service tasks when calling external services for example to provide the input or store the result of the service call , etc. A process instance can have variables called process variables , but also executions which are specific pointers to where the process is active and user tasks can have variables.
A process instance can have any number of variables. Any of the startProcessInstanceXXX methods have an optional parameters to provide the variables when the process instance is created and started. For example, from the RuntimeService:. Note that variables can be set local for a given execution remember a process instance consists of a tree of executions.
The variable will only be visible on that execution, and not higher in the tree of executions. Variables can also be fetched again, as shown below. Note that similar methods exist on the TaskService. This means that tasks, like executions, can have local variables that are alive just for the duration of the task.
Variables are often used in Java delegates , expressions , execution- or tasklisteners, scripts, etc. The simplest methods are these:. For historical and backwards compatible reasons , when doing any of the calls above, behind the scenes actually all variables will be fetched from the database.
This means that if you have 10 variables, and only get one through getVariable "myVariable" , behind the scenes the other 9 will be fetched and cached.
This is not bad, as subsequent calls will not hit the database again. For example, when your process definition has three sequential service tasks and thus one database transaction , using one call to fetch all variables in the first service task might be better then fetching the variables needed in each service task separately.
Note that this applies both for getting and setting variables. Of course, when using a lot of variables or simply when you want tight control on the database query and traffic, this is not appropriate. Since Activiti 5. When using true for the parameter fetchAllVariables , the behaviour will be exactly as described above: However, when using false as value, a specific query will be used and no other variables will be fetched nor cached.
Only the value of the variable in question here will be cached for subsequent use. Transient variables are variables that behave like regular variables, but are not persisted. Typically, transient variables are used for advanced use cases i.
Like regular variables, transient variables are put on the highest parent when set. This means that when setting a variable on an execution, the transient variable is actually stored on the process instance execution. Like regular variables, a local variant of the method exists if the variable should be set on the specific execution or task.
A transient variable can only be accessed until the next wait state in the process definition. After that, they are gone.
The wait state means here the point in the process instance where it is persisted to the data store. Note that an async activity also is a wait state in this definition! Transient variables can only be set by the setTransientVariable name, value , but transient variables are also returned when calling getVariable name a getTransientVariable name also exists, that only checks the transient variables.
The reason for this is to make the writing of expressions easy and existing logic using variables works for both types. A transient variable shadows a persistent variable with the same name. This means that when both a persistent and transient variable is set on a process instance and the getVariable "someVariable" is used, the transient variable value will be returned. Also, these config parameters are not important for historical audit purposes, so we pass them as transient variables:.
Note that the variables will be available until the user task is reached and persisted to the database. For example, in the Additional Work user task they are not available anymore. The Process Data would get the response transient variable, parse it and store the relevant data in real process variables as we need them later. The condition on the sequence flow leaving the exclusive gateway are oblivious to whether persistent or transient variables are used in this case the status transient variable:.
Activiti uses UEL for expression-resolving. Although there are 2 types of expressions, value-expression and method-expression, Activiti abstracts this so they can both be used where an expression is needed. Value expression: By default, all process variables are available to use. Also all spring-beans if using Spring are available to use in expressions. Some examples:. Method expression: When invoking a method without parameters, be sure to add empty parentheses after the method-name as this distinguishes the expression from a value expression.
The passed parameters can be literal values or expressions that are resolved themselves. Note that these expressions support resolving primitives incl. On top of all process variables, there are a few default objects available to be used in expressions:. The DelegateExecution that holds additional information about the ongoing execution. The DelegateTask that holds additional information about the current Task.
Only works in expressions evaluated from task listeners. The id of the user that is currently authenticated. If no user is authenticated, the variable is not available. Business processes are an integral part of software projects and they should be tested in the same way normal application logic is tested: Since Activiti is an embeddable Java engine, writing unit tests for business processes is as simple as writing regular unit tests.
Activiti supports both JUnit versions 3 and 4 styles of unit testing. In the JUnit 3 style, the org. ActivitiTestCase must be extended. This will make the ProcessEngine and the services available through protected member fields. In the setup of the test, the processEngine will be initialized by default with the activiti.
To specify a different configuration file, override the getConfigurationResource method. Process engines are cached statically over multiple unit tests when the configuration resource is the same.
By extending ActivitiTestCase , you can annotate test methods with org. Before the test is run, a resource file of the form testClassName. At the end of the test, the deployment will be deleted, including all related process instances, tasks, etc. The Deployment annotation also supports setting the resource location explicitly. See the class itself for more information. To get the same functionality when using the JUnit 4 style of writing unit tests, the org.
ActivitiRule Rule must be used. Through this rule, the process engine and services are available through getters.
As with the ActivitiTestCase see above , including this Rule will enable the use of the org. Deployment annotation see above for an explanation of its use and configuration and it will look for the default configuration file on the classpath.
Process engines are statically cached over multiple unit tests when using the same configuration resource. The following code snippet shows an example of using the JUnit 4 style of testing and the usage of the ActivitiRule.
When using the in-memory H2 database for unit tests, the following instructions allow to easily inspect the data in the Activiti database during a debugging session. The screenshots here are taken in Eclipse, but the mechanism should be similar for other IDEs. Suppose we have put a breakpoint somewhere in our unit test.
In Eclipse this is done by double-clicking in the left border next to the code:. If we now run the unit test in debug mode right-click in test class, select Run as and then JUnit test , the test execution halts at our breakpoint, where we can now inspect the variables of our test as shown in the right upper panel.
Now select Display or execute the shortcut instead of right-clicking. Now open up a browser and go to http: You can now see the Activiti data and use it to understand how and why your unit test is executing your process in a certain way. The ProcessEngine is a thread-safe class and can easily be shared among multiple threads.
In a web application, this means it is possible to create the process engine once when the container boots and shut down the engine when the container goes down. The following code snippet shows how you can write a simple ServletContextListener to initialize and destroy process engines in a plain Servlet environment:. The contextInitialized method will delegate to ProcessEngines.
That will look for activiti. If you have multiple such resource files on the classpath, make sure they all have different names. When the process engine is needed, it can be fetched using. Of course, it is also possible to use any of the variants of creating a process engine, as described in the configuration section.
The contextDestroyed method of the context-listener delegates to ProcessEngines. That will properly close all initialized process engines. The ProcessEngine can be configured as a regular Spring bean.
The starting point of the integration is the class org. That bean takes a process engine configuration and creates the process engine. This means that the creation and configuration of properties for Spring is the same as documented in the configuration section. For Spring integration the configuration and engine beans will look like this:. Note that the processEngineConfiguration bean now uses the org.
SpringProcessEngineConfiguration class. Below is the Spring configuration file that we use in this example you can find it in SpringTransactionIntegrationTest-context. The section shown below contains the dataSource, transactionManager, processEngine and the Activiti Engine services.
This is done to make sure the SQL connections retrieved from the DataSource and the Spring transactions play well together.
In this case no additional wrapping will occur. First the application context is created with any of the Spring ways to do that. In this example you could use a classpath XML resource to configure our Spring application context:. Then we can get the service beans and invoke methods on them. The ProcessEngineFactoryBean will have added an extra interceptor to the services that applies Propagation. So, for example, we can use the repositoryService to deploy a process like this:.
The other way around also works.
In this case, the Spring transaction will be around the userBean. The UserBean looks like this. Remember from above in the Spring bean configuration we injected the repositoryService into the userBean.
The example below exposes a single bean printer , available to use under the key "printer". When no beans property is set, all Spring beans in the context will be available. Now the exposed beans can be used in expressions: Spring integration also has a special feature for deploying resources. In the process engine configuration, you can specify a set of resources. When the process engine is created, all those resources will be scanned and deployed.
There is filtering in place that prevents duplicate deployments. Only when the resources actually have changed, will new deployments be deployed to the Activiti DB. This makes sense in a lot of use case, where the Spring container is rebooted often e. By default, the configuration above will group all of the resources matching the filtering into a single deployment to the Activiti engine.
The duplicate filtering to prevent re-deployment of unchanged resources applies to the whole deployment. In some cases, this may not be what you want.
For instance, if you deploy a set of process resources this way and only a single process definition in those resources has changed, the deployment as a whole will be considered new and all of the process definitions in that deployment will be re-deployed, resulting in new versions of each of the process definitions, even though only one was actually changed. To be able to customize the way deployments are determined, you can specify an additional property in the SpringProcessEngineConfiguration , deploymentMode.
This property defines the way deployments will be determined from the set of resources that match the filter. There are 3 values that are supported by default for this property:. Group all resources into a single deployment and apply duplicate filtering to that deployment.
Create a separate deployment for each individual resource and apply duplicate filtering to that deployment. This is the value you would use to have each process definition be deployed separately and only create a new process definition version if it has changed.
Create a separate deployment for resources that share the same parent folder and apply duplicate filtering to that deployment. This value can be used to create separate deployments for most resources, but still be able to group some by placing them in a shared folder. In addition to using the values listed above for deploymentMode , you may require customized behavior towards determining deployments.
This method determines which deployment strategy is used for a certain value of the deploymentMode configuration. When integrating with Spring, business processes can be tested very easily using the standard Activiti testing facilities.
The following example shows how a business process is tested in a typical Spring-based unit test:. Note that for this to work, you need to define a org. ActivitiRule bean in the Spring configuration which is injected by auto-wiring in the example above. When using Hibernate 4. This is not needed for Hibernate 4. The following dependency should be added:. Spring Boot is an application framework which, according to its website , makes it easy to create stand-alone, production-grade Spring based Applications that can you can "just run".
It takes an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need very little Spring configuration. For more information on Spring Boot, see http: The Spring Boot - Activiti integration is currently experimental.
It has been developer together with Spring committers, but it is still early days. We welcome all to try it out and provide feedback. Spring Boot is all about convention over configuration. To get started, simply add the spring-boot-starters-basic dependency to your project. For example for Maven:. This dependency will transitively add the correct Activiti and Spring dependencies to the classpath. You can now write the Spring Boot application:. Activiti needs a database to store its data.
If you would run the code above, it would give you an informative exception message that you need to add a database driver dependency to the classpath. For now, add the H2 database dependency:. So by just adding the dependency to the classpath and using the EnableAutoConfiguration annotation a lot has happened behind the scenes:.
An in-memory datasource is created automatically since the H2 driver is on the classpath and passed to the Activiti process engine configuration. Also, any BPMN 2. Create a folder processes and add a dummy process definition named one-task-process.
Also add following code lines to test if the deployment actually worked. The CommandLineRunner is a special kind of Spring bean that is executed when the application boots:.
As stated above, Spring Boot is about convention over configuration. By default, by having only H2 on the classpath, it created an in memory datasource and passed that to the Activiti process engine configuration. To change the datasource, simply override the default by providing a Datasource bean. For example, to switch to a MySQL database:. Spring Boot makes this really easy. Add following dependency to the classpath:. Create a new class, a Spring service, and create two methods: Here, we simply delegate to the service defined above.
Both the Service and the RestController will be found by the automatic component scan ComponentScan we added to our application class. Run the application class again. This will add in the Spring configuration and beans for using JPA.
By default the JPA provider will be Hibernate. Create a file application. We add the method to find a Person by username. Spring will automagically implement this based on conventions i. The startProcess now gets an assignee username in, which is used to look up the Person, and put the Person JPA object as a process variable in the process instance. A method to create Dummy users is added. This is used in the CommandLineRunner to populate the database. And there is a lot more to the Spring Boot integration:.
To deploy processes, they have to be wrapped in a business archive. A business archive is the unit of deployment to an Activiti Engine.
A business archive is equivalent to a zip file. It can contain BPMN 2. In general, a business archive contains a collection of named resources. When a business archive is deployed, it is scanned for BPMN files with a. Each of those will be parsed and may contain multiple process definitions. Java classes present in the business archive will not be added to the classpath.
All custom classes used in process definitions in the business archive for example Java service tasks or event listener implementations should be present on the Activiti Engine classpath in order to run the processes. See the javadocs for more details. Process definitions live in the Activiti database. These process definitions can reference delegation classes when using Service Tasks or execution listeners or Spring beans from the Activiti configuration file. These classes and the Spring configuration file have to be available to all process engines that may execute the process definitions.
All custom classes that are used in your process e. When you are using the demo setup and you want to add your custom classes, you should add a jar containing your classes to the activiti-explorer or activiti-rest webapp lib. When expressions or scripts use Spring beans, those beans have to be available to the engine when executing the process definition.
If you are building your own webapp and you configure your process engine in your context as described in the spring integration section , that is straightforward. But bear in mind that you also should update the Activiti rest webapp with that context if you use it. You can do that by replacing the activiti. Instead of making sure that all process engines have all the delegation classes on their classpath and use the right Spring configuration, you may consider including the Activiti rest webapp inside your own webapp so that there is only a single ProcessEngine.
That is actually good because the executable BPMN process file will probably live in a version control system repository e. Subversion, Git or Mercurial as part of your development project. Versions of process definitions are created during deployment. For each process definition in a business archive the following steps are performed to initialize the properties key , version , name and id:. The process definition id attribute in the XML file is used as the process definition key property.
The process definition name attribute in the XML file is used as the process definition name property. If the name attribute is not specified, then id attribute is used as the name. The first time a process with a particular key is deployed, version 1 is assigned.
For all subsequent deployments of process definitions with the same key, the version will be set 1 higher than the maximum currently deployed version.
The key property is used to distinguish process definitions. When deploying this process definition, the process definition in the database will look like this:.
Suppose we now deploy an updated version of the same process e. The process definition table will now contain the following entries:. When the runtimeService. Should we create a second process, as defined below and deploy this to Activiti, a third row will be added to the table. Note how the key for the new process is different from our first process. Even though the name is the same we should probably have changed that too , Activiti only considers the id attribute when distinguishing processes.
The new process is therefore deployed with version 1. A process diagram image can be added to a deployment. This image will be stored in the Activiti repository and is accessible through the API. This image is also used to visualize the process in Activiti Explorer.
The following naming conventions for the process diagram image apply in this specific order:. If an image resource exists in the deployment that has a name of the BPMN 2. In case you have multiple images defined in one BPMN 2. Each diagram image will then have the process key in its file name. If no such image exists, am image resource in the deployment matching the name of the BPMN 2.
Note that this means that every process definition defined in the same BPMN 2. In case there is only one process definition in each BPMN 2. In case no image is provided in the deployment, as described in the previous section , the Activiti engine will generate a diagram image if the process definition contains the necessary diagram interchange information.
The resource can be retrieved in exactly the same way as when an image is provided in the deployment. If, for some reason, it is not necessary or wanted to generate a diagram during deployment the isCreateDiagramOnDeploy property can be set on the process engine configuration:.
Both deployments and process definitions have user defined categories. The process definition category is initialized value in attribute in the BPMN file: This introduction is written under the assumption you are using the Eclipse IDE to create and edit files. Very little of this is specific to Eclipse, however. Make sure that the file ends with.
The root element of the BPMN 2. Within this element, multiple process definitions can be defined although we advise to have only one process definition in each file, since this simplifies maintenance later in the development process.
An empty process definition looks as listed below. Note that the minimal definitions element only needs the xmlns and targetNamespace declaration. The targetNamespace can be anything, and is useful for categorizing process definitions. Optionally you can also add the online schema location of the BPMN 2.
This id can then be used to start a new process instance of the process definition, through the startProcessInstanceByKey method on the RuntimeService.
This method will always take the latest deployed version of the process definition.
Important to note here is that this is not the same as calling the startProcessInstanceById method. This method expects the String id that was generated at deploy time by the Activiti engine, and can be retrieved by calling the processDefinition.
The format of the generated id is key: If you get an ActivitiException stating that the generated id is too long, limit the text in the key field of the process. In this section we will cover a very simple business process that we will use to introduce some basic Activiti concepts and the Activiti API. This tutorial assumes that you have the Activiti demo setup running , and that you are using a standalone H2 server. Edit db. The end result will be a simple Java SE program that deploys a process definition, and interacts with this process through the Activiti engine API.
The use case is straightforward: In BPMCorp, a financial report needs to be written every month for the company shareholders. This is the responsibility of the accountancy department. When the report is finished, one of the members of the upper management needs to approve the document before it is sent to all the shareholders. The business process as described above can be graphically visualized using the Activiti Designer.
The graphical BPMN 2. What we see is a none Start Event circle on the left , followed by two User Tasks: The none start event tells us what the entry point to the process is. The User Tasks declarations are the representation of the human tasks of our process. Note that the first task is assigned to the accountancy group, while the second task is assigned to the management group.
See the section on user task assignment for more information on how users and groups can be assigned to user tasks. The elements are connected with each other through sequence flows. These sequence flows have a source and target , defining the direction of the sequence flow.
We have now created the process definition of our business process. From such a process definition, we can create process instances. In this case, one process instance would match with the creation and verification of a single financial report for a particular month. All the process instances share the same process definition.
To be able to create process instances from a given process definition, we must first deploy this process definition. Deploying a process definition means two things:. The process definition will be stored in the persistent datastore that is configured for your Activiti engine.
So by deploying our business process, we make sure that the engine will find the process definition after an engine reboot. The BPMN 2. More information on deployment can be found in the dedicated section on deployment. As described in that section, deployment can happen in several ways. One way is through the API as follows. Note that all interaction with the Activiti engine happens through its services. Now we can start a new process instance using the id we defined in the process definition see process element in the XML file.
Note that this id in Activiti terminology is called the key. This will create a process instance that will first go through the start event.
After the start event, it follows all the outgoing sequence flows only one in this case and the first task write monthly financial report is reached. The Activiti engine will now store a task in the persistent database. At this point, the user or group assignments attached to the task are resolved and also stored in the database. At such a wait state, the current state of the process instance is stored in the database. It remains in that state until a user decides to complete their task. At that point, the engine will continue until it reaches a new wait state or the end of the process.
When the engine reboots or crashes in the meantime, the state of the process is safe and well in the database. After the task is created, the startProcessInstanceByKey method will return since the user task activity is a wait state. In this case, the task is assigned to a group, which means that every member of the group is a candidate to perform the task.
We can now throw this all together and create a simple Java program. Create a new Eclipse project and add the Activiti JARs and dependencies to its classpath these can be found in the libs folder of the Activiti distribution. Before we can call the Activiti services, we must first construct a ProcessEngine that gives us access to the services.
Here we use the 'standalone' configuration, which constructs a ProcessEngine that uses the database also used in the demo setup. You can download the process definition XML here. This file contains the XML as shown above, but also contains the necessary BPMN diagram interchange information to visualize the process in the Activiti tools.
We can now retrieve this task through the TaskService by adding the following logic:. Note that the user we pass to this operation needs to be a member of the accountancy group, since that was declared in the process definition:. We could also use the task query API to get the same results using the name of the group.
We can now add the following logic to our code:. By default, no user is in the accountancy group. Then click Users and add the group to fozzie. As explained, the process will execute up to the first user task. Select the Tasks page to view this new task.
Note that even if the process was started by someone else, the task would still be visible as a candidate task to everyone in the accountancy group.
An accountant now needs to claim the task. By claiming the task, the specific user will become the assignee of the task and the task will disappear from every task list of the other members of the accountancy group. Claiming a task is programmatically done as follows:.
In the Activiti UI App, clicking the claim button will call the same operation. The task will now move to the personal task list of the logged on user. You also see that the assignee of the task changed to the current logged in user. The accountant can now start working on the financial report. Once the report is finished, he can complete the task , which means that all work for that task is done. For the Activiti engine, this is an external signal that the process instance execution must be continued.
The task itself is removed from the runtime data. The single outgoing transition out of the task is followed, moving the execution to the second task 'verification of the report'. The same mechanism as described for the first task will now be used to assign the second task, with the small difference that the task will be assigned to the management group. In the demo setup, completing the task is done by clicking the complete button in the task list.
The second task is now visible in the unassigned task lists. The verification task can be retrieved and claimed in exactly the same way as before. Completing this second task will move process execution to the end event, which finishes the process instance. The process instance and all related runtime execution data are removed from the datastore.
When you log into Activiti Explorer you can verify this, since no records will be found in the table where the process executions are stored. Programmatically, you can also verify that the process is ended using the historyService. Combine all the snippets from previous sections, and you should have something like this this code takes in account that you probably will have started a few process instances through the Activiti Explorer UI.
As such, it always retrieves a list of tasks instead of one task, so it always works:. However, as you are going through the BPMN 2. This way, a manager could reject the financial report which would recreate the task for the accountant. Frameworks, and particularly open-source frameworks such as Activiti, can implement a solution that has the same and often better implemented ;- features as those of a big vendor.
Due to the BPMN 2. The downside of a standard however, is the fact that it is always the result of many discussions and compromises between different companies and often visions.
As a developer reading the BPMN 2. Since Activiti puts ease of development as a top-priority, we introduced something called the Activiti BPMN extensions. These extensions are new constructs or ways to simplify certain constructs that are not in the BPMN 2. Although the BPMN 2. The prerequisite of such a custom extension is that there always must be a simple transformation to the standard way of doing things. When using a custom extension, this is always clearly indicated by giving the new XML element, attribute, etc.
So whether you want to use a custom extension or not, is completely up to you. Several factors will influence this decision graphical editor usage, company policy, etc. We only provide them since we believe that some points in the standard can be done simpler or more efficient.
Who knows, some day your idea might pop up in the specification! Events are used to model something that happens during the lifetime process. Events are always visualized as a circle. In BPMN 2. The type of trigger is defined by the inner icon or the type declaration in the XML.
Catching events are visually differentiated from a throwing event by the inner icon that is not filled i. Throwing events are visually differentiated from a catching event by the inner icon that is filled with black. Event definitions define the semantics of an event. Without an event definition, an event "does nothing special". For instance a start event without and event definition does not specify what exactly starts the process.
If we add an event definition to the start event like for instance a timer event definition we declare what "type" of event starts the process in the case of a timer event definition the fact that a certain point in time is reached. Timer events are events which are triggered by defined timer.
They can be used as start event , intermediate event or boundary event. The behavior of the time event depends on the business calendar used. Every timer event has a default business calendar, but the business calendar can also be defined on the timer event definition.
Where businessCalendarName points to business calendar in process engine configuration. When business calendar is omitted default business calendars are used. This format specifies fixed date in ISO format, when trigger will be fired. To specify how long the timer should run before it is fired, a timeDuration can be specified as sub-element of timerEventDefinition.
Example interval lasting 10 days:. Specifies repeating interval, which can be useful for starting process periodically, or for sending multiple reminders for overdue user task. Time cycle element can be in two formats. First is the format of recurring time duration, as specified by ISO standard.
Example 3 repeating intervals, each lasting 10 hours:. There is also the possibility to specify the endDate as an optional attribute on the timeCycle or either in the end of the time expression as follows: When the endDate is reached the application will stop creating other jobs for this task. It accepts as value either static values ISO standard for example "T Additionally, you can specify time cycle using cron expressions, example below shows trigger firing every 5 minutes, starting at full hour:.
Please see this tutorial for using cron expressions. The recurring time duration is better suited for handling relative timers, which are calculated with respect to some particular point in time e. You can use expressions for the timer event definitions, by doing so you can influence the timer definition based on process variables. The process variables must contain the ISO or cron for cycle type string for appropriate timer type. Important note: In fact, the two have nothing in common.
BPMN error events are a way of modeling business exceptions. Java exceptions are handled in their own specific way. Signal events are events which reference a named signal.
A signal event definition is declared using the signalEventDefinition element. The attribute signalRef references a signal element declared as a child element of the definitions root element.
The following is an excerpt of a process where a signal event is thrown and caught by intermediate events. The following methods on the org.
RuntimeService can be used to throw a signal programmatically:. The difference between signalEventReceived String signalName ; and signalEventReceived String signalName, String executionId ; is that the first method throws the signal globally to all subscribed handlers broadcast semantics and the second method delivers the signal to a specific execution only.
We could then use the signalEventReceived String signalName, String executionId method to deliver the signal to these executions.
By default, signals are broadcast process engine wide. This means that you can throw a signal event in a process instance, and other process instances with different process definitions can react on the occurrence of this event. However, sometimes it is wanted to react to a signal event only within the same process instance. A use case for example is a synchronization mechanism in the process instance, if two or more activities are mutually exclusive.
To restrict the scope of the signal event, add the non-BPMN 2. The following is an example of two separate processes communicating using signals. The first process is started if an insurance policy is updated or changed. After the changes have been reviewed by a human participant, a signal event is thrown, signaling that a policy has changed:.
This event can now be caught by all process instances which are interested. The following is an example of a process subscribing to the event. This means in the case of the example given above, that all instances of the process catching the signal would receive the event.
In this case this is what we want. However, there are also situations where the broadcast behavior is unintended. Consider the following process:.
The pattern described in the process above is not supported by BPMN. The idea is that the error thrown while performing the "do something" task is caught by the boundary error event and would be propagated to the parallel path of execution using the signal throw event and then interrupt the "do something in parallel" task.
So far Activiti would perform as expected. The signal would be propagated to the catching boundary event and interrupt the task. However, due to the broadcast semantics of the signal, it would also be propagated to all other process instances which have subscribed to the signal event. In this case, this might not be what we want. On the contrary, it is broadcast to all process instances.
If you need to deliver a signal to a specific process instance only, perform correlation manually and use signalEventReceived String signalName, String executionId and the appropriate query mechanisms.
Activiti does have a way to fix this, by adding the scope attribute to the signal event and set it to processInstance. Message events are events which reference a named message. A message has a name and a payload. Unlike a signal, a message event is always directed at a single receiver. A message event definition is declared using the messageEventDefinition element.
The attribute messageRef references a message element declared as a child element of the definitions root element. The following is an excerpt of a process where two message events is declared and referenced by a start event and an intermediate catching message event.
As an embeddable process engine, Activiti is not concerned with actually receiving a message. The reception of messages is therefore something you have to implement as part of the application or infrastructure into which the process engine is embedded.
After you have received a message inside your application, you must decide what to do with it. If the message should trigger the start of a new process instance, choose between the following methods offered by the runtime service:. If the message needs to be received by an existing process instance, you first have to correlate the message to a specific process instance see next section and then trigger the continuation of the waiting execution. The runtime service offers the following methods for triggering an execution based on a message event subscription:.
In the case of a message start event, the message event subscription is associated with a particular process definition. Such message subscriptions can be queried using a ProcessDefinitionQuery:.
Since there can only be one process definition for a specific message subscription, the query always returns zero or one results. If a process definition is updated, only the newest version of the process definition has a subscription to the message event.
In the case of an intermediate catch message event, the message event subscription is associated with a particular execution. Such message event subscriptions can be queried using a ExecutionQuery:. Such queries are called correlation queries and usually require knowledge about the processes in this case that there will be at most one process instance for a given orderId.
This is useful if the process needs alternative ways to react to different start events but eventually continues in a uniform way. A start event indicates where a process starts. The type of start event process starts on arrival of message, on specific time intervals, etc. In the XML representation, the type is given by the declaration of a sub-element. Start events are always catching: The authenticated user must be set with the method IdentityService.
This code is baked into the Activiti Explorer application. So it works in combination with Forms. A none start event technically means that the trigger for starting the process instance is unspecified.
This means that the engine cannot anticipate when the process instance must be started. The XML representation of a none start event is the normal start event declaration, without any sub-element other start event types all have a sub-element declaring the type. More information can be found in the forms section Example:. A timer start event is used to create process instance at given time.
It can be used both for processes which should start only once and for processes that should start in specific time intervals. The reasoning is that normally it is not wanted to keep automatically starting new process instances of this old version of the process. The XML representation of a timer start event is the normal start event declaration, with timer definition sub-element.
Please refer to timer definitions for configuration details. A message start event can be used to start a process instance using a named message. This effectively allows us to select the right start event from a set of alternative start events using the message name. When deploying a process definition with one or more message start events, the following considerations apply:.
The name of the message start event must be unique across a given process definition. A process definition must not have multiple message start events with the same name.
Activiti throws an exception upon deployment of a process definition such that two or more message start events reference the same message of if two or more message start events reference messages with the same message name. The name of the message start event must be unique across all deployed process definitions.
Activiti throws an exception upon deployment of a process definition such that one or more message start events reference a message with the same name as a message start event already deployed by a different process definition. Process versioning: Upon deployment of a new version of a process definition, the message subscriptions of the previous version are cancelled. This is also true for message events that are not present in the new version. When starting a process instance, a message start event can be triggered using the following methods on the RuntimeService:.
The messageName is the name given in the name attribute of the message element referenced by the messageRef attribute of the messageEventDefinition. The following considerations apply when starting a process instance:. Message start events are only supported on top-level processes.
Message start events are not supported on embedded sub processes. If a process definition has multiple message start events, runtimeService. If a process definition has multiple message start events and a single none start event, runtimeService. If a process definition has multiple message start events and no none start event, runtimeService. If a process definition has a single message start event, runtimeService. A message start event is visualized as a circle with a message event symbol.
The symbol is unfilled, to visualize the catching receiving behavior. The XML representation of a message start event is the normal start event declaration with a messageEventDefinition child-element:. A signal start event can be used to start a process instance using a named signal. The signal can be fired from within a process instance using the intermediary signal throw event or through the API runtimeService.
In both cases, all process definitions that have a signal start event with the same name will be started. Note that in both cases, it is also possible to choose between a synchronous and asynchronous starting of the process instances. The signalName that must be passed in the API is the name given in the name attribute of the signal element referenced by the signalRef attribute of the signalEventDefinition.
A signal start event is visualized as a circle with a signal event symbol. The XML representation of a signal start event is the normal start event declaration with a signalEventDefinition child-element:. An error start event can be used to trigger an Event Sub-Process.