1. edoras one Overview

1.1. What is edoras one?

edoras one comprises a new generation of integrated platform that combines business process management, case management and content management simply and effectively. It makes work processes much more economical. Running in the background, the platform guarantees quick access to whatever content is relevant for your company’s tasks. To achieve this, edoras one doesn’t rely on a rigid process structure. Instead, it’s based on "design by doing"; each individual user decides how much structure he actually needs and determines for himself which work fragment will help him achieve his task. All process steps have grown organically and, as such, are part of natural productivity. That means your company stays well organized in an unstructured world and sustains the dynamics necessary for success.

1.2. What is the main concept behind edoras one?

edoras one organizes everything you do around the concept of work items. No matter whether you create a single task, start a new case or process, or upload a document, everything is a work item and supports a common set of functionality like ownership and assignment, due date and priority. Forms are used to manage the data associated with work items. Work items can have relations to each other and support hierarchies. The behavior of a work item is driven by its model, which is called a definition. For instance a process is driven by its process definition which is modeled using the modeling standard BPMN 2. These models can be designed and configured within the modeler dashboard of edoras one. An edoras one App contains all types of models and configurations to support a specific aspect or area of your organization. An App can be deployed and all of its models become available to drive the behavior of your work items.

1.3. What is the concept behind "cases"?

The work item type called "case" is key in edoras one as it acts as the main context around a collection of work items and information. A case can represent many things depending on how you define it. Think of a case like a box with a label where you can find everything that you need to work on a particular task. There are small and large boxes, square and round ones, boxes with one compartment only or boxes with a lot of compartments to organize the contents. For example if you handle customer complaints with edoras one, a single "complaint" could become a "case" and everything that happens while solving that complaint can be stored in and made available in that case. Or if you use edoras one for your recruiting, each job applicant is represented by a "case" where all structured data like name, birthday etc. for the applicant is part of the case form and documents like CV and references are simply stored within the case as attachments. Another great fit for edoras one is request and approval handling where a vacation request, a travel request or even a request for a quote from a customer becomes a case, supporting the handling and approval process through edoras one.

1.4. What can I use edoras one for?

The best matches for edoras one are all types of processes where people are involved working and collaborating together, on-site or distributed, with internal colleagues and even external participants like customers or service providers - wherever data has to be collected, approved, discussed and solutions have to be found using a process style that is a combination of structured and unstructured, ad-hoc work. Let’s have a look at some examples.

1.4.1. Approval Processes

Think about a request in your organization which contains data that has to be approved, decided on and processed. Examples include a vacation or travel request, an order form to be approved and processed, or access rights and permissions for applications that need to be approved by several people in your organization. An approval process could even be a typical e-government process, where a citizen submits an application for processing by the government. edoras one allows every participant to be part of the whole process as needed.

1.4.2. Help Desk

There is a lot of unstructured work in a typical help desk environment. It needs to be fast, nothing must be lost and the customer needs answers. From submitting a help desk request either via email or over the phone, it all starts with a need from the customer. Some requests such as ordering a new license or upgrading to a new version of your product might be standard and can be fully structured or even automated. But complaint management or support issues are typically less structured and more driven by knowledge, not routine. That’s exactly where edoras one fits best: the combination of structured and knowledge driven work. If your help desk sees repeating patterns, start structuring them and you will gain added value every day, but even without any structure at all you will never loose a case in your help desk, you always have full access to all data, information and past discussions and you don’t miss a due date, at least not because of the tooling.

1.4.3. HR

HR processes are a great fit for edoras one as there are many people involved. Think of using edoras one in your recruiting process, let applicants apply for a job through an initial job application case form and upload their documents (CV, references etc.) . Then work on the application internally - everyone from HR people to superiors and managers who are part of the recruiting process can participate in the case and make it an effective place to collect information, have discussions and make decisions. Onboarding a new employee is another great example where a lot of people are typically involved - did you think about and remember everything that needs to be done? edoras one will help you with that organization. Once the employee has started working, then vacation, expenses or travel requests are typical processes where edoras one is a great fit.

1.5. How do I start using edoras one in my organization?

Using edoras one is very simple and even without your own collection of processes, templates and forms, you can benefit from edoras one from the first day by using default templates like a simple case, ad-hoc tasks and review process. Start collecting feedback from the people working with those default templates and then start modeling your own processes, forms and templates accordingly in small steps. Adjust them, deploy them, use them and collect feedback again to constantly improve. That’s what we call "design by doing" where your App emerges from your organizational needs in small, but continuous steps.

1.6. What license do I need to work with edoras one?

Licensing options are based on a license model with three user types:

  • Agents

  • Participants

  • Modelers

Agents and modelers are licensed as named users and participants are all free of charge. An agent has full access to the edoras one features, except the modelling features. You have to be a modeler in order to access the modelling capabilities of edoras one. A participant is able to start new cases and is able to participate with full feature capability in all the cases he started. In foreign cases, a participant can be included for single tasks (like approval) with limited access to the case, for everything else, you need to be an agent to have full access to all features.

1.7. Architecture Overview

The following diagram shows the main components of edoras one.

architectureOverview
Figure 1. Architecture overview
  1. Web Container (e.g. Tomcat)
    edoras one runs in a Java web-compliant container like Tomcat for instance. You can also deploy edoras one into a JEE compliant server like JBoss, although the JEE parts of the container are not necessarily needed but are integrated with, if available.

  2. Client / Web Browser
    edoras one is fully web-based and only needs a web browser to work with. Even the graphical modeling environment is fully running within the browser without the need of an extra plugin. The client part is based on HTML5 / CSS3 and uses a client side model-view-controller framework (AngularJS) to abstract the data from the view and the controllers.

  3. RDBMS
    All information within edoras one is stored transactionally within an RDBMS. The following database systems are supported by edoras one: Oracle 11/12, MS SQL Server, DB2, MySQL, PostgreSQL, H2 and Derby.

  4. Content Repository
    File-based content or large unstructured content is stored within the content repository of edoras one. There is a simple, built-in repository supporting a light-weight content storage system with built-in versioning capabilities. The content can also be stored in an external system like Alfresco, Sharepoint or any other system using the CMIS protocol.

  5. Search Infrastructure
    edoras one supports a full text search integration, each work item is searchable as well as its content. The search can be integrated with the featured Java based query API or through the search REST endpoint, supporting full text search as well as structured search.

  6. Work Item Infrastructure (edoras gear)
    The core of edoras one is its work item infrastructure supported by edoras gear, the work management framework. You can read more about edoras gear later in this document.

  7. Modelling Infrastructure (edoras vis)
    Part of edoras one is the modelling infrastructure named edoras vis. It is embedded into edoras one for a smooth modeling experience, deploying directly into edoras gear and runtime experience using edoras one. For each supported type of models there is an appropriate provider interpreting that model. Process models for instance are modeled with the BPMN 2 standard and being executed by the process provider, based on the Activiti process engine. The form models are stored in JSON and rendered through the form engine in the client.

  8. REST API
    edoras one supports a REST API based on the JSON data protocol. The edoras one client actually uses the same API as well for all of its features. Additionally, the REST API can be used for any kind of integration with edoras one.

  9. Extensions / Listeners / Providers
    There are a lot of well designed extension points in edoras gear that can be used to extend the work item platform in many ways. Read more details about the extension points later in this document.

  10. Client / Server Communication
    The client / server communication is based on the REST API supported by the edoras one backend services. JSON is used for the data in the requests and HTTP / HTTPS as the transfer protocol. edoras one can be integrated with SSO infrastructures as well.

2. edoras one User Guide

2.1. Basic application layout and navigation

2.1.1. Dashboards

When you log into edoras one, you will normally see the edoras one user dashboard:

dashboardUser

The edoras one dashboards each provide a summary of information that is relevant to a particular user role, in this case the user’s active work items. Only work items that are visible to the current user are displayed. You can change between dashboards using the dashboard selector in the application toolbar:

dashboardSelect
Note that depending on the user’s permissions, some dashboards may be available.

2.1.2. List view

The dashboard widgets typically show a summary of a particular type of work item:

dashboardWidget

Clicking on the widget header will open the corresponding list view to show the full list of work items (the widget itself only shows the first few):

listView

2.1.3. Work item page

Clicking on a particular item in the dashboard list will take you directly to the work item page where the work item details can be viewed and/or edited:

workItemPage

The work item page will typically provide a number of different work item views, which can be selected using the icons in the top right-hand corner:

viewSelection

and a number of work item actions in the action toolbar on the right hand side which can be used to perform operations on the work item:

actions

2.1.4. Work item views

Browse view

The browse view shows the work item details and is available for all work items. Select the Browse icon to open the work item view:

browseIcon

This will show the work item work form and if the item is active then the details may also be modifiable:

browseView
Search view

The search view shows the current child work items and is available for container work items such as Apps and Cases. Select the Search icon to open the child work item view:

searchIcon

This will show the list of child work items:

searchView
Comments view

The comments view shows the work item comments and is available for all work items.

Select the Comments icon to open the comments view:

commentsIcon

This will show the work item comments, including both automatically generated change notifications and user comments:

commentsView
Preview view

The preview view shows a preview of the work item contents and is available for all work items with suitable content.

Select the Preview icon to open the comments view:

previewIcon

This will show the content preview, which depends on the work item content type. As an example, a form model preview will show a preview image of the form layout:

previewView
Edit entity view

The edit entity view allows all work items to be viewed and/or modified (not just those that are accessible through the normal work item forms). This is a technical view of the work item that is available for all work items but only to users with suitable access permissions.

Select the Edit Entity icon to open the entity editor view:

editEntityIcon

This will show the work item values as a form:

editEntityView
Edit entity JSON view

The edit entity JSON view allows all the raw work item definition to be viewed and/or modified. This is a technical view of the work item that is available for all work items but only for users with suitable access permissions.

Select the Edit Entity JSON icon to open the entity JSON editor view:

editEntityJsonIcon

This will show the work item as a raw text field:

editEntityJsonView

2.1.5. Bookmarking pages

Every page in edoras one has a unique persistent URL that can be bookmarked in the browser or referenced from a link. Simply add a bookmark or copy the page URL from the browser address toolbar.

When following a link to edoras one you may have to log in if the browser does not have active edoras one credentials. When the link points to a work item view, the view will only be shown if the user that is logged in has suitable access permissions for the work item in question.

2.1.6. Keyboard shortcuts

edoras one provides a number of keyboard navigation shortcuts:

Table 1. Keyboard shortcuts
Key Description

c

create a new work item. The work item types that can be created are defined by the current dashboard. Select the work item type using the arrow keys and press Enter to create it.

d

change dashboard. Select the dashboard using the arrow keys and press Enter to open it.

ctrl + s

save form. Save the pending changes of a browse view or a create action.

2.2. Dashboards

2.2.1. User dashboard

The user dashboard provides a summary of the work items that are related to the workflows currently in progress in edoras one:

dashboardUser

The work items shown in the user dashboard are:

Case

a container for related work items and processes.

Task

describes a task to be performed by a user.

Document

a document or other file.

Query

a stored search configuration.

2.2.2. Modeler dashboard

The modeler dashboard provides a summary of the workflow apps and models:

dashboardModeler

The work items shown in the modeler dashboard are:

App Model

a container for related models that combine to define a workflow. The workflow defined by the models can only be used when the app is deployed.

Case Model

defines a particular type of case.

Process Model

defines an executable workflow that combines several tasks, either manual or automated.

Task Model

defines a particular type of task.

Document Model

defines a particular type of document.

Form Model

defines a form used by other models to interact with a specific work item.

Please refer to the edoras one Modeler Guide for more details of the modeler dashboard and the modeler work items.

2.2.3. Admin dashboard

The admin dashboard provides a summary of the system administration work items:

dashboardAdmin

The work items shown in the admin dashboard are:

Account

a container for related users and groups.

Group

defines related sets of users, and can also be used to grant permissions.

User

a particular user within the system.

App

the instance of an app model where the dynamic properties can be updated.

Please refer to the edoras one Admin Guide for more details of the admin dashboard and the admin work items.

2.2.4. Management dashboard

The management dashboard provides a statistical work item overview:

dashboardManagement

2.3. User Profile

You can manage your profile by accessing the user profile. Click on your user name in the top right corner of the screen and select User Profile.

2.3.1. Change your email address

edoras one sends email notifications depending on your settings. To change your email address simply type the new address in the field Email address and save your changes by clicking save at the bottom of the profile

2.3.2. Change your language

edoras one currently supports english, spanish, german, french and italian as platform languages. To change the language just select the desired language from the language dropdown and save your changes by clicking save at the bottom of the page.

Changing the language needs a page refresh after the save to become effective. Not every App has to be maintained in all languages. If your language is not maintained in a particular App, it defaults to the primary language defined by the issuer of the App.

2.3.3. Change your password

To change your password simply enter the new password in the password field (There are currently no restrictions about password strength). Then re-enter the password in the repeat password field and save your changes by clicking save at the bottom of the page.

2.3.4. Deputies

You are allowed to select users which can act as your deputies. Activated deputies can act on behalf of you. You can decide whether deputies are notified on the notification events. In the case when somebody else has chosen you as a his/her deputy you can impersonate the user by clicking on the user menu user name and Users to impersonate.

2.4. Avatar

edoras one uses the Gravatar online Avatar Service to load your avatar from the internet. If you don’t use gravatar yet and want to have a custom avatar in edoras one, sign up to Gravatar with the email address specified in your user profile by clicking on Create your own Gravatar on their website.

2.5.1. Basic searching

To search for work items in edoras one, use the search functionality provided by the edoras one toolbar.

Clicking on the triangle to the right of the search field opens a pull-down dialog where a number of common search settings can be selected. As these options are changed, the results of the search are shown in the list view:

Search dialog

Typing a plain text value into the search text field will also restrict the search results to work items that contain the given text, either in the name, in the description, or in a string attribute value.

2.5.2. More complex searching

In addition to plain text search, the search text field supports a query language that allows more complex queries to be created.

Search terms

A query consists of a list of search terms separated by whitespace:

<term1> <term2> <term3> …​

In the simplest case, a term can be a single word which performs a text search for work items that contain the given word. This is the basis for the search mechanism described in <basic-search>.

When searching, the search results from each term are combined with 'and', so each additional term restricts the search results more tightly.

To include whitespace in a search term, surround the search text with quotes (i.e. +'multiple word search').

More complex terms follow the pattern:

<termKey>:<expression>,<expression>,…​

where the term key defines the type of search to be performed, and the list of expressions defines the values to be matched.

The values matched by the expressions are combined with 'or', so each additional expression extends the list of search results.

Expressions may also consist either of a single value (e.g. 123) or be an operator / operand pair, also separated by a : (e.g. gt:123).

As an example, the search term priority:1,3,gt:5 will return all work items that have a priority of 1, 3 or any value greater than 5.

The following search term keys are currently supported by edoras one:

Table 2. Supported term keys
Term key Expression type Searches by

app

Model expression

user work items based on models from matching apps

assignee

User expression

assigned user

assigneeUpdated

Date expression

assignee update time

assignedGroup

Group expression

assigned group by id or group name

assignedGroupUpdated

Date expression

assigned group update time

candidateGroups

Group expression

candidate groups by id or group name

candidateUsers

User expression

candidate users

initialAssignedGroup

Group expression

initially assigned group

previousAssignedGroup

Group expression

previously assigned group

initialAssignee

User expression

initially assigned user

previousAssignee

User expression

previously assigned user

created

Date expression

creation date

dashboard

Dashboard expression

work item type (using dashboard shortcuts)

descendantsOf

ID

hierarchy

description

String expression

work item description

desc

String expression

work item description (alias for description)

due

Date expression

due date

for

User expression

assigned user (alias for assignee)

model

Model expression

user work items based on matching models

modelId

Model expression

user work items based on matching model global ID

externalId

ID

work object id in the external system

definitionId

ID

work object definition id

providerId

ID

work object provider id

name

String expression

work item name

owner

User expression

owner

parent

ID

hierarchy (alias for descendantsOf)

priority

Number expression

priority

state

State expression

state

text

String expression

textual content (the default search term key)

type

Type expression

work item type

updated

Date expression

last modified date

resubmissionTime

Date expression

resubmission date

stateUpdateTime

Date expression

state update date

globalId

ID

work object globalId

<variable name>

all

variable value

2.5.3. Sort terms

In addition to the search terms described above, a sort term may also be specified which allows the order of the search results to be specified. A sort term begins with sort:, is followed by an optional asc: (ascending, the default) or desc: (descending), and then the attribute to sort by. The following sort attributes are supported:

Table 3. Sort term values
Sort attribute Description

assignee

assignee (grouping only, no alphabetical sort)

creation

creation date

due

due date

modification

last modified date

name

work item name

owner

owner (grouping only, no alphabetical sort)

priority

priority

type

work item type

Examples
sort:desc:name
sort:creation

2.5.4. User expression

A user expression accepts the following operand values:

Table 4. User operand values
Operand value Matches

<ID>

the specific user ID (work object ID)

all

any assigned user

me

the current user

unassigned

unassigned work items (a value alias for the empty operator)

<text>

any user with the given text as part of the display name

The following operators are also supported:

Table 5. User operators
Value Matches

empty:

unassigned work items

Examples
owner:empty:
owner:all
owner:me
owner:joe

2.5.5. Date expression

The following date operators are supported:

Table 6. Date operators
Operator Operand value Matches

eq:

date

values equal to the given value (default)

gt:

date

values greater than the given value

gte:

date

values greater than or equal to the given value

lt:

date

values less than the given value

lte:

date

values less than or equal to the given value

range:

date..date

values in the given range (inclusive)

The following date specification formats are supported:

Table 7. Date specification formats
Format Description

yyyy-MM-dd

a specific date

[yY][mM][wW][dD]

a date relative to today in years, months weeks, or days

today

today’s date

Examples
created:today
created:lt:2014-02-14
updated:range:-2W..2W
Date values are currently interpreted in the UTC timezone, so a date-based search may occasionally contain unexpected results when viewed from a particular user’s local timezone.

2.5.6. Number expression

The following number operators are supported:

Table 8. Number operators
Operator Operand value Matches

eq:

<number>

values equal to the given value (default)

gt:

<number>

values greater than the given value

gte:

<number>

values greater than or equal to the given value

lt:

<number>

values less than the given value

lte:

<number>

values less than or equal to the given value

range:

<number>..<number>

values in the given range (inclusive)

Examples
priority:1,2
priority:gt:5

2.5.7. State expression

No special state operators are supported, only the following state operand values:

Table 9. State operand values
Operand value Matches

all

all states (no restriction)

open

open work items (active, pending, pending inactive)

active

active work items

inactive

inactive work items

pending

pending work items

'pending inactive'

pending inactive work items (quotes are required)

completed

completed work items

archived

archived work items

interrupted

interrupted work items

Examples
state:open
state:archived,completed

2.5.8. Type expression

No special type operators are supported, only the following operand values:

Table 10. Type operand values
Operand value Matches

CAS

cases

DOC

documents

TSK

tasks

QUERY

queries

APP

apps

CASE_MODEL

case models

DOCUMENT_MODEL

document models

FORM_MODEL

form models

MAIL_MODEL

mail models

PROCESS_MODEL

process models

TASK_MODEL

task models

APP_MODEL

app models

ACC

accounts

GRP

groups

USR

users

Examples
type:TSK,DOC

2.5.9. Dashboard expression

No special dashboard operators are supported, only the following operand values:

Table 11. Dashboard operand values
Operand value Matches

admin

accounts, groups, users & apps

modeler

models

user

cases, task, documents & queries

Dashboard terms are just a shortcut for a type term with the corresponding type list.

Examples
dashboard:user

2.5.10. String expression

The following string operators are supported:

Table 12. String operators
Operator Operand value Matches

contains:

<string>

values that contain the given substring

empty:

<string>

values that are not set

eq:

<string>

values that exactly match the given string (default)

Examples
name:example
description:empty:

2.5.11. Group expression

No special group operators are supported, only the following operand values:

Table 13. Group operand values

Operand value

Matches

<ID>

the specific group ID (work object ID)

unassigned

values that are not set

<text>

any group with the given text as part of the display name

Examples
assignedGroup:unassigned
initialAssignedGroup:example
candidateGroups:someGroup,someOtherGroup

2.5.12. Model expression

The following model operators are supported.

Table 14. Model operators
Operator Operand value Matches

contains:

<string>

values that contain the given substring (default)

eq:

<string>

values that exactly match the given string

The operand value is used to perform a name search on apps or models (depending on the term). For the app term, all models from the matching apps will be selected, for the model term only the matching models will be selected.

The search results will consist of all work items that were created from one of the selected models.

Examples
app:vacation
model:eq:'Vacation Request Case'
In order to retrieve the corresponding work items, permissions to access the corresponding models are needed.

2.5.13. Model ID expression

User dashboard work items can be searched for using a model global ID. A work item has two sets of model IDs:

  • design-time model IDs are the model IDs that were used to create the underlying definition for this work item. This includes the model ID of the parent App as well. This is set of IDs is fixed for each work item.

  • runtime model IDs includes the design time model IDs for all work items up to the root work item. This set of IDs can be understood as describing the models that provide the runtime context for a particular work item, and may change if the work item is moved to another context.

As an example, a ad-hoc task work item from "App 1" will have the following design-time model IDs:

  • the global ID for the "App 1" model

  • the global ID for the ad-hoc task model

If this task was created in the context of an adaptive case from "App 2" then the same work item will have the following runtime model IDs:

  • the global ID for the "App 2" model

  • the global ID for the adaptive case model

  • the global ID for the "App 1" model

  • the global ID for the ad-hoc task model

Table 15. Model ID operators
Operator Operand value Matches

design:

<string>

work items containing the given design-time model ID (default)

runtime:

<string>

work items containing the given runtime model ID

The search results will consist of all work items that were either created from the given model or are contained in the context of a work item from the given model.

Examples
modelId:CASE_MODEL-3cfc6c6a-082d-4f1e-a433-547fdf96d50c
modelId:runtime:CASE_MODEL-3cfc6c6a-082d-4f1e-a433-547fdf96d50c
This search term only applies to user dashboard work items, but no model access permissions are required as the search only requires access to the user dashboard work objects.

2.6. Glossary

app model

an app model is a container for a collection of models that define a specific workflow.

dashboard

a page in the edoras one application where work objects can be found, displayed and manipulated. Each dashboard manages related work object types that play a given role within the system.

model

a description of a workflow component which can be deployed together with other models to create a executable workflow in edoras one

operand

the value part of a search term expression.

operator

the optional first part of a search term expression which says how the operand value should be interpreted.

process

a process is a workflow definition, described using a BPMN 2.0 model and executed within edoras one. It typically defines the automated and manual tasks that must be performed to complete the workflow.

search term expression

part of a search term. A search term can contain multiple expressions, separated by commas. The result set for the term contains work items that match any of the operators. A search term expression contains an optional operator, and an operand value.

search term

part of a search query. The result set for the query contains work items that match all of the separate terms.

task

a task is a single action within a workflow, and may be either automated (a service task) or manual (a user task).

work object / work item

an item that can be created or manipulated in edoras one. Different types of work item are supported. The work object types are typically grouped according to their role within the system and accessed through dashboards.

3. edoras one Modeler Guide

3.1. Modeler Overview

The modeler dashboard can be accessed by authorized users through the dashboard menu and is used to create and deploy workflow models for use within edoras one.

Before we look at the details of the modeler dashboard it will help to understand how models are related to the work items in the user dashboard.

Models are created and edited in the modeler dashboard. When models are deployed, corresponding work object definitions are created. These definitions can be used in the user dashboard to create work objects of the new type (usually referred to as work items in the user context):

model workflow

After a model has been deployed to create a definition it may still be edited, for example to add new functionality or to fix a problem, but the changes that have been made will only become active when the App is deployed again. You can easily see whether an App has outstanding changes by checking the App status (see Model state).

A number of different model types are available as described in the following sections.

3.1.1. App model

An edoras one App model is a container for the models that combine to define a specific workflow within edoras one.

To define a workflow, first an App model is created and then the different models can be added and linked together as required. When the models defining the workflow are ready, the App can be deployed to create the corresponding definitions which can then be accessed from the user dashboard to execute the workflow. Only a complete App can be deployed as the models in the App should all be consistent if the deployed workflow is to function as intended.

App models can be transferred between different edoras one installations using the Export and Import actions.

3.1.2. Case model

In the user dashboard, a case serves as a container for all work items related to a workflow, such as documents, process executions (with the resulting tasks), ad-hoc tasks etc. Variables in the case work item can also be used to store information that needs to be shared by different parts of the workflow.

The case model typically uses init and work forms to create and manipulate the shared workflow information, and also defines the workflow actions that can or must be performed.

A case model may either be an adaptive case model or a CMMN case model.

With an adaptive case model, processes, tasks or documents will either be added automatically to a new case when is created or can be added manually later.

With a CMMN case model, the case lifecycle is defined using a CMMN 1.0 model and can be much richer than for an adaptive case model, including automatic state changes, milestones, processes, tasks etc.

3.1.3. Task model

A task model is used to define a new type of user task, corresponding to an action that needs to be performed by a participant in the workflow. Examples are entering / updating data or confirming that an external action has been performed.

3.1.4. Document model

A document model is used to define a new type of document. A skeleton document can be defined which will be used as a template when a new document of the given type is created, and placeholder substitutions can also be defined to insert values from the current context into the skeleton document.

3.1.5. Form model

A form model defines a form that can be used by other workflow models to interact with the user. Each form contains a number of form fields arranged in a given layout. The fields in a form may contain predefined content, or may be bound to the current work object values at runtime, for example to allow the name and description of a document to be displayed and perhaps changed.

Typically two types of forms are used: init forms are used to initialize new work objects, and work forms are used to edit existing work objects.

3.1.6. Process model

A process model allows a full BPMN 2.0 process execution model to be defined, describing a sequence of tasks to be performed either by the system itself (system tasks) or by users (user tasks). Conditional paths in the process allow the workflow to contain different tasks depending on the specific case being processed.

3.1.7. Mail model

A mail model provides a template for emails that can be sent by a given workflow. The mail model contains the templates for mail subject and header, both of which can use edoras one backend expressions to fill in the template with dynamic information at the time that the mail is sent.

3.2. Working with models

3.2.1. Accessing the modeler dashboard

All users that are part of the modeler group will be able to access the modeler dashboard. Please refer to the edoras one Administrator Guide for details on configuring group membership.

3.2.2. edoras vis

edoras vis is the built-in graphical modeler used to model BPMN 2.0 process models, edoras one form models and CMMN 1.0 case models.

The graphical modeler GUI consists of the following main areas:

edoras vis panels

The model editor panel contains the graphical view of the model being edited. New elements can be added to the diagram either by dragging them from the palette panel or in some cases using the contextual elements that appear when a model element is selected. The attributes for the selected model element are shown and may be edited in the attributes panel. The toolbar contains a number of useful tools for editing models, for example to insert more space into the middle of a model or to compare different model revisions.

3.2.3. Importing App models

An App model can be imported into the system by creating a new App through the user interface, and then using the Import action within the app to upload and import a Zip file containing the models to be imported.

When models are imported, the model will be checked to see whether it is already present on the system. If it is not present, then it will be created in the current App. If it is already present within the current App then it will be updated from the import file. If it is already present but as part of a different App then an error will be shown.

If a new model is created from scratch it is assigned an unchangeable ID which is used to track the model across all systems where the model is installed, and it is this ID which is used to establish the relationship between the models on the system and the models in the import file.

If the Import as duplicate option is selected when an App is imported the models in the imported App will not be checked against the models already present. New models will be created that are unconnected with the originals. This can be useful for creating a completely new App, using an existing App as a starting point.

3.2.4. Model state

Models have a state which changes as the models are edited and deployed. The available states are:

Table 16. Model states
State Applies to Description

active

Models

No pending changes. The model is currently deployed on the system.

inactive

Models except App model

No pending changes. The model has been deactivated on the system.

pending

Models

The model contains changes that have not yet been deployed.

pending inactive

Models except App model

The model will be deactivated on the system when it it next deployed.

The current state of a model is shown in the header bar for the model:

model state

3.2.5. Deploying an App model

When an App model is deployed, the models within that App model will be checked for consistency. If a model has been deactivated but there are still references from other active models then it will not be possible to deploy the App model. If the models are consistent then they will be deployed and corresponding definitions will be created. The users of the system will then be able to access the new workflow in the user dashboard.

Note that work objects and processes may already exist that were created using older versions of the model. These will not automatically be updated to use the new definitions: they will continue to use the definitions that were valid when they were created and will therefore not behave any differently after the new deployment.

3.2.6. Moving models between App models

All of the basic model types can be moved to another App as long as there are no outstanding references within the App model that it is being moved from.

3.2.7. Duplicating App models

All basic model types can also be duplicated, making an exact copy with a new name. This can be very useful when several small variations of a complex model are required.

3.2.8. Sharing models

Models may also be shared with different groups. By default all new models are shared with the modeler group, but in some circumstances it may be required for particular users to work on a particular set of models.

3.2.9. The System App

The administrator will also be able to see the System app in the modeler dashboard in addition to the App models that can be seen by normal modeler users. This App model contains a number of models that are required by the edoras one application and should normally not be changed.

3.3. Actions

Certain models are used to create user work items (e.g. Case, Task, Document). When created, the work item action toolbar (on the right hand side) will contain the actions that can be performed on the work item.

Which actions are available to the user depends on a number of factors:

  • the actions allowed by the model itself

  • the state of the work item

  • the user’s permissions

Some constraints are defined by edoras one itself and cannot be changed, but the model plays a large role in defining the available actions, and this should be considered carefully when designing a workflow.

To change the allowed actions, select the Browse view and add or remove actions as required in the Allowed Actions field:

allowedActions
Table 17. Actions
Action Case Task Document Description

Activate

Yes

Yes

Yes

Re-activate an archived work item

Archive

Yes*

No

Yes

Archived and active work item.

Assign

Yes

Yes

Yes

Change the work item’s owner / responsible

Create variables

Yes

Yes

Yes

Allow new variables to be created in the work item admin view

Download

No

No

Yes

Download the work item content

Download Pdf

No

No

Yes

Download the document in pdf format

Edit document

No

No

Yes

Edit the document

Move

No

No

Yes

Move the work item to another case

Preview

No

Yes

No

Show a work item preview

Share

Yes

Yes

Yes

Share the work item with specific groups

Start process

Yes

No

No

Start a new process instance

Update placeholders

No

No

Yes

Upload a new document

Upload document

No

No

Yes

Upload a new document

*There are three possibilities to archive cases which are displayed in the following table:

Table 18. Archive options for cases
Option Name Description

Archive only if there are no active children

If case contains active processes, tasks or documents archive action returns an error.

Archive only if there are only active documents

If case contains active processes or tasks archive action returns an error. Active documents are archived automatically.

Archive the case and all children

Active processes and tasks are interrupted and it is not possible to activate them again. Active documents are archived.

3.4. App model

An edoras one App model is a container for the specific models that combine to define a specific workflow within edoras one.

App models support the following settings:

Name

The name of the App

Primary language

The primary language to be used for the models in the App (i.e. the language used in base attribute values).

Secondary languages

Secondary languages that will be supported by the models in this App. When secondary languages are specified additional localization functionality will be enabled.

Description

Describes the purpose of the App. This is provided solely as information for modelers and does not have any runtime significance.

Group / User / Work Item Mappings

When an App is installed, the models may require references to other work objects outside of the App to function correctly, for example a specific user may have to be assigned to a particular role. Such references are specific will vary depending on the environment specific system, so the App model allows this information to be defined in a single location and then reused by different models.

Property Mappings

There may also be parameters that the modeler would like to be able to modify globally instead of hardwiring specific values into multiple models. This can be achieved using a property mapping. Properties defined in the App are accessible from all deployed definitions.

3.5. Case model

In the user dashboard, a case serves as a container for all work items related to a workflow, such as documents, process executions (with the resulting tasks), ad-hoc tasks etc. Variables in the case work item can also be used to store information that needs to be shared by different parts of the workflow.

All case models support the following settings:

Name

The name of the model

Description

Describes the purpose of the model. This is provided solely as information for modelers and does not have any runtime significance.

Model type

Either Adaptive Case Model or CMMN Case Model as required.

Init form

A reference to the initialization form model. This form is used to set the initial state of the case when a new case is created based on this model.

Work form

A reference to the work form model. This form is used to view and / or update the state of the case after it has been created.

Candidate Groups

The initial groups with which a newly created case will be shared.

Allowed Actions

The actions that may be performed on the case after it has been created.

3.5.1. Adaptive case model

In addition to the shared case model settings, adaptive case models support the following settings:

Autostart Processes

References the models for processes that will be started automatically in the context of a new case.

Autostart Tasks

References models for tasks that will be added automatically in the context of a new case.

Autostart Documents

References models for documents that will be added automatically in the context of a new case.

Ad-hoc Processes

References the models for processes that can be started manually in the context of a new case. If no models are selected then all process types will be supported.

Ad-hoc Tasks

References models for tasks that will be added manually in the context of a new case. If no models are selected then all task types will be supported.

Ad-hoc Documents

References models for documents that will be added manually in the context of a new case. If no models are selected then all document types will be supported.

3.5.2. CMMN case model

No additional specific settings are provided by CMMN case models

The CMMN model can be designed in edoras vis by using the Design action in the case model. For information on creating CMMN case models please refer to the CMMN Documentation.

3.6. Task model

A task model is used to define a new type of user task, corresponding to an action that needs to be performed by a participant in the workflow. Examples are entering / updating data or confirming that an external action has been performed.

Task models support the following settings:

Name

The name of the model

Description

Describes the purpose of the model. This is provided solely as information for modelers and does not have any runtime significance.

Init form

A reference to the initialization form model. This form is used to set the initial state when a new task is created based on this model.

Work form

A reference to the work form model. This form is used to view and / or update the state of the task after it has been created.

Candidate Groups

The initial groups with which a newly created task will be shared.

Allowed Actions

The actions that may be performed on the task after it has been created.

3.7. Document model

A document model is used to define a new type of document and supports the following settings:

Skeleton document

An optional skeleton document. The skeleton document will be copied into each new document work item as it is created, so each document instance will have its own separate copy. If placeholders are defined then these will also be substituted when the document is copied. Once a document model has been created, the skeleton can be managed using the Upload skeleton and Download skeleton actions.

Name

The name of the model

Description

Describes the purpose of the model. This is provided solely as information for modelers and does not have any runtime significance.

Init form

A reference to the initialization form model. This form is used to set the initial state when a new document is created based on this model.

Work form

A reference to the work form model. This form is used to view and / or update the state of the document after it has been created.

Candidate Groups

The initial groups with which a newly created document will be shared.

Allowed Actions

The actions that may be performed on the document after it has been created.

Placeholders

A placeholder has a key (which can be referenced from the skeleton document) and an expression which will be evaluated when a new document is created. The placeholders are evaluated and replaced in a copy of the skeleton document when a new document work item is created, allowing documents to be filled out automatically with dynamic text.

3.7.1. Placeholder expressions

Document models can define placeholder expressions that can be used to insert dynamic values into documents.

A placeholder definition consists of a key (which will be referenced from the document) and an expression that will be evaluated to give the corresponding value:

placeholders

The expression will be applied at the time that the placeholders are updated, i.e. either when the document is first created from the document model or when the Update placeholders action is used subsequently.

3.7.2. Referencing placeholders from a Microsoft Word document

In a Microsoft word document, placeholders may be referenced by inserting a form field into the document with a Bookmark name that corresponds to the placeholder key:

word placeholder

3.7.3. Referencing placeholders from an Adobe PDF document

In a PDF document, placeholders may be referenced by inserting a form field into the document with a name that corresponds to the placeholder key:

pdf placeholder
A suitable PDF editing tool is required to create PDF documents with form fields.

3.7.4. Microsoft Word Mailing support

Microsoft Word documents support mailings functionality. Mailings fields can be replaced in a similar way as placeholders with document variable values. The fields have to be encapsulated into TableStart/End tags (Mailings regions support). variableName tag is replaced by variable value on update placeholders action.

wordMailings

More information is available about merge mails from the following links:

3.7.5. Microsoft Word Linq support

Microsoft Word documents support the Linq query language. The platform uses Aspose to provide the basic Linq functionality and we integrated our own data retrieval mechanism to support the already known backend expressions. Please read the mentioned links below to familiarize yourself with the Linq expressions and how they are interpreted.

The following snippet of a Word document show some examples of how to use Linq in combination with the work object structure and the backend expressions:

Single String value:

    <<[linq.value("#{name}")]>>

Conditions:

    <<if [linq.booleanValue("#{priority > 10}")]>>
        Condition: <<[linq.value("#{priority}")]>>
    <</if>>

Iterations:

    <<foreach [item in linq.foreach("#{itemsList}")]>>
        Item: <<[item]>>
    <</foreach>>

Nested iterations:

    <<foreach [item in linq.foreach("#{listInList}")]>>
        Item:
	    <<foreach [innerItem in linq.foreach(item)]>>
		    Inner item: <<[ innerItem]>>
        <</foreach>>
    <</foreach>>

Iterations with list of maps:

    <<foreach [item in linq.foreach("#{mapItems}")]>>
        Map Value 'a': <<[linq.value("#{a}", item)]>>
        Map Value 'b': <<[linq.value("#{b}", item)]>>
        Merged value: <<[linq.mergedValue("#{name.concat(' - ').concat(a)}", item)]>>
    <</foreach>>

In the above examples we use the linq key word (or context) to get the values and iterate over lists which are retrieved by a backend expression. This linq context is used to get the data from the backend expressions to be processed by Linq. In the following list you see all available methods on the linq context and what their purposes are:

Table 19. linq methods
Method Expression context Return value Default return value Purpose

value(String expression)

Document work object

Object

Empty String

Evaluates the expression and returns the resolved value.

value(String expression, Map contextObject)

Specified contextObject

Object

Empty String

Evaluates the expression based on the contextObject and returns the resolved value.

mergedValue(String expression, Map contextObject)

Document work object and specified contextObject

Object

Empty String

Evaluates the expression based on the document work object merged with the contextObject and returns the resolved value.

stringValue(String expression)

Document work object

String

Empty String

Evaluates the expression and returns the resolved value.

stringValue(String expression, Map contextObject)

Specified contextObject

String

Empty String

Evaluates the expression based on the contextObject and returns the resolved value.

mergedStringValue(String expression, Map contextObject)

Document work object and specified contextObject

String

Empty String

Evaluates the expression based on the document work object merged with the contextObject and returns the resolved value.

longValue(String expression)

Document work object

long

-1L

Evaluates the expression and returns the resolved value.

longValue(String expression, Map contextObject)

Specified contextObject

long

-1L

Evaluates the expression based on the contextObject and returns the resolved value.

mergedLongValue(String expression, Map contextObject)

Document work object and specified contextObject

long

-1L

Evaluates the expression based on the document work object merged with the contextObject and returns the resolved value.

doubleValue(String expression)

Document work object

double

-1.0D

Evaluates the expression and returns the resolved value.

doubleValue(String expression, Map contextObject)

Specified contextObject

double

-1.0D

Evaluates the expression based on the contextObject and returns the resolved value.

mergedDoubleValue(String expression, Map contextObject)

Document work object and specified contextObject

double

-1.0D

Evaluates the expression based on the document work object merged with the contextObject and returns the resolved value.

booleanValue(String expression)

Document work object

boolean

false

Evaluates the expression and returns the resolved value.

booleanValue(String expression, Map contextObject)

Specified contextObject

boolean

false

Evaluates the expression based on the contextObject and returns the resolved value.

mergedBooleanValue(String expression, Map contextObject)

Document work object and specified contextObject

boolean

false

Evaluates the expression based on the document work object merged with the contextObject and returns the resolved value.

foreach(String expression)

Document work object

Iterable

Empty list

Evaluates the expression and returns the resolved list.

foreach(Object object)

No context

Iterable

No default value

Checks if the specified object is a map and takes out the first element and assumes it is a list. If the object is a list it will return the list right away.

In the merged* methods the specified contextObject is preferred over the document work object. This means that when the document work object has a variable a and the contextObject map has an entry with key a, then the value of the contextObject will be used and not the variable value of the document work object.

You can also check the com.edorasware.cloud.core.service.document.word.LinqContext class to see the details of our implementation.

More information about Linq is available at the following links:

3.8. Form model

A form model defines a form that can be used by other workflow models to interact with the user.

Form models support the following settings:

Name

The name of the model

Description

Describes the purpose of the model. This is provided solely as information for modelers and does not have any runtime significance.

The form layout can be quickly checked in edoras one by hovering over the form model in the App’s model list, previewed within the form model using the Preview view or edited in the edoras vis modeler using the Design action. It is also possible to download the form definition using the Download action.

The following sections describes the elements available in the form palette of edoras one. Each modelling element and its corresponding attributes are described in detail below.

3.8.1. Concepts

This section describes the form concepts in edoras one. It starts with a description of how the layout of forms and fields works in edoras one. Then it describes how a form and its fields are bound to the data model.

Form layout

A form is a graphical layout of fields that may be bound to a data model to allow this data model to be displayed to the user. The fields are arranged in rows.

formLayout
Figure 2. Form layout

Each row is made up of exactly twelve slots. All slots are equal in size, so the width of a slot is one twelfth the width of the whole form. A field can occupy exactly all slots or it can occupy only a part of the slots. With this it is possible to place more than one field in a row.

formLayoutWithSlots
Figure 3. Form layout with slots

Not every slot needs to be occupied by a field. It is allowed that single slots of a row are empty. These empty slots can be at the beginning, in the middle, or at the end of a row.

formLayoutWithEmptySlots
Figure 4. Form layout with empty slots
Field layout

A field is made up of several parts (all but the widget part are optional):

widget

The widget visualizes the data model. Most widgets are interactive and let the user change the data model, however some widgets are read-only. There are widgets to manipulate strings, numbers, dates, rich text, selections, and many others. The widget is located in the center of the field, all other parts are arranged around the widget. The field configuration defines the concrete positioning of the field parts.

Label

The label tells the user to which part of the data model the widget is bound. The label is located on the left side or on top of the widget (depends on the field configuration).

Required indicator

The required indicator is displayed for required fields. Required means that the widget cannot be empty. The required indicator is located on the right side of the widget.

Description

The description gives additional information to the user. This can be formatting instructions or further description about how the App uses the entered value. The description is located on the bottom of the widget.

fieldLayout
Figure 5. Field layout
Field alignment

To enhance the readability of a form, the field parts of all fields are aligned among themselves: the labels are aligned, the widgets and descriptions are aligned, the required indicators are aligned.

The alignment is performed per slot. All fields that start in the same slot build a field group. Inside such a field group edoras one looks for the widest label which becomes the dominating label for that slot. All labels in the field group are then enlarged to the same width of the dominating label. This is done by adding empty space between the label and the widget. This ensures that all widgets and descriptions of a field group start in one line and all.

fieldAlignment
Figure 6. Field alignment

The only exception is with fields that have top label position. For these fields the label, the widget and the description all start at the beginning of the slot.

fieldAlignmentTop
Figure 7. Field alignment with top label position
Binding

Binding is the process to connect the form fields to the data model. The binding in edoras one is always two-way. When the user changes the form fields then those changes are immediately propagated to the data model. On the other side changes in the data model are immediately propagated back to the form fields.

A binding expression defines to which part of the data model the form field is connected. The binding expression has to be a writable frontend expression, e.g. {{foo}}, {{case.bar}}.

There are some reserved expressions which cannot be used as they are used internally to save some work item information. The reserved frontend expressions are:

  • id

  • definitionId

  • definition

  • type

  • state

  • creationTime

  • updateTime

  • currentUser

Moreover the expressions referring to the hierarchy (e.g. root, parent) can be only be used in order to bind nested widgets like subforms.

3.8.2. Common attributes

There are several attributes that are available for all form widgets. These common attributes define the rendering and the layout of the form field, as well as the part of the data model to which the form field is bound.

Attribute name Description

Label

The label is a single word or term that describes the purpose of the form widget. When the form is rendered, the label is located either on the left side or on top of the widget (depends on the value of the Label position attribute).

Typical labels are: First name, Last name, Sex, Address, ZIP code, City.

Labels can be localized. See Localization to learn how to localize your Apps.

Label position

The label position relative to the widget, can be either Left or Top.

Value

The value connects the form field to the data model. As such the value decides which part of the data model the form field visualizes and which part of the data model is updated when the user interacts with the widget.

See Binding to learn how binding in edoras one works.

Default value

The default value is the value that is applied when the data model is undefined, i.e. not yet initialized. The default value can be expressed as a static value or as a frontend expression.

Typical default values are: Support (= string), false (= boolean), 42 (= number), Comment from {{role}} (= frontend expression).

See Frontend expressions to learn the frontend expression syntax.

Description

The description is a whole sentence that describes the purpose of the form widget in more detail. When the form is rendered, the description is located below the widget.

A typical description is: The ZIP file format is ##, e.g 4143. The ZIP is used to lookup the city.

Descriptions can be localized. See Localization to learn how to localize your Apps.

Documentation

Intended for documenting details about specific widget to explain concepts of its use for future reference.

Visible

The visible flag decides if the form field is shown or hidden. If true, the form field is shown, if false the form field is hidden. The visible flag is a runtime value which means you can configure a frontend expression for it.

A typical frontend expression for the visible flag is: {{case.showDeliveryAddress}}

See Frontend expressions to learn the frontend expression syntax.

Editable

The editable flag decides if the form widget is editable or read-only. If true, the user can manipulate the form widget to change the data model, if false the user is not able to change the data model. The editable flag is a runtime value which means you can configure a frontend expression for it.

A typical frontend expression for the editable flag is: {{case.step1Completed}}

See Frontend expressions to learn the frontend expression syntax.

Style class

The style class allows to add additional CSS styles to the form field.

3.8.3. Validation attributes

A validation method checks if a widget contains valid data, if not edoras one displays an error message that instructs the user how to fix his input. edoras one supports many different validation methods, not all are available for all form widgets.

Validation is only done if the user is able to fix a potential validation error. This is not the case for hidden and read-only form fields, so such fields are not validated.

The following table lists the supported validation methods.

Attribute name Description

Required

The required flag defines if a form field can be empty or not. If true then the form field is not allowed to be empty, if false the form field might be empty.

A typical sample where the required flag is set to true is a name field that is mandatory.

The following form widgets support the required flag: text, text area, rich text area, password, number, date, checkbox, autocomplete, select, radio buttons.

Minimum length

The minimum length validation ensures that the text input is longer than a minimum length.

A typical sample is a password that has to be at least 4 characters long.

The following form widgets support the minimum length validation: text, text area, rich text area, password.

The Minimum length error message attribute holds the error message that is displayed when the text input is less than the configured number of characters.

Maximum length

The maximum length validation ensures that the text input has a smaller than a maximum length.

A typical sample is a password that has to be at most 8 characters long.

The following form widgets support the minimum length validation: text, text area, rich text area, password.

The Maximum length error message attribute holds the error message that is displayed when the text input is bigger than the configured number of characters.

Regular expression

The regular expression validation ensures that the text input matches a regular expression. See http://www.w3schools.com/jsref/jsref_obj_regexp.asp for more information on the supported regular expression syntax. Regular expression can be become quite complex and difficult to understand. http://www.regular-expressions.info/javascriptexample.html provides a good way to test your regular expressions.

A typical sample is the number of a credit card which matches: ^4[0-9]{11,12}(?:[0-9]{3})?$.

The following form widgets support the regular expression validation: text, text area, rich text area, password.

The Regular expression error message attribute holds the error message that is displayed when the text input does not match the regular expression.

Mask

The mask validation ensures that the text input adhere to a certain pattern. The mask can contain the following special characters: * a - Represents an alpha character (A-Z,a-z) * 9 - Represents a numeric character (0-9) * * - Represents an alphanumeric character (A-Z,a-z,0-9) * all other characters are treated as fixed input

A typical sample is the expiry date of a credit card which is the month followed by a dash followed by the year. The mask that adheres to this pattern is 99/9999.

The text form widget supports mask validation.

The Mask error message attribute holds the error message that is displayed when the text input does not match the mask.

Minimum

The minimum validation ensures that the number input is equals to or bigger than a minimum.

A typical sample is an order quantity field which has to be equals to or bigger than 1.

The number form widget supports the minimum validation.

The Minimum error message attribute holds the error message that is displayed when the number input is less than the configured minimum.

The minimum number supported is -9007199254740991.

Maximum

The maximum validation ensures that the number input is equals to or less than a maximum.

A typical sample is an order quantity field which has to be equals to or lower than 100.

The number form widget supports the minimum validation.

The Maximum error message attribute holds the error message that is displayed when the number input is bigger than the configured maximum.

The maximum number supported is 9007199254740991.

Minimum date

The minimum date validation ensures that the date input is equals to or after a minimum date. The minimum date can be a fixed date, today, or a day relative to today.

A typical sample is an delivery date field which has to be equals to or after today.

The date form widget supports the minimum date validation.

The Minimum date error message attribute holds the error message that is displayed when the date input is before the configured minimum date.

Maximum date

The maximum date validation ensures that the date input is equals to or before a maximum date. The maximum date can be a fixed date, today, or a day relative to today.

A typical sample is a birthday field which has to be equals to or before today.

The date form widget supports the maximum date validation.

The Maximum date error message attribute holds the error message that is displayed when the date input is after the configured maximum.

Invalid selection error message

This validation displays an error message when the selection input is not available anymore.

The autocomplete and the select widgets support the invalid selection validation.

Both form widgets look up if the selection is in the available options to check if the selection is valid or not.

Minimum number of elements

The minimum number of elements validation ensures that the input contains at least a certain number of elements.

A typical sample is an order which has to contain at least one order position.

The subform widget and the autocomplete widget with multi-selection supports the minimum number of elements validation.

The Minimum number of elements error message attribute holds the error message that is displayed when the input contains less than the configured number of elements.

Maximum number of elements

The maximum number of elements validation ensures that the input contains at most a certain number of elements.

A typical sample is a wish list which can hold at most ten wishes.

The subform widget and the autocomplete widget with multi-selection supports the maximum number of elements validation.

The Maximum number of elements error message attribute holds the error message that is displayed when the input contains more than the configured number of entries.

Minimum number of attachments

The minimum files validation ensures that not less than a certain number of files are attached.

A typical sample is a support incident attachment field where at lease one screenshot has to be attached.

The attachment form widget supports the minimum files validation.

The Minimum number of attachments error message attribute holds the error message that is displayed when the attachment input has less files attached than the configured number.

Maximum number of attachments

The maximum files validation ensures that at not more than a certain number of files are attached.

A typical sample is a favourite images attachment field where not more than ten images can be attached.

The attachment widget supports the maximum files validation.

The Maximum number of attachments error message attribute holds the error message that is displayed when the attachment input has more files attached than the configured number.

Minimum number of rows

The minimum number of rows validation ensures that not less than a certain number of rows are displayed.

A typical sample is a list which has always the same name of rows even they are empty.

The list form widget supports the minimum number of rows validation.

Maximum number of rows

The maximum number of rows validation ensures that at not more than a certain number of rows are displayed.

A typical sample is a wish list which can hold at most ten wishes.

The list form widget supports the maximum number of rows validation.

3.8.4. Text form widgets

The text form widgets allow the user to input text. To support different text input requirements edoras one provides different text form widget variants. The following list explains the different text form widget variants:

Form widget Description
formComponentText

Used to input a single line of regular text.

formComponentTextRuntime
formComponentTextArea

Used to input multiple lines of regular text.

formComponentTextAreaRuntime
formComponentRichTextArea

Used to input multiple lines of rich text.

In contrast to regular text, rich text can be formatted in various ways: regular, bold, italic, ordered list, unordered list, headings, and much more.

formComponentRichTextAreaRuntime
formComponentPassword

Used to input a password.

The password form widget is marked with a small key icon at the right border of the widget. To hide the typed text from curious people all typed characters are visualized as dots.

formComponentPasswordRuntime
formComponentIntegralNumber

Used to input an integral number.

The integral number form widget is marked with a small hash icon at the right border of the widget.

formComponentNumberRuntime

We should to be aware that Javascript number has a limited precision (64-bit binary format IEEE 754 value).

It does not support a negative exponential notation like 1e-2 but can support positive exponential notation like 1e+2.

formComponentFloatNumber

Used to input a floating point number.

The float number form widget is marked with a small hash icon at the right border of the widget.

formComponentFloatRuntime

We should to be aware that Javascript number has a limited precision (64-bit binary format IEEE 754 value). So if, for example, we have a number with too many decimals, which cannot be represented, it will be rounded.

formComponentDate

Used to input a date.

The date form widget is marked with a small calendar icon at the right border of the control. All non date input is treated as invalid.

The user can enter a date in two ways. First he can enter the date as date string, e.g. 1970-11-25. Second he can use a date picker to select a date with the mouse. The date picker pops up as soon as the date control receives focus.

formComponentDateRuntime
formComponentComment

Used to input work object comments.

Do not change default variable name. Variable name create binding for the comment handling. Comments can be only added during create, complete and save work object events.

Text attributes
Attribute Description

Common

See Common attributes to learn more about the common attributes.

Validation

The text form widget supports the required, the minimum length, the maximum length, the regular expression, and the mask validation.

See Validation attributes to learn more about validation.

Text area attributes
Attribute Description

Common

See Common attributes to learn more about the common attributes.

Validation

The text area form widget supports the required, the minimum length, and the maximum length validation.

See Validation attributes to learn more about validation.

Rich text area attributes
Attribute Description

Common

See Common attributes to learn more about the common attributes.

The Default value attribute of a Rich text area form widget is rich text which supports the following formatting options (see toolbar buttons on top of the default value editor):

  • bold, italic, and underline text style

  • font size

  • foreground and background color

  • left, center, and right text alignment

  • headline, sub-headline, and section headline style

  • ordered and unordered list

  • text indentation

  • horizontal line

  • links

formComponentRichTextAreaDefaultValue

Validation

The rich text area form widget supports the required, the minimum length, and the maximum length validation.

See Validation attributes to learn more about validation.

Password attributes
Attribute Description

Common

See Common attributes to learn more about the common attributes.

Validation

The password form widget supports the required, the minimum length, and the maximum length validation.

See Validation attributes to learn more about validation.

Integral number attributes
Attribute Description

Common

See Common attributes to learn more about the common attributes.

*Default property: it only supports a frontend expression or an integral number without format.

Validation

The number form widget supports the required, the minimum, and the maximum validation.

The maximum value for a number is 9007199254740991. The minimum value for a number is -9007199254740991.

See Validation attributes to learn more about validation.

Format

Defines the format of the number with thousand and decimal separators. "No format" will not apply any format.

Format "auto" will apply the format depending on the language of the current user. With Format "auto", if the language is English, it will apply "1,000,000" format. With Format "auto", if the language is Spanish, German or Italian it will apply "1.000.000" format. With Format "auto", if the language is French, it will apply "1 000 000" format.

Float number attributes
Attribute Description

Common

See Common attributes to learn more about the common attributes.

*Default property: it only supports a frontend expression or a number without format.

Validation

The float number form widget supports the required, the minimum, and the maximum validation.

The maximum value for a number is 9007199254740991. The minimum value for a number is -9007199254740991.

See Validation attributes to learn more about validation.

Fraction size

Defines the maximum number of decimal characters for float type.

If fraction size is bigger than 0, exponential notation is not supported. If fraction size is 0, it will behave like integer number widget.

Format

Defines the format of the number with thousand and decimal separators. "No format" will not apply any format.

Format "auto" will apply the format depending on the language of the current user. With Format "auto", if the language is English, it will apply "1,000,000.22" format. With Format "auto", if the language is Spanish, German or Italian it will apply "1.000.000,22" format. With Format "auto", if the language is French, it will apply "1 000 000,22" format.

Date attributes
Attribute Description

Common

See Common attributes to learn more about the common attributes.

The default value of a date field form field can be specified as absolute date, as relative date, or as frontend expression.

formComponentDateDefaultValue

Validation

The date form widget supports the required, the minimum date, and the maximum date validation.

See Validation attributes to learn more about validation.

Format

Used to define the format in which the date is visualized to the user. If empty then the date is presented in the ISO 8601 format, e.g. 1970-11-25.

See Formatting dates in frontend expressions to learn more about the possible format strings.

Number of visible years

Used to define the range of years displayed in the year drop-down.

formComponentDateRuntimeYearRange

3.8.5. Select form widgets

The select form widgets allow the user to select one or more options from a potential large set of options. The available options are presented in a list from which the user can select one or more options with help of the keyboard and the mouse.

Some select form widget support the filtering of the available options. When the user starts typing then only the options that match the typed text are presented as available options. This makes it easy to locate a specific option in a large set of options.

The select form widgets are very powerful form widgets. To support different selection requirements edoras one provides different variants of select form widgets. The following list explains these variants:

Form widget Selection Options Description
formComponentCheckbox

Single

Boolean true/false

Used to select a simple yes/no option.

When the checkbox is ticked then true is stored in the data model, otherwise false is stored in the data model.

formComponentCheckboxRuntime
formComponentRadioButtonGroup

Single

Static options

Used to select a single option from a static list of options.

At design time the modeler configures for each option a name and a value. The name is displayed to the user whereas the value is stored in the data model.

In the radio button form widget all options are always visible. With this the user can always see all possible option, on the other side this uses a lot of form real estate and is therefore suited only it there are few options.

formComponentRadioButtonGroupRuntime
formComponentSingleSelect

Single

Select options

Used to select one option from a list of options.

The list of options is built at runtime by querying edoras one (datasource = Query) or any other rest service (datasource = Rest) or defined at design time (datasource = Static).

formComponentSingleSelectRuntime
formComponentMultiSelect

Multiple

Select options

Used to select one or more options from a list of options.

The list of options is built at runtime by querying edoras one (datasource = Query) or any other rest service (datasource = Rest) or defined at design time (datasource = Static).

formComponentMultiSelectRuntime
The Radio button group is recommended when there are few options while the Single Select is recommended when there are more options or there is not much space available in the form.
Checkbox attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

Validation

The checkbox form widget supports the required validation.

See Validation attributes to learn more about validation.

Radio button group attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

Validation

The radio button group form widget supports the required validation.

See Validation attributes to learn more about validation.

Options

Defines the options from which the user can choose. Each option has a name and a value: the name is shown to the user whereas the value is stored in the data model.

formComponentOptions

Orientation

Defines if the single radio buttons in the group are Horizontal or Vertical aligned.

formComponentRadioButtonGroupRuntimeVertical
Select attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

Setting $options as default value will make that all the available options are set by default in the component. Setting $options[0] will select the first available option.
To select one specific option please use only the id (see Identity). Eg. defaultValue = GEAR-a65c4a12-20b4-45d8-bb09-2105be7f0d1f. To select more than one item by id please type the ids separated by commas. Eg. defaultValue = GEAR-1,GEAR-2.

Validation

The Select form widget supports the following validations:

  • Required.

  • Invalid selection.

  • Minimum number of elements.

  • Maximum number of elements.

See Validation attributes to learn more about validation.

Placeholder

Used to set up the placeholder text. The component shows the placeholder text until the field is focused upon, then hides it.

Enable autocomplete

When checked the user will be allowed to write text in the component, this text is then used to filter the options to those that match the text.

Input minlength

The minimum number of characters the user needs to write inside the component before any option is shown. When it’s set to 0 the component dropdown appears immediately when the component gets the focus.

Storage

When it’s set to Id only the attribute defined in Identity will be persisted in the data model. When it’s set to Full the whole object will be saved as it’s returned from the rest service.

This attribute is not available when datasource is Static.

Datasource

Used to set up the source of the options.

Possible values are:

  • Rest ⇒ Data from any Rest service

  • Query ⇒ Data from edoras one

  • Static ⇒ Data defined on model time

Each option requires a different set of attributes.

Static Select specific attributes
Attribute name Description

Options

Defines the options from which the user can choose. Each option has a name and a value: the name is shown to the user whereas the value is stored in the data model.

formComponentOptions
Rest Select specific attributes
Attribute name Description

Query URL

Used to load the available options that are presented to the user from a URL.

The query URL attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

The autocomplete form widget expects the options to be returned as list of JSON objects, e.g.

[ {
  "id" : "GEAR-a65c4a12-20b4-45d8-bb09-2105be7f0d1f",
  "title" : "edoras one Modeler",
  "value" : "GEAR-a65c4a12-20b4-45d8-bb09-2105be7f0d1f"
}, {
  "id" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac",
  "title" : "edoras one User",
  "value" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac"
} ]

The user typed text can be used in the expression as {{$searchTerm}}. If it’s not set in the Query URL it will be added as a URL parameter.

https://one.edorasware.com/rest/one-groups?typedText=edoras

Usually the REST endpoint uses the typed text to filter the available options. This way the user sees only the options that match the already typed text and can easily locate single options in a large set of options.

The options are filtered in the REST endpoint and not in the autocomplete form widget. If the REST endpoint does not do the filtering then independent of the typed text the autocomplete form widget always presents the same options to the user.
Referencing external resources may have problems due to SSL (https) or CORS security browser limitations. To solve CORS security, the resource server must send appropriate response headers. Another option is using a proxy to receive the right response headers from any url e.g .:https://cors-anywhere.herokuapp.com. To solve SSL if edoras one is being executed over https, the url of the external resource should also have the https protocol.
The URL is encoded automatically so it shouldn’t be encoded.

Lookup URL

Used for two things:

  • first: to load the complete information of the selected options (only if they are stored in serialized form in the data model)

  • second: to validate if the selected options are still available, see Validation attributes to learn more about this validation

The lookup URL can use expressions but the only available attribute from the selected option is {{$item.id}}. The id attribute of the selected option must be set in Identity (see next point). If {{$item.id}} is not set in the lookupUrl, the id is appended to the lookup URL, e.g.

https://one.edorasware.com/rest/one-groups/GEAR-a65c4a12-20b4-45d8-bb09-2105be7f0d1f

The option is serialized with help of the Identity. So the Lookup URL and the Identity attribute have to play together.

The URL is encoded automatically so it shouldn’t be encoded.

Identity

Used to select the attribute in the JSON option that is stored in the data model.

So if the JSON option looks like

{
  "code" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac",
  "title" : "edoras one User",
  "value" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac"
}

and Identity = code then GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac will be stored in the data model.

Please note that the Identity, the Query URL, and the Lookup URL attributes have to play together. The Identity converts the JSON options returned by the Query URL REST endpoint into strings which then are stored in the data model. And the Lookup URL REST endpoint does the opposite: it takes the strings stored in the data model and converts them back into JSON options.

Format

Used to compose a user friendly string from the JSON option.

I allows frontend expressions. The selected option is available as $item.

So if the JSON option looks like

{
  "id" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac",
  "title" : "edoras one User",
  "value" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac",
  "type": "TSK"
}

then a format of Group: {{$item.type}} - {{$item.title}} results in Group: TSK - edoras one User being presented to the user for this JSON option.

Navigation URL

Used to set a link icon to the left of each option in the list and each selected option. The Navigation URL defines the URL to navigate to when the user clicks a link icon.

The navigation URL attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

The prefix to select an attribute from the JSON option is $item.

So if the JSON option looks like

{
  "id" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac",
  "title" : "edoras one User",
  "value" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac"
}

then a navigation URL of /GRP/{{$item.id}}/browse results in /GRP/GEAR-3456061f-4892-4ef4-b234-69217201cd09/browse being invoked when the user clicks the link icon.

formComponentAutocompleteRuntimeLink

Target

Used to define the tab where the linked option is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Query Select specific attributes
Attribute name Description

Search query

The edoras one query that is used to load the available work items that are presented to the user.

The user typed text is added as additional filter to the configured query.

Typical queries:

type:CAS for:me

all cases that are assigned to me

type:TSK for:me,unassigned

all tasks that are either directly assigned to me or are unassigned

type:CAS app:foo

all cases that belong to the foo App

See section Searches in the User guide to learn more about the search syntax and about all possible search terms.

Format

Used to compose a user friendly string from the work item.

The prefix to select an variable from the work item item. Literals have to be enclosed in quotes, attributes and literals can be concatenated with +.

So if the format is Group: {{item.name}} then the work item is shown to the user as Group: edoras one User.

Navigation view

Used to set the target view for the link.

Possible values are:

  • Browse ⇒ The link points to the form view of the work item

  • Preview ⇒ The link points to the preview view of the work item

Target

Used to define the tab where the linked work item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

3.8.6. Read only form widgets

The read only form widgets allow to present information, to add navigation functionality, and to split a form into section.

Form widget Description
formComponentOutputTextArea

Used to show static rich text.

The rich text can be formatted in various ways: regular, bold, italic, ordered list, unordered list, headings, and much more.

formComponentOutputTextAreaRuntime
formComponentHTMLComponent

Used to render html code.

formComponentListRest

Used to show a list of options that are returned by a custom REST endpoint.

The dynamic list of options is build at runtime by calling a custom REST endpoint that the modeler has configured. The rest list form widget can be used to enable simple navigation inside your App. For this the modeler can configure the links that are followed when the user clicks one of the options in the list.

formComponentListRestRuntime
formComponentList

Used to show a list of work items that are returned by edoras one.

The dynamic list of work items is build at runtime by calling calling edoras one with a query that the modeler has configured. The rest list form widget can be used to enable simple navigation inside your App. For this the modeler can configure the links that are followed when the user clicks one of the options in the list.

formComponentImage

Used to show an image.

formComponentImageRuntime
formComponentLink

Used to show a generic link.

formComponentLinkRuntime
formComponentCreateLink

A link which navigates to a specific initialization form for a new work item to be created based on a given model you can select in the work item model attribute

formComponentCreateLinkRuntime
formComponentSearchLink

Used to show a link that navigates to a list of work items returned by a search using a specified query.

formComponentSearchCountLink

A link which renders a text including the numbers of elements returned by a count query you can specify.

The link text can be configured to show the number of elements returned by the query. Clicking the link navigates to the result of the query.

formComponentCreateCountLinkRuntime
formComponentRestSearchCountLink

A link which renders a text including the numbers of elements returned by a REST endpoint.

The link text can be configured to show the number of elements returned by the REST query. Clicking the link navigates to the result of the REST query.

formComponentLinkQueryRestRuntime
formComponentButton

Used to show a button that points to a generic URL.

formComponentLinkButtonRuntime
formComponentCreateButton

A button with a link which navigates to a specific initialization form for a new work item to be created based on a given model you can select in the work item model attribute.

formComponentDynamicLinkButton

A button which calls a REST endpoint to obtain dynamic navigation information. When pressed, the REST endpoint will be invoked and the response used to navigate to a specific work item view.

formComponentRestButton

A button which calls a REST endpoint and loads the resulting JSON object into the bound variable.

formComponentCMMNButton

A button which, providing the model id of a plan item which has manual activation or an user event listener, has the same functionality than an CMMN action. Note that the button is only displayed in a CMMN template and if the action is available.

formComponentButtonGroup

A container that can only contain button widgets and has properties which affect the group of buttons contained.

formComponentButtonGroupRuntime
formComponentHorizontalLine

Used to show a horizontal line.

The Horizontal line form widget is useful to structure large forms by splitting the form into sections, e.g. basic information, detail information, address, …​

formComponentHorizontalLineRuntime
formComponentIframe

A view to display content from a given source through an iframe.

formComponentPdfPreview

Used to preview documents as pdf. It can preview formats like doc or txt in addition to pdf.

the functionality of the REST list and the List form widgets is similar. The only difference is that the REST list form widget uses a custom REST endpoint to load the displayed items (which can be of any format) whereas the List form widget uses edoras one to load the displayed work items.
the functionality of the REST query link and the Query link form widget is similar. The only difference is that the REST query link form widget uses a custom REST endpoint to load the number of found elements whereas the Query link form widget uses edoras one to load the number of found elements.
the functionality of the Link and the Link button as well as the Query link and the Query link button is similar. The only difference is that the Link and the Query link form widgets are rendered as links whereas the Link button and the Query link button form widgets are rendered as buttons.
Output text area attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Output text area form widget does not support the Default value and the Editable attribute, as these do not make sense for read only widgets.

The Value attribute of a Output text area form widget is rich text which supports the following formatting options (see toolbar buttons in the image below): bold, italic, and underline text style, font size, foreground and background color, left, center, and right text alignment, headline, sub-headline, and section headline style, ordered and unordered list, text indentation, horizontal line, links.

formComponentOutputTextAreaValue
HTML attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The HTML widget does not support the value, default value and the editable attributes, as these do not make sense for read only widgets.

Content

Defines the content of the html.

The "Content" attribute of an HTML widget is a plain text for writing html code. It may include front-end expressions.

Border

Defines if it will show a wrapper border.

REST list attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The REST list form widget does not support the Value, the Default value and the Editable attribute, as these do not make sense for read only widgets.

Query URL

Used to load the items that are presented to the user from a URL.

The query URL attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

The list form widget expects the items to be returned as list of JSON objects, e.g.

----
[ {
  "id" : "GEAR-a65c4a12-20b4-45d8-bb09-2105be7f0d1f",
  "title" : "edoras one Modeler",
  "value" : "GEAR-a65c4a12-20b4-45d8-bb09-2105be7f0d1f"
}, {
  "id" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac",
  "title" : "edoras one User",
  "value" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac"
} ]
----
Referencing external resources may have problems due to SSL (https) or CORS security browser limitations. To solve CORS security, the resource server must send appropriate response headers. Another option is using a proxy to receive the right response headers from any url e.g .:https://cors-anywhere.herokuapp.com. To solve SSL if edoras one is being executed over https, the url of the external resource should also have the https protocol.
The URL is encoded automatically so it shouldn’t be encoded.

List title

Used to define the title that is shown in the header of the list.

The list title attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Format

Used to compose a user friendly string from the JSON item.

The prefix to select an attribute from the JSON item is item. Literals have to be enclosed in quotes, attributes and literals can be concatenated with +.

So if the JSON item looks like

{
  "id" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac",
  "title" : "edoras one User",
  "value" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac"
}

then a format of Group: {{item.title}} results in Group: edoras one User being presented to the user for this JSON item.

Minimum number of visible items

Used to define the minimum height of the list.

The list height is forced to a height that can show at least a certain number of items. If the concrete list has less items then the missing space is filled with empty items. For example if there are 5 items to show and the minimum height is 10 then the list height is forced to a height that can show 10 items.

formComponentListRestRuntimeMinimumHeight

Maximum number of visible items

Used to define the maximum height of the list.

The list height is forced to a height that can show at most a certain number of items. If the concrete list has more items then the list shows a scroll with which the user can scroll in the list. For example if there are 15 items to show and the minimum height is 10 then the list height is forced to a height that can show 10 items.

formComponentListRestRuntime

Navigation URL

Used to define the URL to navigate to when the user clicks an item in the list.

The navigation URL attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

The prefix to select an attribute from the JSON option is $item.

So if the JSON item looks like

{
  "id" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac",
  "title" : "edoras one User",
  "value" : "GEAR-c641f3bb-876e-45f4-9550-ef95ef5a2fac"
}

then a navigation URL of /GRP/{{$item.id}}/browse results in /GRP/GEAR-3456061f-4892-4ef4-b234-69217201cd09/browse being invoked when the user clicks the item in the list.

Target

Used to define the tab where the linked item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

List attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The List form widget does not support the Value, the Default value and the Editable attribute, as these do not make sense for read only widgets.

Query

The edoras one query that is used to load the work items for the list.

Typical queries:

type:CAS for:me

all cases that are assigned to me

type:TSK for:me,unassigned

all tasks that are either directly assigned to me or are unassigned

type:CAS app:foo

all cases that belong to the foo App

See section Searches in the User guide to learn more about the search syntax and about all possible search terms.

List title

Used to define the title that is shown in the header of the list.

The list title attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Format

Used to compose a user friendly string from the work item.

The prefix to select an variable from the work item item. Literals have to be enclosed in quotes, attributes and literals can be concatenated with +.

So if the format is Group: {{item.name}} then the work item is shown to the user as Group: edoras one User.

Minimum number of visible items

Used to define the minimum height of the list.

The list height is forced to a height that can show at least a certain number of items. If the concrete list has less items then the missing space is filled with empty items. For example if there are 5 items to show and the minimum height is 10 then the list height is forced to a height that can show 10 items.

formComponentListRestRuntimeMinimumHeight

Maximum number of visible items

Used to define the maximum height of the list.

The list height is forced to a height that can show at most a certain number of items. If the concrete list has more items then the list shows a scroll with which the user can scroll in the list. For example if there are 15 items to show and the minimum height is 10 then the list height is forced to a height that can show 10 items.

formComponentListRestRuntime

Navigation view

Used to set the target view for the link.

Possible values are:

  • Browse ⇒ The link points to the form view of the work item

  • Preview ⇒ The link points to the preview view of the work item

Target

Used to define the tab where the linked work item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Image attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Image form widget does not support the Value, Default value and the Editable attribute, as these do not make sense for read only widgets.

Source URL

Used to define the URL from which the image is loaded.

The source URL attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

This can be an absolute URL like http://www.activiti.org/images/edorasware_logo.png or a relative URL that points to the content of a document work item, for example rest/workobjects/GEAR-faded1c0-a147-4fb1-9875-e13b185b0abe/content.

Maximum height

Used to define the maximum height of the image.

If set then the height of the Image form widget is forced to that height, which means the contained image is scaled down to that height. If not set then the height of the Image form widget is equals to the height of the contained image.

Refresh time (seconds)

Used to define a refresh internal in seconds.

The image is reloaded every x seconds, where x is the defined refresh time. This is useful if the Source URL attribute point to a dynamic image that can change over time.

Navigation URL

Used to define the URL to navigate to when the user clicks the image.

The navigation URL attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Target

Used to define the tab where image is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Link form widget does not support the Value, Default value and the Editable attribute, as these do not make sense for read only widgets.

Link text

The attribute is used to define the link text.

Navigation URL

Used to define the URL to navigate to when the user clicks the link.

The navigation URL attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

The URL is encoded automatically so it shouldn’t be encoded.

Context variables

Parameters that can be added to the URL linked. A dialog is opened where the name and the value of the parameters are specified. The value of the parameter can be a frontend-expression. See Frontend expressions to learn the frontend expression syntax.

formComponentLinkContextVariables

An special parameter is "forwardTo", which defines the url where we will be redirected after executing the submit action of the page where we navigate to.

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Target

Used to define the tab where the linked item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Create Link form widget does not support the Value, Default value and the Editable attribute, as these do not make sense for read only widgets.

Link text

The attribute is used to define the link text.

Work item type

Type of the work item you want to create. The items can be Case, Task, Document or Process. The attribute can be set by a frontend-expression.See Frontend expressions to learn the frontend expression syntax.

Work item model

Select the models available to create, depending on the Work item type selected. The attribute can be set by a frontend-expression. See Frontend expressions to learn the frontend expression syntax.

Context variables

Parameters that can be added to the URL linked. A dialog is opened where the name and the value of the parameters are specified. The value of the parameter can be a frontend-expression. See Frontend expressions to learn the frontend expression syntax.

formComponentLinkContextVariables

An special parameter is "forwardTo", which defines the url where we will be redirected after executing the submit action of the page where we navigate to.

Hide selectors

If its value is true, the template and parent selectors will be hidden. This only happens if the parameters (modelId and parentId) of the creation page where we are going to navigate are defined in the url.

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Target

Used to define the tab where the linked item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Search Link form widget does not support the Value, Default value and the Editable attribute, as these do not make sense for read only widgets.

Link text

The attribute is used to define the link text.

Query

The edoras one query that is used to load the work items for the list.

Typical queries:

type:CAS for:me

all cases that are assigned to me

type:TSK for:me,unassigned

all tasks that are either directly assigned to me or are unassigned

type:CAS app:foo

all cases that belong to the foo App

See section Searches in the User guide to learn more about the search syntax and about all possible search terms.

Show as button

If it’s wanted to show the link as a button

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Target

Used to define the tab where the linked item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Link form widget does not support the Value, Default value and the Editable attribute, as these do not make sense for read only widgets.

Link text

The attribute is used to define the link text.

The Link text attribute attribute can be expressed as a static value or as a frontend expression. See [frontend-expressions] to learn the frontend expression syntax. The value attribute supports the special $count frontend expression which represents the result count of the query. The value attribute as well supports different texts for singular and plural depending on the result counts. The syntax for this is [singular text|plural text].

So a value of $count case [|s] results in 1 case or 21 cases depending on the result count.

Query

The edoras one query that is used to load the work items for the list.

Typical queries:

type:CAS for:me

all cases that are assigned to me

type:TSK for:me,unassigned

all tasks that are either directly assigned to me or are unassigned

type:CAS app:foo

all cases that belong to the foo App

See section Searches in the User guide to learn more about the search syntax and about all possible search terms.

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Target

Used to define the tab where the linked item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Link form widget does not support the Value, Default value and the Editable attribute, as these do not make sense for read only widgets.

Link text

The attribute is used to define the link text.

The Link text attribute attribute can be expressed as a static value or as a frontend expression. See [frontend-expressions] to learn the frontend expression syntax. The value attribute supports the special $count frontend expression which represents the result count of the REST query. The value attribute as well supports different texts for singular and plural depending on the result counts. The syntax for this is [singular text|plural text].

So a value of $count user [|s] results in 1 user or 21 users depending on the result count.

Count URL

Defines the REST URL that returns the count result (as a numerical value).

The count URL attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Referencing external resources may have problems due to SSL (https) or CORS security browser limitations. To solve CORS security, the resource server must send appropriate response headers. Another option is using a proxy to receive the right response headers from any url e.g .:https://cors-anywhere.herokuapp.com. To solve SSL if edoras one is being executed over https, the url of the external resource should also have the https protocol.
The URL is encoded automatically so it shouldn’t be encoded.

Navigation URL

Used to define the URL to navigate to when the user clicks the link.

The navigation URL attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Target

Used to define the tab where the linked item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Button attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Button form widget does not support the Value, Default value and the Editable attribute, as these do not make sense for read only widgets.

Button text

The attribute is used to define the button text.

The Button text can be expressed as a static value or as a frontend expression. See [frontend-expressions] to learn the frontend expression syntax.

Navigation URL

Used to define the URL to navigate to when the user clicks the button.

The navigation URL attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Context variables

Parameters that can be added to the URL linked. A dialog is opened where the name and the value of the parameters are specified. The value of the parameter can be a frontend-expression. See Frontend expressions to learn the frontend expression syntax.

formComponentLinkContextVariables

An special parameter is "forwardTo", which defines the url where we will be redirected after executing the submit action of the page where we navigate to.

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Target

Used to define the tab where the linked item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Button alignment

The alignment of the button can be Left or Right.

Icon url

The url of an image, which will be displayed inside the button as an icon.

Icon alignment

The alignment of the icon inside the button. Can be Left or Right.

Create Button attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Create button form widget does not support the Value, Default value and the Editable attribute, as these do not make sense for read only widgets.

Button text

The attribute is used to define the button text.

The Button text can be expressed as a static value or as a frontend expression. See [frontend-expressions] to learn the frontend expression syntax.

Work item type

Type of the work item you want to create. The items can be Case, Task, Document or Process. The attribute can be set by a frontend-expression.See Frontend expressions to learn the frontend expression syntax.

Work item model

Select the models available to create, depending on the Work item type selected. The attribute can be set by a frontend-expression. See Frontend expressions to learn the frontend expression syntax.

Context variables

Parameters that can be added to the URL linked. A dialog is opened where the name and the value of the parameters are specified. The value of the parameter can be a frontend-expression. See Frontend expressions to learn the frontend expression syntax.

formComponentLinkContextVariables

An special parameter is "forwardTo", which defines the url where we will be redirected after executing the submit action of the page where we navigate to.

Hide selectors

If its value is true, the template and parent selectors will be hidden. This only happens if the parameters (modelId and parentId) of the creation page where we are going to navigate are defined in the url.

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Target

Used to define the tab where the linked item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Button alignment

The alignment of the button can be Left or Right.

Icon url

The url of an image, which will be displayed inside the button as an icon.

Icon alignment

The alignment of the icon inside the button. Can be Left or Right.

CMMN Action Button attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The CMMN Action Button form widget does not support the Value, Default value and the Editable attribute, as these do not make sense for read only widgets.

Model ID

The model ID corresponds to the Model ID attribute of components which provide action buttons in CMMN template. These components are:

  • Plan items with manual activation

  • User event listener

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Button alignment

The alignment of the button can be Left or Right.

Icon url

The url of an image, which will be displayed inside the button as an icon.

Icon alignment

The alignment of the icon inside the button. Can be Left or Right.

Inline Iframe attributes
Attribute Description

Common

See Common attributes to learn more about the common attributes.

Source URL

The URL of the source to be displayed in the iframe, might also contain expressions.

Height

Used to define the maximum height of the iframe in pixels.

Show border

If is set to true, it renders a border around the iFrame.

Scrolling type

If is set to true, a scrolling bar is attached to the iframe or not. The possible values are:

  • Auto: the scrolling bar will appear just if the content of the iframe is taller than its height.

  • Yes: the scrolling bar will always appear.

  • No: the scrolling bar will never appear, so part of the iframe could be potentially hidden.

Pdf preview attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Pdf preview form widget does not support the Default value and the Editable attribute, as these do not make sense for read only widgets.

Document source type

Possible values are:

  • id ⇒ The document source is the application, so the document is internal.

  • url ⇒ The document source is an external url.

Document source

It depends on the prevous attribute, the Document source type:

  • id ⇒ The id of the document, could be a frontend expression or the id document.

  • url ⇒ An external url should be provided.

Referencing external resources may have problems due to SSL (https) or CORS security browser limitations. To solve CORS security, the resource server must send appropriate response headers. Another option is using a proxy to receive the right response headers from any url e.g .:https://cors-anywhere.herokuapp.com. To solve SSL if edoras one is being executed over https, the url of the external resource should also have the https protocol.

Height

Defines the height of the pdf preview.

Show border

If is set to true, the pdf preview will have a wrapper border.

Button group attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Button group form widget does not support the Default value and the Editable attribute, as these do not make sense for read only widgets.

Button alignment

The alignment of the button group. It can be Right, Left or Center.

Horizontal line attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Label attribute is used to define the title that is displayed inside the horizontal line.

The Horizontal line form widget does not support the Default value and the Editable attribute, as these do not make sense for read only widgets.

3.8.7. Executable form widgets

The execution form widgets executes actions and saves the result in a variable.

Form widget Description
formComponentDynamicLinkButton

A button which calls an endpoint and redirects to a workitem view depending on the result.

formComponentSearchButton

Button which executes a query and stores the result in a variable. In combination with a sub form, this allows to create search-like forms. If the button is clicked, the search is executed, the result stored in the variable and the subform will show the entries accordingly. If the query is using expression bound to search fields, you can create search forms this way.

formComponentSearchButtonRuntime
formComponentRestButton

A button which makes a call to an url and sets the result in the model, with timer interval capability.

formComponentScriptButton

A button which saves in a variable the result of a script.

formComponentSelectionScriptButton

A button which saves in a variable the result of a script and shows a text based on the result.

Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Dynamic Link Button form widget does not support the Value, Default value and the Editable attribute, as these do not make sense for read only widgets.

Button text

The attribute is used to define the button text.

The Button text can be expressed as a static value or as a frontend expression. See [frontend-expressions] to learn the frontend expression syntax.

REST url

The REST url where the navigation information is retrieved. The response from the REST endpoint should have the following structure:

{
    "id" : "GEAR-35354f5d-1004-460a-8d53-88a04e0f22c1",
    "type" : "TSK",
    "view" : "browse"
}

Where id is a work object ID, type is the corresponding work object type and view is the name of the work object view that should be shown.

Referencing external resources may have problems due to SSL (https) or CORS security browser limitations. To solve CORS security, the resource server must send appropriate response headers. Another option is using a proxy to receive the right response headers from any url e.g .:https://cors-anywhere.herokuapp.com. To solve SSL if edoras one is being executed over https, the url of the external resource should also have the https protocol.

Target view

Define the view where will be redirected if the view is not defined in the REST url. If any is defined it will be redirected to Browse view by default.

Context variables

Parameters that can be added to the URL linked. A dialog is opened where the name and the value of the parameters are specified. The value of the parameter can be a frontend-expression. See Frontend expressions to learn the frontend expression syntax.

formComponentLinkContextVariables

An special parameter is "forwardTo", which defines the url where we will be redirected after executing the submit action of the page where we navigate to.

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Target

Used to define the tab where the linked item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Button alignment

The alignment of the button can be Left or Right.

Icon url

The url of an image, which will be displayed inside the button as an icon.

Icon alignment

The alignment of the icon inside the button. Can be Left or Right.

Search button attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Search button form widget does not support the Value, Default value and the Editable attribute, as these do not make sense for read only widgets.

Button text

The attribute is used to define the button text.

The Button text can be expressed as a static value or as a frontend expression. See [frontend-expressions] to learn the frontend expression syntax.

Value

Is used to store the query result once executed (e.g. '{{searchResult}}'). You can bind the same variable to a subform for instance in order to render the result returned by the query.

Query

The edoras one query that is used to load the work items for the list.

Typical queries:

type:CAS for:me

all cases that are assigned to me

type:TSK for:me,unassigned

all tasks that are either directly assigned to me or are unassigned

type:CAS app:foo

all cases that belong to the foo App

See section Searches in the User guide to learn more about the search syntax and about all possible search terms.

Max result size

The maximum number of items being returned by the query in order to limit the result, might even be an expression. See Frontend expressions to learn the frontend expression syntax.

Auto execute

Automatically executes the query during initialization of the form, if set to 'true', might even be an expression. See Frontend expressions to learn the frontend expression syntax.

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Target

Used to define the tab where the linked item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Button alignment

The alignment of the button can be Left or Right.

Icon url

The url of an image, which will be displayed inside the button as an icon.

Icon alignment

The alignment of the icon inside the button. Can be Left or Right.

REST button attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The REST button form widget does not support the Default value and the Editable attribute, as these do not make sense for read only widgets.

Button text

The attribute is used to define the button text.

The Button text can be expressed as a static value or as a frontend expression. See [frontend-expressions] to learn the frontend expression syntax.

Value

Is used to store the REST endpoint result once executed (e.g. '{{result}}'). You can bind the same variable to a subform for instance in order to render the result returned by the REST endpoint.

REST url

Define the URL of the REST endpoint which returns the data.

Referencing external resources may have problems due to SSL (https) or CORS security browser limitations. To solve CORS security, the resource server must send appropriate response headers. Another option is using a proxy to receive the right response headers from any url e.g .:https://cors-anywhere.herokuapp.com. To solve SSL if edoras one is being executed over https, the url of the external resource should also have the https protocol.

Refresh time

The milliseconds interval to execute the button automatically in every tick. If it’s not defined it will not be executed automatically.

Auto execute

Automatically executes the rest request during initialization of the form, if set to 'true', might even be an expression. See Frontend expressions to learn the frontend expression syntax.

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Target

Used to define the tab where the linked item is loaded.

Possible values are:

  • _blank ⇒ Load in a new tab

  • _self ⇒ Load in the same tab as it was clicked

  • tabname ⇒ Load in a named tab, if there is no tab with that name then a new tab is created with that name

Button alignment

The alignment of the button can be Left or Right.

Icon url

The url of an image, which will be displayed inside the button as an icon.

Icon alignment

The alignment of the icon inside the button. Can be Left or Right.

Script button attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Script button form widget does not support the Default value and the Editable attribute, as these do not make sense for read only widgets.

Button text

The attribute is used to define the button text.

The Button text can be expressed as a static value or as a frontend expression. See [frontend-expressions] to learn the frontend expression syntax.

Value

Is used to store the returned value of the script once executed (e.g. '{{scriptResult}}'). e.g It’s possible to bind the variable to a text widget in order to render the result returned by the script.

Script

The script which will be executed.

Inside the script scope is possible to access to a variable called elementId which have the value of the id attribute of the script button.

Is possible to use some util methods or properties:

  • returnAsyncValue (Function): you can execute this function a save the value asynchronously. For example when in the script we do an AJAX call.

  • elementId (String): the attribute id of the clicked button.

  • element (Object): the button clicked.

If the script returns an Angular promise, the button becomes in loading state and ignores new clicks until the promise gets resolved or rejected. Once the promise is resolved, the resolved value will be stored in the model; If the promise is rejected the model won’t be changed.

An example of a script returning a promise:

/* $q needs to be previously injected */

var defer = $q.defer();

setTimeout(function(){
  defer.resolve("anyResult");
}, 1000);

return defer.promise;

Refresh time

The milliseconds interval to execute the button automatically in every tick. When is empty, it will not be executed automatically.

Auto execute

If it is set to 'true', the script is executed automatically during initialization of the form. It might even be an expression. See Frontend expressions to learn the frontend expression syntax.

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Button alignment

The alignment of the button can be Left or Right.

Icon url

The url of an image, which will be displayed inside the button as an icon.

Icon alignment

The alignment of the icon inside the button. Can be Left or Right.

Selection script button attributes
Attribute name Description

Common

See Common attributes to learn more about the common attributes.

The Selection Script button form widget does not support the Default value and the Editable attribute, as these do not make sense for read only widgets.

Button text

The attribute is used to define the button text.

The Button text can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

Value

Is used to store the returned value of the script once executed (e.g. '{{scriptResult}}').

Script

The script which will be executed.

Inside the script scope is possible to access to a variable called elementId which have the value of the id attribute of the script button.

Is possible to use some util methods or properties:

  • returnAsyncValue (Function): you can execute this function a save the value asynchronously. For example when in the script we do an AJAX call.

  • elementId (String): the attribute id of the clicked button.

  • element (Object): the button clicked.

Refresh time

The milliseconds interval to execute the button automatically in every tick. When is empty, it will not be executed automatically.

Auto execute

If it is set to 'true', the script is executed automatically during initialization of the form. It might even be an expression. See Frontend expressions to learn the frontend expression syntax.

Result format

Shows the result of the script in a text field. If the result is an object saved in the 'result variable', it is possible to display its properties by setting it to {{scriptResult .anyProperty}}

Tooltip

Used to define the tooltip, that is, a text which will appear when the mouse enters in the widget.

The tooltip attribute can be expressed as a static value or as a frontend expression. See Frontend expressions to learn the frontend expression syntax.

3.8.8. Nesting form widgets

The nesting form widgets allow to nest widgets.

The data model of a nested form is usually stored in a nested data context. If configured that way the forms and the data model nest in a corresponding way: A field in a nested form then becomes a attribute in the nested data context.

Nested forms can be repeated. This way it is possible to define lists in the data model.

Usually nested forms are rendered in a way that the user can clearly see that the form fields belong to a nested form. But if desired nested forms can be rendered in a transparent way. The user can then not tell if a field comes from the main form or from a nested form.

Form widget Description
formComponentSingleTypeSubform

Used to nest forms of a single type.

formComponentSingleTypeSubformRuntime
formComponentMultiTypeSubform

Used to nest forms of multiple types.

formComponentMultiTypeSubformRuntime
Single-type subform attributes
Attribute Description

Form reference

Used to define the form that is rendered in place of the subform.

The editor for this attribute allows to pick an existing form or to create a new one.

formComponentFormRef

Element name

Used to define the text for the add button.

Common

See Common attributes to learn more about the common attributes.

The Value attribute is used to define the nested data context. This means if the Value is set to foo then all data inside the subform is stored in the foo attribute of the data model.

This widget does not support the Label position, the Default value, and the Description attribute, as these do not make sense for nesting widgets.

Validation

This widget supports the minimum number of children and the maximum number of children validation.

See Validation attributes to learn more about validation.

Multiple elements

Used to define if the user can repeat the form or not.

If true, additional buttons are rendered to let the user add new forms and remove existing ones.

formComponentSingleTypeSubformRuntimeRepeating

Show border

Used to define if the form inside the subform form widget is rendered nested or not.

If true the form is rendered in a nested way and the user can clearly see that this is a nested form. If false the form is rendered in a transparent way and the user cannot distinguish if a field comes form the main form or from the nested form.

formComponentSingleTypeSubformRuntimeTransparent

Show add/remove buttons

If the subform can hold multiple elements, this attribute specifies whether the add/remove buttons should be shown and thus allowing the user to create new elements or to remove existing elements. This can also be done using a dynamic expression.

Collapsible

If true, the subform can be collapsed/expanded by clicking on an arrow ▲/▼.

Collapsed

If true, the subform will appear collapsed by default.

It supports FE expression by writing it in "Collapsed(RT)" field. Using FE expression, if the value of the expression changes, it will be applied to the subform, that is, if it becomes true, the subform will be collapsed and vice versa.

Multi-type subform attributes
Attribute Description

Form references

Used to define the forms that are rendered in place of the subform.

The editor to define the form references asks for a discriminator value, the form reference and display name. The discriminator value identifies the form reference and hence the form to be used inside the data model. The display name is used to define the text for the add button.

The value stored in the discriminator attribute decides which form is used to display the data in the sub data context.

formComponentFormRefs

Common

See Common attributes to learn more about the common attributes.

The Value attribute is used to define the nested data context. This means if the Value is set to foo then all data inside the subform is stored in the foo attribute of the data model.

This widget does not support the Label position, the Default value, and the Description attribute, as these do not make sense for nesting widgets.

Validation

This widget supports the minimum number of children and the maximum number of children validation.

See Validation attributes to learn more about validation.

Multiple elements

Used to define if the user can repeat the form or not.

If true, additional buttons are rendered to let the user add new forms and remove existing ones.

formComponentSingleTypeSubformRuntimeRepeating

Show border

Used to define if the form inside the subform form widget is rendered nested or not.

If true the form is rendered in a nested way and the user can clearly see that this is a nested form. If false the form is rendered in a transparent way and the user cannot distinguish if a field comes form the main form or from the nested form.

formComponentSingleTypeSubformRuntimeTransparent

Show add/remove buttons

If the subform can hold multiple elements, this attribute specifies whether the add/remove buttons should be shown and thus allowing the user to create new elements or to remove existing elements. This can also be done using a dynamic expression.

Collapsible

If true, the subform can be collapsed/expanded by clicking on an arrow ▲/▼.

Collapsed

If true, the subform will appear collapsed by default.

It supports FE expression by writing it in "Collapsed(RT)" field. Using FE expression, if the value of the expression changes, it will be applied to the subform, that is, if it becomes true, the subform will be collapsed and vice versa.

3.8.9. Attachment form widget

formComponentAttachment

The attachment form widget allows to attach files.

formComponentAttachmentRuntime
Attribute Description

Common

See Common attributes to learn more about the common attributes.

Validation

The attachment form widget supports the minimum files and the maximum files validation.

See Validation attributes to learn more about validation.

Preview type

Used to define the preview type.

The following values are allowed:

None

display no preview

Icon

display an icon that identifies the file type as preview

Thumbnail

display a thumbnail of the attached file as preview, the thumbnail is generated in the backend

Thumbnail maximum height

Used to define the maximum height of the thumbnail.

This attribute is only available when the preview type is Thumbnail.

Select file message

Used to define the message that is shown to the user inside the attachment form widget.

By default the attachment form widget shows Please select file to the user.

3.9. Process model

A process model defines a process that can be used by other workflow models to interact with the user.

Process models support the following settings:

Name

The name of the model

Description

Describes the purpose of the model. This is provided solely as information for modelers and does not have any runtime significance.

Init form

A reference to the initialization form model. This form is used to set the initial state of the process when a new process is created based on this model.

Work form

A reference to the work form model. This form is used to view and / or update the state of the process after it has been created.

The process can be quickly checked in edoras one by hovering over the process model in the App’s model list, previewed within the process model using the Preview view or edited in the edoras vis modeler using the Design action. It is also possible to download the process definition using the Download action.

The following sections describe the elements available in the process modelling palette of edoras one. Each modeling element and its corresponding attributes are described in detail. Since edoras one is based on the BPMN 2.0 specification large parts of the modelling capabilities come from there. ̋Currently, edoras one does not support the full BPMN 2.0 standard for execution and the process palette contains only the BPMN2.0 elements that are currently supported by the engine.

In addition to the BPMN 2.0 standard elements, edoras one provides some dedicated process activities that can be used within process models. These edoras one specific activities are dedicated implementations of BPMN 2.0’s generic service task. They are implemented using the custom extensions hook of BPMN 2.0 so if you import a process model to another system that supports BPMN 2.0 these activities will appear as generic service tasks.

There are several attributes, that are available for all modelling elements:

Table 20. Common attributes
Attribute Name Description

Name

The name of the element, displayed on the diagram. This attribute is not equal to the id of the element.

Documentation

Use this attribute to add any documentation / description to the element. The content of the element can not be displayed on the model graphics, but is exported to the BPMN 2.0 XML.

Custom Properties

Defines arbitrary definition properties as name / value pairs. Custom properties are similar to static constants in Java: defined properties are added to the given element in the process definition and cannot be modified without redeploying the app, but they can be accessed at runtime using a runtime expression. Expression evaluation is not supported within a property definition as expressions are only resolved at runtime, so only plain strings can be used for property names and values. Custom properties have a number of uses, for example modifying the behaviour of application code that interacts with the process definition or configuring specific instances of a reusable component.

Background Colour

Specify the background colour of the element in the diagram.

Border Colour

Specify the border colour of the element in the diagram.

LoopType

Selection of the loop type. See Multi Instance to know more about loops.

There are several attributes, that are available to customize the font format of all modelling elements in the diagram. If the attributes are set at process level, all the components of the process will contain these attributes by default:

Table 21. Text format attributes
Attribute Name Description

Font size

Specify the font size of the element in the diagram.

Font weight

Specify the font weight of the element in the diagram.

Font style

Specify the font style of the element in the diagram.

Font Color

Specify the font color of the element in the diagram.

These attributes can also be modified by the shortcut with a "T" icon placed in the left-bottom corner of the components. Clicking on this brings up a text format dialog where the formatting can be changed as required. The dialog includes a button to remove the style format and goes back to the default format.

textFormatShortcut

Moreover the process can contain attributes associated to the whole process. In order to set them click in the design area without selecting any element.

Table 22. Process attributes
Attribute Name Description

Init form ref

The reference to a form which will be rendered before the process starts by the 'Start process' action.

Label expression

Specify a label expression for tasks within this process if you want something else being used as the name property.

Is executable

If is set to false the deployment will ignore the process. Once is set to true and the process deployed

Text format attributes

See the table above. If the text format attributes are set at process level, all the components of the process will be created with the format set.

3.9.1. Events

Start Event

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.

startEvent
Figure 8. Graphical Representation
Table 23. Specific attributes
Attribute Name Attribute Type

Description

none

Sub-processes must always start with a none start event.

Message start event

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. edoras one throws an exception upon deployment of a process definition for which two or more message start events reference the same message or messages with identical names.

  • The name of the message start event must be unique across all deployed process definitions. edoras one throws an exception upon deployment of a process definition for which 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.

messageStartEvent
Figure 9. Graphical Representation
Table 24. Specific attributes
Attribute Name Description

Is interrupting

This attribute denotes whether the sub-process encompassing the event sub-process should be cancelled or not.

Message name

Operation name

Error start event

An error start event can be used to trigger an Event Sub-Process. An error start event cannot be used for starting a process instance.

An error start event is always interrupting.

errorStartEvent
Figure 10. Graphical Representation
Table 25. Specific attributes
Attribute Name Description

Error code

The error code associated to the event.

Timer start event

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. Timer start event is scheduled as soon as process is deployed. That means that the process will be started without parent case. When a timer is needed after the start (not deployment) of a process then an intermediate time event (after a start event) should be used.

A process cannot be deployed if after timer start event there is a create case, create case from subform, create pdf or convert to PDF component.

A subprocess cannot have a timer start event.

There is no need to start an instance explicitly, although starting a process is not restricted and will cause one more starting of the process at the time invocation.

When a new version of a process with a start timer event is deployed, the job corresponding with the previous timer will be removed. The reasoning is that normally it is not wanted to keep automatically starting new process instances of this old version of the process.

timerStartEvent
Figure 11. Graphical Representation
Table 26. Specific attributes
Attribute Name Description

Is interrupting

This attribute denotes whether the sub-process encompassing the event sub-process should be cancelled or not.

Timer properties

Opens a dialog to specify when the timer should fire.

Intermediate Event

An intermediate event marks the occurrence of a particular business event.

Process execution is not delayed.

intermediateEvent
Figure 12. Graphical Representation
Table 27. Specific attributes
Attribute Name Description

Execution listeners

The execution listeners to be executed when the process token arrives in the event.

Message catching intermediate event

Message Catching Intermediate Events are used to model wait state for particular message event with a specified name. After message catching process instance continues in its execution.

Message Catching Intermediate Event style rules: * By convention, message catching intermediate events are named after the event they are waiting for. (e.g. "Additional data received")

messageIntermediateCatchingEvent
Figure 13. Graphical Representation
Table 28. Specific attributes
Attribute Name Description

Message name

The name of the message that the event is waiting for

Operation name

Timer intermediate event

Timer Intermediate Events are used to model wait state driven by a time.

Timer Intermediate Event style rules: * By convention, timer intermediate events are named after the event they are waiting for. (e.g. "Delivery deadline reached")

timerIntermediateEvent
Figure 14. Graphical Representation
Table 29. Specific attributes
Attribute Name Description

Timer properties

A wizard to configure the timer.

Signal catching intermediate event

Signal Catching Intermediate Events are used to model wait for particular signal. After catching the signal the process execution continues. The signal is not consumed after the catching. One signal can fire execution of several independent process instances in one step.

Signal Catching Intermediate Event style rules: * By convention, signal catching intermediate events are named after the event they are waiting for. (e.g. "New customer arrived")

signalIntermediateCatchingEvent
Figure 15. Graphical Representation
Table 30. Specific attributes
Attribute Name Description

Is interrupting

If the event is used as a boundary event. Specify if the related activity should be terminated when the signal arrives.

Signal name

The name of the signal the event is waiting for.

Signal throwing intermediate event

Signal Throwing Intermediate Events are used to model sending a particular signal. After sending the signal the process execution continues. One signal can fire execution of several independent process instances in one step.

Signal Throwing Intermediate Event style rules: * By convention, signal throwing intermediate events are named after the event they are throwing.

signalIntermediateThrowingEvent
Figure 16. Graphical Representation
Table 31. Specific attributes
Attribute Name Description

Execution listeners

The execution listeners to be executed when the process token arrives in the event.

Signal name

The name of the signal the event is throwing.

Boundary error event

An intermediate catching error on the boundary of an activity, or boundary error event for short, catches errors that are thrown within the scope of the activity on which it is defined.

Defining a boundary error event makes most sense on an embedded subprocess, or a call activity, as a subprocess creates a scope for all activities inside the subprocess. Errors are thrown by error end events. Such an error will propagate its parent scopes upwards until a scope is found on which a boundary error event is defined that matches the error event definition.

When an error event is caught, the activity on which the boundary event is defined is destroyed, also destroying all current executions within (e.g. concurrent activities, nested subprocesses, etc.). Non interrupting error boundary event is not supported currently. Process execution continues following the outgoing sequence flow of the boundary event. Transaction is committed when the first wait state after boundary event is reached.

boundaryErrorEvent
Figure 17. Graphical Representation
Table 32. Specific attributes
Attribute Name Description

Error code

The error code associated to the event.

The errorCode is used to match the errors that are caught:

If errorRef is omitted, the boundary error event will catch any error event, regardless of the errorCode of the error. In case an errorRef is provided and it references an existing error, the boundary event will only catch errors with the same error code. In case an errorRef is provided, but no error is defined in the BPMN 2.0 file, then the errorRef is used as errorCode (similar for with error end events).

End event

A none end event means that the result thrown when the event is reached is unspecified. As such, the engine will not do anything extra besides ending the current path of execution.

endEvent
Figure 18. Graphical Representation
Table 33. Specific attributes
Attribute Name Description

none

Error end event

When process execution arrives in an error end event, the current path of execution is ended and an error is thrown. This error can caught by a matching intermediate boundary error event. In case no matching boundary error event is found, an exception will be thrown.

errorEndEvent
Figure 19. Graphical Representation
Table 34. Specific attributes
Attribute Name Description

Error code

The error code associated to the event.

Terminate end event

A terminate end event means that all active tasks for the given process are terminated. edoras one extension may archive parent case also.

terminateEndEvent
Figure 20. Graphical Representation
Table 35. Specific attributes
Attribute Name Description

Archive type

The options to archive the parent case which contains the given process. * Do not archive * Archive only if there are no active children * Archive only if there are only active documents * Archive the case and all children

terminateEndEventAutomaticProcess
Figure 21. Terminate end event limitation

Terminate end event should reference persisted process instances. Note that a process instance without wait state is not persisted. However wait state can be easily created by changing automatic component property from synchronous to asynchronous.

3.9.2. Tasks

User Task

A user task is used to model work that needs to be done by a human actor. When the process execution arrives at such a user task, a new task is created in the task list of the user(s) or group(s) assigned to that task.

userTask
Figure 22. Graphical Representation
Table 36. Specific attributes
Attribute Name Description

Guid

The task guid. It can not be edited.

Form Reference

Select a form to be attached to the current task. You can also directly create a new form from here

Owner

Set the owner of the task by selecting an existing user statically.

Owner (RT)

Use a backend expression to evaluate the owner dynamically at runtime.

Assignee

Set the assignee of the task by selecting an existing user statically.

Assignee (RT)

Use a backend expression to evaluate the assignee dynamically at runtime.

Candidate Users

Set the candidate users of the task by selecting existing users statically.

Candidate Users (RT)

Use a backend expression to evaluate the candidate users dynamically at runtime.

Candidate Groups

Set the candidate users of the task by selecting existing groups statically.

Candidate Groups (RT)

Use a backend expression to evaluate the candidate groups dynamically at runtime.

Priority

Set the priority of the task by using a literal or a backend expression. The priority is not currently not supported at runtime

Due Date

Set the due date of the task. The due date is currently not supported at runtime

Allowed actions

The allowed actions of the task can be edited. If they are removed, will not appear in one. The Assign, Share and Create Variables can be selected or removed.

Mail Attributes

Refer to Send Mail Service Task for the usage of these attributes. By using this attribute section, you cause the engine to additionally send an email when the task is created

Manual task

A Manual task defines a task that is external to the BPM engine. It is used to model work that is done by somebody, which the engine does not need to know of, nor is there a system or UI interface. For the engine, a manual task is handled as a pass-through activity, automatically continuing the process from the moment process execution arrives into it.

manualTask
Figure 23. Graphical Representation
Table 37. Specific attributes
Attribute Name Description

none

Service Task

A service task is a task that uses some sort of service, which could be a web service or an automated application.

There are 4 ways of declaring how to invoke Java logic:

  • Specifying a class that implements JavaDelegate or ActivityBehavior.

  • Evaluating an expression that resolves to a delegation object.

  • Invoking a method expression.

  • Evaluating a value expression.

The named objects are resolved in the execution’s process variables and (if applicable) in the Spring context.

Please note that only one of the following attributes must be filled: class, expression or delegateExpression.

serviceTask
Figure 24. Graphical Representation
Table 38. Specific attributes
Attribute Name Description

Expression

Specify a UEL method expression or UEL value expression that should be evaluated.
Example UEL method: #{printer.printMessage()}, method printMessage (without parameters) will be called on the named object called printer. It’s also possible to pass parameters with a method used in the expression like #{printer.printMessage(execution, myVar)}
Example UEL value expression: #{split.ready} , the getter method of property ready, getReady (without parameters), will be called on the named bean called split.

Delegate expression

Expression that resolves to a delegation object. It is also possible to use an expression that resolves to an object provided in the attribute. This object must follow the same rules as objects that are created when the class attribute is used.
Example: ${delegateExpressionBean}, the delegateExpressionBean is a bean that implements the JavaDelegate interface, defined in for example the Spring container.

Result variable

The return value of a service execution (for service task using expression only) can be assigned to an already existing or to a new process variable by specifying the process variable name as a literal value for resultVariable attribute of a service task definition.
Any existing value for a specific process variable will be overwritten by the result value of the service execution. When not specifying a result variable name, the service execution result value gets ignored.

Class

Class that implements JavaDelegate or ActivityBehaviorSpecify. The class is called during process execution. The fully qualified classname needs to be provided by the attribute. Example: org.activiti.MyJavaDelegate

Disable security

If this option is enabled then the service task will be executed with the security checks disabled, meaning that there will be no restrictions on the work objects that can be accessed or modified during the task execution. This should be used with caution.

Create Case Service Task

The Create Case Service Task can be used to create a new case from within a process. Input data for the new case can be mapped and the newly created case can be referenced form the current case if needed.

createCaseServiceTask
Figure 25. Graphical Representation
Table 39. Specific attributes
Attribute Name Description

Case Model

Select a case model for the new case to be created

Init Variables

Specify additional variables that should be initialized during the creation of the new case

Case Name

Set the name of the new case using literals or backend expressions

CaseId Variable

specify a variable name where the id of the newly created case. Variable value is of WorkObjectId type. Variable name allows following prefixes:

parent. stores generated document id as a variable of the first case from the bottom to the top hierarchy path.

root. stores generated document id as a variable of the top most parent case.

without prefix stores generated document id as a variable of the current process.

This is optional

ParentId

specify an expression to resolve the work item id to be the parent item of the new case to be created. This is optional

Create case from subform service task

The create case from subform service Task is an itemization of the create case service task. Here you can specify a variable (subform) of the current workitem hierarchy as the input values for the new case instead of binding all input parameters manually.

createCaseServiceTask
Figure 26. Graphical Representation
Table 40. Specific attributes
Attribute Name Description

Case Model

Select a case model for the new case to be created

Init Variables

Specify additional variables that should be initialized during the creation of the new case

Case Name

Set the name of the new case using literals or backend expressions

CaseId Variable

specify a variable name where the id of the newly created case should be stored in the current case. This is optional

ParentId

specify an expression to resolve the work item id to be the parent item of the new case to be created. This is optional

Subform Variable

Specify the variable name where the subform to create the new case from is bound to

Remove Subform Variable

If set to true, the variable of the subform will be removed from the data model after creating the case

Create document service task

edoras one allows to enhance business processes with document creation service tasks. The create document service task creates a copy of the specified document template insid the current case. In case the document template is either a MS Word or Adobe PDF form, form fields will automatically be populated with execution data. Refer to Document Placeholders for more information.

createDocumentServiceTask
Figure 27. Graphical Representation
Table 41. Specific attributes
Attribute Name Description

Document Model

Select a document model for the new document to be created

Document Id variable name

Specify a variable name where the id of the newly created document. Variable value is of DocumentId type. Variable name allows following prefixes:

parent. stores generated document id as a variable of the first case from the bottom to the top hierarchy path.

root. stores generated document id as a variable of the top most parent case.

without prefix stores generated document id as a variable of the current process.

This is optional.

Document name

The name of the document to be created within the case, might also contain expressions

Convert to pdf service task

edoras one allows to enhance business processes with document conversion to pdf service tasks. The 'Convert to pdf' service converts a specified document to pdf format.

createDocumentServiceTask
Figure 28. Graphical Representation
Table 42. Specific attributes
Attribute Name Description

Document Id

Specify the ID of the document which will be converted to pdf.

Save as copy

Indicates if the pdf document is saved as a new document.

Document id variable

Only active when 'Save as copy' is true. Specify a variable name where the id of the newly created document is stored. Variable value is of DocumentId type. Variable name allows following prefixes:

parent. stores generated document id as a variable of the first case from the bottom to the top hierarchy path.

root. stores generated document id as a variable of the top most parent case.

without prefix stores generated document id as a variable of the current process.

Send Mail Service Task

edoras one allows to enhance business processes with automatic mail service tasks that send e-mails to one or more recipients, including support for cc, bcc, mail templates, …​ etc. Since version 1.5.0.S120 the mail is send only once to all recipients. Email sending does not iterate through the list of mail recipient as the implementation worked before 1.5.0.S120.

See section Mail Server in the Operators Guide for information on configuring the mail server.
sendMailServiceTask
Figure 29. Graphical Representation
Table 43. Specific attributes
Attribute Name Description

Mail Model

This mail model defines rich-text templates for the mail subject and body. Backend expressions in the mail model templates will be replaced when the mail is sent.

The mail model is a required runtime back end expression (the Mail Model RT attribute) or a literal (the Mail Model attribute) that defines the mail model key or its model id. In the literal case, you are able to select the mail model based on a select box which is populated with the mail models of the current app. In this case, the version of the mail model taken is the one that will be deployed next which on subsequent changes to the mail model will not be the latest mail model definition deployed.

If you specify a back end expression, then this should resolve to either an email model id or email definition key (that is, a specific version of an email model). In the first case, the latest deployed version (definition) of the email model is used as template. In the latter case, the specified definition will be used, similar to selecting the literal case mentioned above.

Mail Recipient

The mail recipient is a required expression or literal that defines the email recipient (or multiple recipients). The first mail recipient can be accessed in the mail template by ${recipient} expression.

Mail Reply-To

The mail reply-to is an optional expression that specify an explicit reply address. If no reply address is defined then the global system default will be used (which will vary from installation to installation)

Mail CC

Specify one or multiple CC recipients using literals or backend expressions. This attribute is optional

Mail Bcc

Specify one or multiple BCC recipients using literals or backend expressions. This attribute is optional

Mail Priority

An optional expression or literal that specifies the mail priority (usually an integer in the range 1 - 5)

Mail Headers

Specify additional mail headers. They will be applied before the message is sent

Attachments ids

The list of documents sent by the email. The documents can be referenced by its id or a backend expression.

Invoke REST endpoint service task

The Invoke REST endpoint service task provides a generic client to call arbitrary REST endpoints. The task supports all HTTP operations, Basic Authentication, custom headers and different mime-types.

invokeRESTEndpointServiceTask
Figure 30. Graphical Representation
Table 44. Specific attributes
Attribute Name Description

Protocol

Specify the protocol to use for the request. HTTP and HTTPS are supported

Request Type

Specify the type of the HTTP Request. GET, POST, PUT and DELETE are supported

Request Headers

Add additional HTTP message headers to your request

Request Body

Specify the message body that will be sent with the request. You can use backend expressions to include data from the data model within your message body structure. This can only be used with POST and PUT requests

Content Type

Define the content type header to be set within the request. This value will be overwritten if you have set a content type in the Header attribute

Host Name

The host name of the remote server (e.g. service.edorasware.com

Port Number

The port number of the remote server. If not specified, 80 is used

Request Path

Specify the path to the endpoint on the remote server. The path must start with a leading / You can use backend expressions to set the path dynamically at runtime based on values from the data model

Request Parameters

Specify the parameters that are passed as part of the request URL. Multiple parameters can be defined using the editor provided

Username

If the remote server requires basic authentication specify the username of the user you want to use for the request

Password

If the remote server requires basic authentication specify the password of the user you want to use for the request

Response Type

Select the format of the response of the REST call. Currently JSON and XML are supported

Set Variables

Map the response data to your data model. specify the variable name and use X-Path expressions to select the respecting value from the response

Overwrite if existing

Set to true if you want to overwrite the values of existing variables with the values from the REST calls response

JSON to XML mapping

The JSON to XML mapping used to prepare data for the XPath expression evaluation is mainly intuitive, but for completeness here is a quick summary of how different JSON content is mapped:

Table 45. JSON to XML mapping
JSON XML XPath example Result
{ 'node': 'value' }
<root>
  <node original-type="string">value</node>
</root>

//node

value

{ 'node': [ 'value1', 'value2' ] }
<root>
  <node1 original-type="string">value1</node1>
  <node2 original-type="string">value2</node2>
</root>

//node[2]

value2

{ 'node': { 'child':'cValue' } }
<root>
  <node>
    <child original-type="string">cValue</child>
  </node>
</root>

//child

cValue

'single value'
<root original-type="string">single value</root>

/root

single value

[ 'one', 'two', 'three' ]
<json>
  <root original-type="string">one</root>
  <root original-type="string">two</root>
  <root original-type="string">three</root>
</json>

/json/root[2]

two

Note that in the case where multiple values are in the top-level JSON content, an additional root node (json) will be created as XML may only have a single root node.

Initialize variables service task

Use the initialize variables service task to initialize arbitrary variables in the current workitem hierarchy. You can use Expressions or literals to set the values of the variables.

initializeVariablesServiceTask
Figure 31. Graphical Representation
Table 46. Specific attributes
Attribute Name Description

Init Variables

Specify variable name and target workitem of the variable you want to initialize using literals. Use literals or backend expressions to specify the value of the variable

Overwrite if existing

If set to true, the values of already defined variables will be overwritten. Otherwise, already initialized variables are skipped

Initialize variables on query result

Use the 'Initialize variables on query result' service task to initialize variables in every work item being returned by a query. You can use Expressions or literals to set the values of the variables.

initializeVariablesServiceTask
Figure 32. Graphical Representation
Table 47. Specific attributes
Attribute Name Description

Query

The specified variables will be applied to every work item being returned by that query.

Variables to initialize

Specify variable name and target workitem of the variable you want to initialize using literals. Use literals or backend expressions to specify the value of the variable. For each variable it’s specified the flag 'Overwrite if existing', If set to true, the value of variable will be overwritten. Otherwise, already initialized variable is skipped

Result list item name

The name of the local variable representing the currently processed result list work item. This name might be used in an expression to access the current work item (e.g. '#{item.name}')

Result list item index

The name of the local variable representing the index (0-based) of the currently processed result list work item. This might be used in an expression to access the loop counter (index) of the currently processed work item (e.g. '#{itemIndex+1}')

Comment service task

Use the comment service task to add a comment to an arbitrary workitem reachable by the expression resolver. You can use templates similar to the ones in the send mail service Task to add formatted, structured comments.

commentServiceTask
Figure 33. Graphical Representation
Table 48. Specific attributes
Attribute Name Description

Comment Target Object

Use an expression that resolves to the workitem where the comment should be added to the comment-stream

History variable name

Stores the last comment added in the given variable name. If empty the comment is added to the comment-stream.

Comment User

Specify a the user in whose name the comment is created using an expression

Comment Template

Select the template for the comment

3.9.3. Execution elements

Sequence Flow

A sequence flow is the connector between two elements of a process. After an element is visited during process execution, all outgoing sequence flow will be followed. This means that the default nature of BPMN 2.0 is to be parallel: two outgoing sequence flow will create two separate, parallel paths of execution.

A sequence flow can have a condition defined on it. When a BPMN 2.0 activity is left, the default behavior is to evaluate the conditions on the outgoing sequence flow. When a condition evaluates to true, that outgoing sequence flow is selected. When multiple sequence flow are selected that way, multiple executions will be generated and the process will be continued in a parallel way.

The above holds for BPMN 2.0 activities (and events), but not for gateways. Gateways will handle sequence flow with conditions in specific ways, depending on the gateway type.

Currently conditionalExpressions can only be used with Backend Expressions, detailed info about these can be found in section Backend Expressions. The expression used should resolve to a boolean value, otherwise an exception is thrown while evaluating the condition.

All BPMN 2.0 tasks and gateways can have a default sequence flow. This sequence flow is only selected as the outgoing sequence flow for that activity if and only if none of the other sequence flow could be selected. Conditions on a default sequence flow are always ignored.

sequenceFlow
Figure 34. Graphical Representation
Table 49. Specific attributes
Attribute Name Description

Condition Type

Specify the condition type of the message flow. standard an conditional flow behave the same, but are displayed differently. Use a backend expression in the Condidtion Expression Attribute to specify the condition. If you set the condition type to Default, this flow is executed when no other flow condition evaluates to true

Condition Expression

A backend expression that must evaluate to a boolean value

Exclusive Gateway

An exclusive gateway (also called the XOR gateway or more technical the exclusive data-based gateway), is used to model a decision in the process. When the execution arrives at this gateway, all outgoing sequence flow are evaluated in the order in which they are defined. The sequence flow which condition evaluates to true (or which doesn’t have a condition set, conceptually having a 'true' defined on the sequence flow) is selected for continuing the process.

Note that the semantics of outgoing sequence flow is different to that of the general case in BPMN 2.0. While in general all sequence flow which condition evaluates to true are selected to continue in a parallel way, only one sequence flow is selected when using the exclusive gateway. In case multiple sequence flow have a condition that evaluates to true, the first one defined in the XML (and only that one!) is selected for continuing the process. If no sequence flow can be selected, an exception will be thrown.

exclusiveGateway
Figure 35. Graphical Representation
Table 50. Specific attributes
Attribute Name Description

none

Inclusive gateway

The inclusive gateway can be seen as a combination of an exclusive and a parallel gateway. Like an exclusive gateway you can define conditions on outgoing sequence flows and the inclusive gateway will evaluate them. But the main difference is that the inclusive gateway can take more than one sequence flow, like the parallel gateway. The functionality of the inclusive gateway is based on the incoming and outgoing sequence flow:

  • fork: all outgoing sequence flow conditions are evaluated and for the sequence flow conditions that evaluate to true the flows are followed in parallel, creating one concurrent execution for each sequence flow.

  • join: all concurrent executions arriving at the inclusive gateway wait in the gateway until an execution has arrived for each of the incoming sequence flows that have a process token. This is an important difference with the parallel gateway. So in other words, the inclusive gateway will only wait for the incoming sequence flows that will be executed. After the join, the process continues past the joining inclusive gateway.

Note that an inclusive gateway can have both fork and join behavior, if there are multiple incoming and outgoing sequence flow for the same inclusive gateway. In that case, the gateway will first join all incoming sequence flows that have a process token, before splitting into multiple concurrent paths of executions for the outgoing sequence flows that have a condition that evaluates to true.

Note that at least one condition must be true

inclusiveGateway
Figure 36. Graphical Representation
Table 51. Specific attributes
Attribute Name Description

none

Parallel gateway

Gateways can also be used to model concurrency in a process. The most straightforward gateway to introduce concurrency in a process model, is the Parallel Gateway, which allows to fork into multiple paths of execution or join multiple incoming paths of execution. The functionality of the parallel gateway is based on the incoming and outgoing sequence flow:

  • fork: all outgoing sequence flow are followed in parallel, creating one concurrent execution for each sequence flow.

  • join: all concurrent executions arriving at the parallel gateway wait in the gateway until an execution has arrived for each of the incoming sequence flow. Then the process continues past the joining gateway.

Note that a parallel gateway can have both fork and join behavior, if there are multiple incoming and outgoing sequence flow for the same parallel gateway. In that case, the gateway will first join all incoming sequence flow, before splitting into multiple concurrent paths of executions.

An important difference with other gateway types is that the parallel gateway does not evaluate conditions. If conditions are defined on the sequence flow connected with the parallel gateway, they are simply neglected.

parallelGateway
Figure 37. Graphical Representation
Table 52. Specific attributes
Attribute Name Description

none

Call activity (subprocess)

BPMN 2.0 makes a distinction between a regular subprocess, often also called embedded subprocess, and the call activity, which looks very similar. From a conceptual point of view, both will call a subprocess when process execution arrives at the activity.

The difference is that the call activity references a process that is external to the process definition, whereas the subprocess is embedded within the original process definition. The main use case for the call activity is to have a reusable process definition that can be called from multiple other process definitions.

When process execution arrives in the call activity, a new execution is created that is a sub-execution of the execution that arrives in the call activity. This sub-execution is then used to execute the subprocess, potentially creating parallel child execution as within a regular process. The super-execution waits until the subprocess is completely ended, and continues the original process afterwards.

callActivity
Figure 38. Graphical Representation
Table 53. Specific attributes
Attribute Name Description

LoopType

Selection of the loop type. See Multi Instance to know more about loops

Sub Process Reference

Select the subprocess to be called within the call activity

Sub Process Reference (RT)

Use a backend expression to evaluate the sub process reference dynamically at runtime.
Example: The expression ${modelManager.findLatestDefinitionKeyByModelId(String modelId)} gets the latest model definition for the given model Id.

In

Map input data to be passed from the parent (current) process to the subprocess while starting the subprocess

Out

Map output data to be passed form the subprocess to the parent process after the subprocess has finished

Subprocess

BPMN 2.0 makes a distinction between a regular subprocess, often also called embedded subprocess, and the call activity, which looks very similar. From a conceptual point of view, both will call a subprocess when process execution arrives at the activity.

The difference is that the call activity references a process that is external to the process definition, whereas the subprocess is embedded within the original process definition. The main use case for the call activity is to have a reusable process definition that can be called from multiple other process definitions.

A subprocess is executed within the scope of the parent process.

subprocess
Figure 39. Graphical Representation
Table 54. Specific attributes
Attribute Name Description

LoopType

Selection of the loop type. See Multi Instance to know more about loops

Text Annotation

The Text Annotation is for documentation purpose only, it’s not evaluated by the engine. Use it to add textual explanations to an element of the process model. In contrast to the Documentation property of an element, the text annotation is also visible on the graphical representation of the process model.

textAnnotation
Figure 40. Graphical Representation
Table 55. Specific attributes
Attribute Name Description

Text

Text annotation displayed in the process model.

Association

An association is represented with a dotted line. It is used to associate an artifact or text to a flow object, and can indicate some directionality using an open arrowhead (toward the artifact to represent a result, from the artifact to represent an input, and both to indicate it is read and updated). No directionality is used when the artifact or text is associated with a sequence or message flow (as that flow already shows the direction).

edoras one currently only supports undirected associations

association
Figure 41. Graphical Representation
Table 56. Specific attributes
Attribute Name Description

none

3.9.4. Role elements

Horizontal Pool

Represents the organizational boundaries of a process, typically separating different organisations. A pool contains one or more lanes (like a real swimming pool). One process has to be executed within a pool. If the end-to-end process includes multiple pools, each pool has its own process flow. Communication between pools is handled by Message Flows. The horizontal pool in edoras one represents the system boundaries of edoras one in the mentioned orientation.

horizontalPool
Figure 42. Graphical Representation
Table 57. Specific attributes
Attribute Name Description

isExecutable

Indicates if this pool is executable.

Vertical Pool

Represents the organizational boundaries of a process, typically separating different organisations. A pool contains one or more lanes (like a real swimming pool). One process has to be executed within a pool. If the end-to-end process includes multiple pools, each pool has its own process flow. Communication between pools is handled by Message Flows. The vertical pool in edoras one represents the system boundaries of edoras one in the mentioned orientation.

verticalPool
Figure 43. Graphical Representation
Table 58. Specific attributes
Attribute Name Description

isExecutable

Indicates if this pool is executable.

Collapsed pool

A collapsed pool hides internal detail from the viewer. It’s used to visualize communication between the main pool and an external system / organization that is not in the scope of the current project. The collapsed pool has no impact at execution time.

collapsedPool
Figure 44. Graphical Representation
Table 59. Specific attributes
Attribute Name Attribute Type

Description

none

Lane

Used to organise and categorise activities within a pool according to function or role, and depicted as a rectangle stretching the width or height of the pool. A lane contains the flow objects, connecting objects and artifacts.

lane
Figure 45. Graphical Representation
Table 60. Specific attributes
Attribute Name Description

Owner

Set the owner of the lane by selecting an existing user statically.

Owner (RT)

Use a backend expression to evaluate the owner dynamically at runtime.

Assignee

Set the assignee of the lane by selecting an existing user statically.

Assignee (RT)

Use a backend expression to evaluate the assignee dynamically at runtime.

Candidate Users

Set the candidate users of the lane by selecting existing users statically.

Candidate Users (RT)

Use a backend expression to evaluate the candidate users dynamically at runtime.

Candidate Groups

Set the candidate users of the lane by selecting existing groups statically.

Candidate Groups (RT)

Use a backend expression to evaluate the candidate groups dynamically at runtime.

All User task components in a lane will inherit the values of Assignee, Owner, Candidate groups and Candidate users attributes at run-time, but only if they are not explicitly set on the individual User task components. This makes proper assignmetn of User tasks easier in the context of Swimlanes.

Message Flow

A Message Flow is represented with a dashed line, an open circle at the start, and an open arrowhead at the end. It tells us what messages flow across organizational boundaries (i.e., between pools). A message flow can never be used to connect activities or events within the same pool.

messageFlow
Figure 46. Graphical Representation
Table 61. Specific attributes
Attribute Name Description

none

3.9.5. Multi Instance

edoras one supports the creation of multiple instances of several BPMN 2.0 elements (Human Task, Call Activity, Embedded Subprocess and all Activities in the section Service Tasks of the edoras one palette). Multi-instancy is configured within the process model.

To specify multi-instancy select the corresponding type parallel or sequential.

If you chose parallel, all instances of the element are created at once, when the execution arrives at the activity. If you choose sequential, the next instance of the activity ist created, when the previous activity was completed.

Table 62. Multi-instance attributes
Attribute Name Description

Loop collection

A varialbe from the variable hierarchy that holds a list of elements. All elements of the list are processed, that means, the platform will generate one instance per list element

Loop element variable

a copy of the current list element. If you want to modify the variable, write the new value to the original list element since the loop element variable is not merged with the original one, once the execution is terminated.

Loop element index variable

The name of the variable where the current list index is stored.

Loop cardinality

An expression that evaluates to an integer which determines the number of instances to be created if you do not use a list for iteration.

Completion condition

A boolean expression do define a condition, to terminate the multi-instancy. As long as the expression evaluates to true, a new instance will be created.

3.10. Mail model

A mail model is used to define an email template that can be sent automatically by a workflow, and supports the following settings:

Name

The name of the model

Description

Describes the purpose of the model. This is provided solely as information for modelers and does not have any runtime significance.

Mail Subject

The subject line to be sent with the email.

Mail Body

The body text to be sent with the email.

3.10.1. Placeholder expressions

The mail subject and body can contain placeholder expressions that can be used to insert dynamic values. Placeholder expressions are delimited in the same way as other backend expressions, i.e. with #{…​}:

mail placeholders

When the mail is sent (for example using a mail task as part of a process definition), the placeholders will be resolved at the time the mail is sent:

mail received

3.11. Keyboard shortcuts

Table 63. Keyboard shortcuts supported by the property panel
Name Description

Up

Navigate to above property in the panel.

Down

Navigate to below property in the panel.

ENTER

To open editors and closing/committing entered value for inline editors.

SPACE

To open inline editors / toggle boolean values.

ESC

To close inline editor without committing the values.

F2

To open editor for editing selected attribute.

Table 64. Keyboard shortcuts supported by the treeview dialog editor
Name Description

ALT + 1

Selecting a New radio button.

ALT + 2

Selecting a Reference radio button.

ALT + 3

Selecting a Url radio button.

ALT + 4

Selecting a Remove Reference radio button.

SHIFT + F

Switch to Find(Search) mode in reference panel.

SHIFT + T

Switch back to Treeview mode in reference panel.

Up

Navigate to above node in tree.

Down

Navigate to below node in tree.

Left

Collapse folder.

Right

Expand folder.

ENTER

Select the current model.

Table 65. Keyboard shortcuts supported by the complex dialog editor
Name Description

INSERT

Adding a new row.

DELETE

Deleteing a selected row.

CTRL + up

Moving selected row up.

CTRL + down

Moving selected row down.

ENTER

Editing a selected cell.

TAB

Selecting next cell.

F2

To open editor for editing the selected cell.

3.12. Designer Usability hints

The designer provides various usability hints.

3.12.1. Alignment of shapes

Using Middle shape align middle and Center shape align center toolbar buttons we can align shapes horizontally or vertically.

Click the link to see demo.

3.12.2. Resizing of shapes to same size

Using Same size shape align size toolbar button we can resize all selected shapes to the same size.

Click the link to see demo.

3.12.3. Auto layout of connectors in process designer

Using Auto Layout shape auto align toolbar button we can auto layout the connectors (sequence flows) in the process diagram.

3.12.4. Creating dockers and removing dockers

We can create and remove dockers in 2 ways:

  • By using Add Docker vector add and Delete Docker vector delete toolbar buttons

  • By using mouse pointer directly on connecting shapes.

Click the link to see demo.

3.12.5. Changing the position of shapes

Using Change the position of shapes shape translate toolbar button we can move the shapes horizontally or vertically.

Click the link to see demo.

3.12.6. Transform shape

Using Transform shape feature we can transform a shape to another type belonging to same group.

Click the link to see demo.

3.12.7. Validating a process

Using Validate Process checker syntax toolbar button we can find if there are any errors in the process.

Click the link to see demo.

3.12.8. Deleting of shapes

Using Delete all selected shapes cross toolbar button we can delete all selected shapes. We can also delete selected shapes using Del key.

Click the link to see demo.

3.12.9. View preview in form designer

Using View preview edorasform preview toolbar button we can view preview of the form.

3.12.10. Import BPMN 2.0 XML in process designer

Using Import BPMN 2.0 XML import toolbar button we can import process from a BPMN 2.0 XML into the process diagram.

3.12.11. Compare revisions

Compare revisions compare toolbar button can be used to compare the revisions of the model to view the changes done between revisions.

3.12.12. Revert to a previous revision

In the Compare revisions mode you can click the Revert to this revision button. This action creates a new revision with the content of the selected revision.

3.12.13. Drop shape on connectors / remove shape from connector

When we drop a new shape on a connector which is already connecting 2 other shapes, the connector automatically splits to accomodate the new shape.

Similarly, if we delete a shape which is already connected to two other shapes, the connectors automatically rejoin.

Click the link to see demo.

3.12.14. Quick shape menu

We can quickly add and connect shapes to existing shapes using the quick shape menu.

Click the link to see demo.

3.12.15. Editing shape property in process/form designer

We can directly edit some of the shape properties like name in the process editor, and label, description and value in the form editor.

Click the link to see demo.

3.12.16. Using label expression in process designer

We can define a custom label expression for shapes, so that corresponding values are displayed as label on the shapes

Click the link to see demo.

3.12.17. Resizing of shapes using mouse

Using mouse pointer, we can resize the shapes.

Click the link to see demo.

3.13. Expressions

edoras one can evaluate expressions in both the frontend (i.e. in the browser) and in the backend (i.e. in the server). Expressions can be used in a number of ways in the edoras one application, for example:

  • to create a binding between a form field and work object data

  • to modify the state of form fields dynamically in response to user input (e.g. field visibility)

  • to populate a mail template before the mail is sent

  • to control the execution flow in a process execution

  • to execute method calls on the server

  • …​

3.13.1. Frontend expressions

Form binding expressions

Forms are used to display and edit the data of underlying work objects. The work object data and the form definition are fetched from the server, and the expressions used within the form definition are then used to link the form fields with corresponding data. For editable fields, any changes made are reflected in the underlying work object data, which is sent back to the server to be persisted when the form is submitted:

formbinding

Form data binding expressions are placed between two sets of curly braces, e.g. {{expression}}, and are set using a form field’s Value attribute:

formeditor

The Value attribute of most form fields may only be bound to a single expression, and this may not be preceded or followed by other text.

The only exception to this rule is the output field, which doesn’t bind to a single value, but instead uses form expressions embedded within a rich text template to create dynamic textual output.

Simple variable bindings

A simple value name in double curly braces (e.g. {{value}}) is used to link to the corresponding variable in the current work object. If the work object variable doesn’t exist when the form is opened then it will be created automatically.

Bindings to other hierarchy work objects

A work object in edoras one is typically part of a hierarchy, where work objects are linked together in a tree of parent/child relationships. For example a case typically serves as a container for other work objects (tasks, running processes, documents etc.). Form binding expressions can also be used to access the values from related work objects in the work object hierarchy. This is done be preceding the variable to be accessed by a qualifier (e.g. {{root.value}}):

The following qualifier keywords are currently supported:

parent

the parent of the current work item

root

the root of the current work item hierarchy

self

the current work item

$this

the form. When we use a subform widget it would be the subform itself.

As an example, if we start a process within a case then the process’s parent work object will be the case. A form task created by that process will have the process work object as its parent:

hierarchybinding
Figure 47. Example work object hierarchy

In this case {{root.name}} will bind to "Example case", {{parent.name}} will bind to "Example process" and {{name}} will bind to "Example task".

Init forms for tasks and processes only support parent variables update. That means that is not possible to update the case variables using the expression root.

Bindings to other global objects
currentUser

The object of the current user logged in the application, which provides its properties like id, name e.g {{currentUser.id}}

Bindings to global functions
isUserInGroup(userId, groupId)

The result of this expression will become true if the user is member of the provided group.

  • Parameters:

    • userId: the id of the user.

    • groupId: the id of the group.

This expression is executed asynchronously, that means that it will be "false" until the response from server is success.

isUserInGroups(userId, groupIds)

The result of this expression will become true if the user is member of one of the provided groups.

  • Parameters:

    • userId: the id of the user.

    • groupIds: an array of group id’s.

This expression is executed asynchronously, that means that it will be "false" until the response from server is success.

isUserInAllGroups(userId, groupIds)

The result of this expression will become true if the user is member of all of the provided groups.

  • Parameters:

    • userId: the id of the user.

    • groupIds: an array of group id’s.

This expression is executed asynchronously, that means that it will be "false" until the response from server is success.

Formatting dates in frontend expressions

When not being used to create a binding between a form field and a work item attribute (e.g. when used in the output form widget), frontend expression that resolve into a date can have an additional format string that defines how the date is formatted. To do so append the format string to the binding expression, for example:

{{anyBoundDate | date:'MMM/dd/yyyy'}}
{{anyBoundDate | date:'dd-MM-yyyy'}}

If no format string is explicitly specified then yyyy-MM-dd is used.

The following tokens are allowed:

Token Description

yyyy

4 digit representation of year, e.g. 0001, 2010

yy

2 digit representation of year, padded (00-99), e.g. 01, 10

MMMM

month name long (always in English): January-December

MMM

month name short (always in English): Jan-Dec

MM

month of year (two digit): 01-12

M

month of year (no leading zero): 1-12

dd

day of month (two digit): 01-31

d

day of month (no leading zero): 1-31

EEEE

day name long (always in English): Sunday-Saturday

EEE

day name short (always in English): Sun-Sat

The format string can contain literal values which need to be quoted with single quotes. Make sure that you escape the single quotes that denote a literal value. In order to output a single quote, use two single quotes in a sequence:

{{anyBoundDate | date: '\'day\' d \'of\' MMMM \'in the year\' yyyy'}}
{{anyBoundDate | date: '\'Today it\'\'s\' dd/MM/yyyy'}}

It’s also possible to use the age filter in order to calculate the elapsed time from provided date until current date. The elapsed time can be calculate in ages or days.

{{anyBoundDate | age}}
{{anyBoundDate | age: 'd'}}
More complex frontend expressions

When not being used to create a binding between a form field and a work object attribute, that is when not setting value property on most of the widgets, we can use more complex expressions like arithmetic or logic operations.

You can use this kind of expressions in runtime properties (like Editable(RT) or Visible(RT) ), query, default, or in the value of the output text.

Arithmetic operations
{{ (number1 + number2) * number3 }}
{{ number1 / number2 }}
Text concatenation
{{ text + ‘_end’ }}
Logic operations
{{ (boolean && otherBoolean)  &&  ( text + _‘endText’ )}}
Subform with multiple elements special expression keys

When we use subform or multi type subform with multiple elements we can make use of some special expressions:

Key Result type Description

$index

number

iterator offset of the repeated element (0..length-1)

$first

boolean

true if the repeated element is first

$middle

boolean

true if the repeated element is between the first and last

$last

boolean

true if the repeated element is last

$even

boolean

true if the position $index is even

$odd

boolean

true if the position $index is odd

We can, for example, retrieve the value of the previous item, having a subform with "mySub" value, the last item would be {{mySub[$index-1]}}

Accessing arrays

Some widgets saves an array of items (Search button , Autocomplete with multitag, subform with miltiple elements, etc.)

You can access the value of an element through an expression model, for example, having a search button with {{myResult}} value, and a number widget with {{myIndex}}. You can use an expression like {{myResult[myIndex]}} to retrieve an item of the array.

3.13.2. Backend Expressions

Expressions can also be executed on the server, for example within the process models. Server-side expressions are called backend expressions. A much wider range of expressions is possible than in frontend expressions the expressions may also have side-effects within the system (for example causing an e-mail to be sent). As well as accessing data from the work object hierarchy, backend expressions support additional functionality such as accessing work objects outside of the immediate hierarchy, predefined function calls and bean method calls.

There are two basic expression types:

value expressions

have the form #{value.property} and resolve to a value

method expressions

have the form #{bean.method(value)} and result in a method invocation

The full backend expression language is part of the EE6 specification and only an brief overview will be provided here. For a full description of the expression language syntax please refer to the EE6 specification.
Accessing work objects

As in the frontend, qualifiers can be used to traverse the work object hierarchy, although there are more options available in backend expressions. qualifiers can also be chained (e.g. #{process.parent.name}):

The following qualifier keywords are currently supported:

self

the current work item (the default if no work object is explicitly specified)

case

the top-most parent case to which the current work object belongs

parentCase

the nearest parent case to which the current work object belongs

process

the top-most parent process to which the current work object belongs

parentProcess

the nearest parent process to which the current work object belongs

root

the root of the current work object hierarchy

parent

the direct parent of the current work object

Backend attribute values

Simple attribute names can be used to access work object attributes in backend expressions in the same way as in frontend expressions (see Frontend expressions).

To access attributes, simply use the attribute name: #{case.name}

One significant difference between frontend expressions and backend expressions is that the work object attributes accessible in the frontend may have been pre-processed by the server so that the attribute values are in a form that makes more sense in the client’s context. With backend expressions this processing is not performed so you will be working with raw work attributes.

As an example, state is represented in a work object by an instance of the State class. In the frontend , the expression {{state}} will be bound to the name field of this object (e.g. "ACTIVE"). The conversion from a State object to the state name string has already been performed by the server.

The corresponding process binding, #{state} resolves to the underlying State object, which if it is used in a string context will be converted to a string literal, e.g. "[State@51d838d9 name = \'ACTIVE']". To access the plain name ("ACTIVE") we can use a java bean property expression: #{state.name}.

For a description of common work object attributes, refer to Common attributes.

Automatic work object ID conversion

Work objects are referenced using IDs, and in a backend expressions it is often useful to access not the ID itself but the referenced work object. To support this use case, an expression that resolves to a work object ID will automatically be converted to the corresponding work object instance as needed.

For example the expression #{ownerId} will resolve to the owner ID, but if we then extend the expression (e.g. #{ownerId.name} then the ID will be converted to the corresponding work object, and the name attribute from this work object will be returned.

As access to other work objects linked from a work object using IDs is so common there are also some shortcut expressions to access this information directly:

Table 66. Predefined work object expressions
Expression Type Description

#{owner}

User work object

the work object’s owner

#{assignee}

User work object

the work object’s assignee

#{initialAssignee}

User work object

the work object’s initial assignee

#{previousAssignee}

User work object

the work object’s previous assignee

#{candidateUsers}

List of user work object

the work object’s candidate user list

Resolving hierarchy variables

A major difference between frontend expressions and backend expressions is the visibility of work object variables within the work object hierarchy. With frontend expressions, accessing parent or root variables requires explicit use of the appropriate qualifier (e.g. parent.attribute).

With backend expressions, however, this is not always required. In the server, variables from parent work objects in the hierarchy are also visible in the child work objects. If a parent and child both have variables with the same name then only the child variable will be visible in the child work object.

For example, take the following work object hierarchy:

variablehierarchy

If we are resolving variables in the task context, then the expression #{case.message} will resolve to "Case message".

The expression #{process.message} will also resolve to "Case message" the process work object will inherit the message value from its parent (the case).

The expression #{message} will resolve to "Task message", however, as the variable inherited from the case has been hidden by a more local value.

Bean resolution

Backend expressions can also be used to access java beans, either to make method calls (#{beanName.method()}) or to access bean properties (#{beanName.property}).

For security reasons it is obviously not a good idea to allow access to all beans within the server, and so edoras one only allows access to a specific set of approved bean names.

Predefined functions

Backend expressions also support a number of predefined functions. As with bean resolution, the functions provided by a given edoras one installation can be configured, so the list of available functions may vary from system to system.

The following functions are provided by default:

now()

returns the current date and time

formatDate(Date date, String pattern)

returns the provided date formatted according to the provided pattern. When input parameters are null or empty throws IllegalArgumentException.

formatDateNullSafe(Date date, String pattern)

returns the provided date formatted according to the provided pattern. When input parameters are null or empty returns empty string.

formatType(Type type, boolean lowerCase)

returns the provided type formatted as a String. When type input parameter is null throws IllegalArgumentException.

anyOf(Boolean... operands)

returns true if any of the provided booleans is true, false otherwise

allOf(Boolean... operands)

returns true if all of the provided operands are true, false otherwise

concatenateListWithList(List<T> base, List<T> toAppend)

returns a list that is the concatenation of the given two lists

concatenateListWithElements(List<T> base, T... toAppend)

returns a list that is the concatenation of the given lists and the given elements

extractValuesFromCollectionOfMaps(Collection<Map<String, T>> maps, String mapKey, boolean skipNullValues)

returns a collection of map values for the given key from the given collection of maps

Identity Manager bean

The predefined bean #{identityManager} provides functions related with the group management and the session user name.

The available functions of this bean are:

getUsersOfGroup(GroupId)

returns the list of users of a given group.

getUsersOfGroups(Collection<?>)

returns the list of users of a collection of groups. Only objects of String and GroupId type are allowed in the parameter.

isUserInGroup(UserId userId, GroupId groupId)

returns a boolean which value is true if the given user belongs to a given group.

isUserInGroups(UserId userId, Collection<?> groupIds)

returns a boolean which value is true if the given user is member of at least one group in the collection, false otherwise. In case of empty list false is returned. Only objects of String and GroupId type are allowed in the parameter.

isUserInAllGroups(UserId userId, Collection<?> groupIds)

returns a boolean which value is true if the given user belongs to all groups in the collection, false otherwise. In case of empty list false is returned. Only objects of String and GroupId type are allowed in the parameter.

getSessionUserName()

returns the display name of the current session user. It also adds the information if the user is impersonated by another user.

getCurrentSystemAdminUserId()

returns the current tenant system administrator user id.

Model Manager bean

The predefined bean #{modelManager} provides functions related with the models.

findLatestDefinitionKeyByModelId(String testModelId)

Returns a string which contains the latest active definition key by the given model id.

System properties in backend expressions

The expressions using system properties with dots in the name are supported in the following way, for the example for the property mail.smtp.from:

#{systemProperties['mail.smtp.from']}

3.13.3. Common attributes

Work object attributes

A number of predefined attributes are available on every work object:

Table 67. Predefined work object attributes
Expression Type Description

name

String

the work object’s name

description

String

the work object’s description

state

String

the work object’s state

type

String

the work object’s type

ownerId

User ID

the work object’s owner

assigneeId

User ID

the work object’s assignee

candidateUserIds

List of group IDs

the work object’s candidate users

candidateGroupIds

List of group IDs

the work object’s candidate groups

creationTime

Date

the work object’s creation time

updateTime

Date

the work object’s last update time

dueTime

Date

the work object’s last due time

priority

Number

the work object’s priority

User attributes

The following attributes are defined in user work objects:

Table 68. Predefined user attributes
Expression Type Description

login

String

the user’s login name

name

String

the user’s display name (full name)

firstName

String

the user’s first name

lastName

String

the user’s surname

address

String

the user’s address

phone

String

the user’s telephone number

mobile

String

the user’s mobile telephone number

email

String

the user’s email address

language

String

the user’s language

homeUrl

String

the user’s home URL

notes

String

the user’s profile notes

memberGroups

List of group IDs

the groups ids which the user belongs to

3.14. Localization

In this section you can find how to localize your application models.

edoras one supports five languages: English, German, French, Spanish and Italian. When modelling, it is possible to define different language texts for tasks, forms widgets, cases, etc.

3.14.1. Key concepts

Localised texts fall into one of two categories:

  • design-time (non-runtime) text that is displayed in the modeler dashboard and in model previews

  • runtime text that is used for corresponding runtime objects (usually marked with RT)

For example, a task in a process model has the following Name attributes in the process design view:

localizationAttributes

As you can see, the value of the plain Name attribute is shown as the task label in the model.

When a user task is created, the runtime attributes will be used to set the task name:

localizationTask EN

Note that it is only necessary to define separate runtime and non-runtime texts if different values are required. In the above example, displaying an expression in the task label would be ugly and not meaningful in a process preview so it’s a good idea to provide a separate design-time label for the task.

In general, if no specific runtime text is provided then the design-time text will be used instead.

3.14.2. Localize applications models

In order to set the supported languages of the application model, firstly they should be defined in the 'Browse' view. There you can set a primary language and various secondary languages.

If your language is not maintained in a particular App model, it defaults to the primary language defined.

localizationAppModel

3.14.3. Localize case models

In order to localize the cases, the modeller should navigate to the 'Browse' view and click in 'Localize' action button. The name and description of the case can be set in the languages defined in the application model.

localizationCaseModel

3.14.4. Localize process models

In order to localize the processes, the modeller should navigate to the 'Browse' view and click in 'Localize' action button. The name and description of the process can be set in the languages defined in the application model.

localizationProcessModel

3.14.5. Localization in VIS

There are some attributes of VIS elements which can also be localized, for example the labels or the task names can be set in the languages defined in the corresponding App model. To see the localized attributes in the attributes panel, the language must be selected at the top-right of the panel. A list with the application model languages will be displayed:

localizationSelectLanguageVIS

When a language is selected, a new attribute for each attribute which can be localized will be added in the attributes list:

localizeAttributesVIS

At the end of the attributes list an i18n-key attribute is also added. This key is used in exporting and importing all translations within an App model.

Moreover the design and preview form will be displayed in the language selected in the menu.

3.14.6. Exporting and Importing translations used in Process, Form and Case models

To make localization easier to manage, edoras one supports exporting and importing of text translations used within the Process, Form and Case models belonging to a given App model.

Translations for all the attributes which support multi-language entries in the vis designer view and have a i18n-key specified are exported to respective language specific translation_<language-code>.properties file bundled into a <App-Model-Name>-translations.zip file.

Each translation file has a global section at the top followed by model specific sections. The global section contains common i18n-keys used across multiple models within the App. While the model specific sections contain i18n-keys used only within each model.

In cases where same i18n-keys are used in multiple attributes within various models of an App and such attributes have different values, commented duplicate key value entries are exported in the translation properties file to facilitate the user to choose the correct one among them and then import it back into the App model.

The translations in the language specific properties files can be edited as required and re-zipped into a zip file and imported using the Import translation action of the App model. The new translations will then be set to the attributes which have the matching i18n-key entries within all the models of the App.

Rich text content edited with the rich-text editor are exported in HTML format within an enclosing <rich-text> tag. This enclosing <rich-text> tag needs to be retained while importing the translations so that the formatting is preserved.

3.15. App overview

edoras one supports the export of an App overview containing a summary of all models, the elements within those models (e.g. tasks in a process model), and the attribute values.

This overview can be useful for analyzing the App structure, and allows the contents of the App to be searched (e.g. to find usages of a particular variable name).

To export the App overview, select the Export overview action in the App actions list, choose the format that the overview should be exported in, and press Download. The following formats are supported:

JSON

creates a hierarchical JSON structure, also for complex attribute values such as lists or maps.

Excel

creates a Microsoft Excel worksheet with the columns Model ID, Element ID, Attribute key and Attribute value. Attributes from the root model have an empty Element ID value. Complex attribute values are 'flattened' into mutiple rows with name key[i] for the i-th element in a list and key.X for a map entry with key X (where key is the base attribute key).

3.16. Attribute value replacement support in VIS

VIS supports attribute value replacements in Case, Process and Form models when [[attribute-id]] place holders are used in the attribute values.

In an attribute’s value, one can reference another attribute by giving the attribute-id of the other attribute, for example, in the "Description" attribute’s value (of a Human task), you can have "This task has priority=[[priority]]" where "priority" is the id of the "Priority" attribute.

attributeReplacements

In this case, in the generated CMMN XML the description value will be exported as "This task has priority=1" if the priority attribute’s value is 1. In case the priority is left blank, then, it will be exported as "This task has priority=".

Multiple [[attribute-id]] place-holders can be used within an attribute’s value and all of them will be replaced as described above.

Run-time (RT) values of attributes will be used for replacement, where available, else the design-time values will be used for fall back.

3.16.1. Attribute value replacement support in REST URLs

Attribute place holders ([[attribute-id]]) used in REST URLs which are used to load REST Combo-box data at design-time are replaced by design-time attribute values.

However, in cases where values entered in the attribute’s RT fields need to be used for replacement in REST URLs an _rt suffix (as in [[attribute-id_rt]]) should be used.

3.17. Design time notes support in VIS

VIS supports adding design time notes to all process elements, case elements and form widgets. These notes are not shown in the previews.

designTimeNotesContextIcon

Whenever an element or widget is selected in the design view, a small Notes icon is shown near the top-right corner of the selected element or widget, clicking on which displays the notes call out box where the design time notes can be entered.

designTimeNotes

Clicking again on this icon will hide the design time notes for that element or widget.

designTimeNotesToolbarMenu

The toolbar also has a Notes menu-item which can be used to toggle the display of all the design time notes added within the diagram.

3.18. Front end scripting reference

The edoras API provides a set of commands and utilities to interact with ONE in a standardised way.

It eases the job of the implementer by leveraging the most common operations in a small set of operations.

The API can be consumed via script buttons or in a developer console in the browser accessing the global property window.edoras. We recommend to use the developer console to test ideas and debugging and then move your code to the script button before deploying.

browser console
Table 69. The API is organised around these different namespaces

UI

UI

Proxies commands to the user interface to interact with the application via CLI. Think of this namespace as a lightweight version of a browser driver like Selenium or WebDriverIO.

Examples

refresh

Refresh the page data without reloading the html, it returns a promise which is resolved when the refresh is finished.

refresh
edoras.ui.refresh().then(()=>alert('Refresh has been done!'))

Actions

Whenever a view exposes actions to the user, they can be reproduced using this namespace as if the user interacted with the UI manually.

Functions

  • Save: Saves the current work object

  • Complete: Completes the current work object

  • Discard: Discards any changes in the current work object

  • Assign: Assign the work object to another user

  • Create: Creates the current work object

  • …​

Actions
edoras.ui.actions.save()
edoras.ui.actions.complete()
edoras.ui.actions.discard()
edoras.ui.actions.assign()
edoras.ui.actions.create()

globalMessage

Shows a message to the user.

Functions

  • Show: Shows the first parameter (String) as a global message, with optional type in the second parameter [info, success, error]. Alternatively, a single Object parameter can be used as first parameter:

    • type: (String) one of [info, success, error], used to modify the container behaviour and style.

    • title: (String) The title in the message container.

    • body: (String) Body text of the message.

    • mainLink: (String) Url link of the title.

    • otherLinks: (Array) Body section with link list. e.g. {otherLinks:[{name:'link text', url:'http://url'}]}

    • autoHide: (Number) Time (in ms) after which a global message modal will be closed automatically. Set to 0 to disable.

  • Hide: Hides the current message.

GlobalMessage
edoras.ui.globalMessage.show('hello world')
edoras.ui.globalMessage.show('hello world', 'error')
edoras.ui.globalMessage.hide()
edoras.ui.globalMessage.show({
  title: 'hello world',
  body: 'Lorem ipsum dolor sit amet',
  autoHide: false,
  mainLink: 'http://edorasware.com',
  type: 'success'
})

navigate

Navigate to views and action views

Functions

  • config: allows to config global options for "to" methods

    • avoidHistory: When navigate, it will avoid to create history points by replacing the history current state with the new url.

  • to: navigates to the entity or dashboard with the view specified given the following table

Entity

Views

home

eventsLog

dashboard

user, modeller, manager, administrator, <any>

case

task

document

QUERY

editEntity, editEntityJson, search, browse, comments, startProcessAction, assignAction

  • reload: reload the whole page

Navigate
edoras.ui.navigate.to.home()
edoras.ui.navigate.to.dashboard('manager')
edoras.ui.navigate.to.task(taskId)
edoras.ui.navigate.to.task(taskId, 'create')
edoras.ui.navigate.to.case(caseId, 'assignAction')
edoras.ui.navigate.reload()

REST

REST

Not implemented

Provides direct access to the backend rest endpoints.

Examples

WorkObject

Create, update, read and delete WorkObjects

WorkObject
edoras.rest.workObject.create(workObjectPayload)
edoras.rest.workObject.delete(id)

CurrentState

CurrentState

Exposes the current state of the application

Examples

user

Get the current user

User
edoras.currentState.user.get()

forms

Get the current forms and read or set values in them

Functions

  • get: Gets a form from the current forms loaded in the view (by index)

    • data

      • get: Return a copy of the data of that particular form

      • set: Sets some data in that particular form

    • components (not yet implemented)

      • get: Returns the list of components loaded in that particular form

forms
edoras.currentState.forms.get(0).data.get()
edoras.currentState.forms.get(0).data.set('name', value)

formData

Gets a copy of the data from the default form of the current view

Functions

  • get: Gets a copy of the data in the current default form.

  • set: Sets some data in that particular form

edoras.currentState.formData
edoras.currentState.formData.get()
edoras.currentState.formData.set(field, value)

tempData

Gets a copy of the temporary data from the default form of the current view

Functions

  • get: Gets a copy of the temporary data in the current default form.

  • set: Sets some temporary data in that particular form

edoras.currentState.tempData
edoras.currentState.tempData.get()
edoras.currentState.tempData.set(field, value)

WorkObject

Get the current in-memory work object data

WorkObject
edoras.currentState.workObject.get()

Services

Services

Provides access to ONE services and allows registering custom services on demand to use globally in the app

Examples

register

Sets a function as a ONE service by providing a name and a reference

register
edoras.services.register(serviceName, serviceFunction)

edoras.services.register('foo', function(msg) { console.log(`foo${msg}`) });
edoras.services.foo('bar')
 // Outputs 'foobar'

i18n

Get translations for i18n keys

i18n
edoras.services.i18n.translate(key)

expressionService

Evaluates and normalizes expressions

expressionService
edoras.services.expressionService.eval(scope, expression, modelPropertyName)
edoras.services.expressionService.interpolate(scope, expression, modelPropertyName)
edoras.services.expressionService.normalize(bindingExpression, modelPrefix, removeCurlyBrackets)
edoras.services.expressionService.toNormalizedParseString(expression, dataModelPrefix)

edoras.services.expressionService.eval({foo: {bar: 7}}, '{{bar + bar}}', 'foo');
edoras.services.expressionService.interpolate({foo: {bar: 7}}, 'Result = {{bar + bar}}', 'foo');
edoras.services.expressionService.normalize('{{bar}}', 'foo', true);
edoras.services.expressionService.toNormalizedParseString('{{bar + baz}}', 'foo');

ViewEngine

ViewEngine

Extend the form renderer configuration

Examples

ViewEngine
edoras.viewEngine.configuration.extend({configuration})

EventLog

EventLog

Get the history of actions triggered by edoras API

Examples

EventLog
edoras.eventLog.get()

Configuration

Configuration

Provides means of configuring and extending the client.

Examples

widgets

Implementers can register new components to use in the view engine by using this namespace.

Functions

  • Register: Register a new widget into the client

  • Types: Widget type constants

  • Modules: Used by angular to import the widget modules

Widgets
edoras.configuration.widgets.register({
    module: // angular module name to be used by the framework dependency injection
    config: // widget configuration (check in widget creation guide)
    name: // name of the widget used by the View Engine
    type: // one of the types provided by edoras.configuration.widgets.types
})

edoras.configuration.widgets.types === { COMPONENT: 'COMPONENT' }

Chain

Chain

Execute a sequence of API commands

Examples

Execute a sequence of API commands

Functions

  • Chain: Starts a chain of commands

  • Step: Queues a function to be executed sequentially. Takes a function with one parameter ( x ) that will be the last returned value from the previous step if present.

  • Go: Starts the execution. It returns a promise which resolves the last step value. If some step returns a rejected promise, next steps are not executed and resolution contains the rejection result and the stepNumber.

Chain
edoras.chain()
   .step(function(x) { edoras.ui.navigate.to.case('GEAR-a123b456-c789-a123-b456-c789d123') })
   .step(function(x) { return edoras.currentState.forms.get().data.get('name') })
   .step(function(x) { edoras.currentState.forms.get().data.set('name', x + '1337') })
   .step(function(x) { edoras.ui.actions.save() })
   .step(function(x) { return 'Love your work!'; })
   .go()
   .then(function successCallback(info){
    edoras.ui.globalMessage.show(info.result, 'success');// if success, will show a message 'Love your work!'
   })
Chain with rejected promise
edoras.chain()
   .step(function(x) { edoras.ui.navigate.to.case('GEAR-a123b456-c789-a123-b456-c789d123') })
   .step(function(x) { return edoras.currentState.forms.get().data.get('name') })
   .step(function(x) { edoras.currentState.forms.get().data.set('name', x + '1337') })
   .step(function(x) { return Promise.reject('failed'); })
   .step(function(x) { /* this step is not executed */ })
   .go().then(
    function successCallback(){},
    function errorCallback(errorInfo){
       console.log('chain had an error on step:' + errorInfo.stepNumber + ' with result:' + errorInfo.result);
       //chain had an error on step: 4 with result: failed
   });

3.19. Glossary

app

an app is a container for a collection of models that define a specific workflow.

backend expression

a backend expression will be evaluated in the server, for example to populate a mail template before it is sent.

dashboard

a page in the edoras one application where work objects can be found, displayed and manipulated. Each dashboard manages related work object types that play a given role within the system.

definition

when a model is deployed, a definition is created in the system. Definitions describe the behaviour of the system as seen by a normal user.

deployment

the process of converting the models into definitions to create an executable workflow.

document placeholder

a backend expression identified by a key in a document model. Used to insert dynamic content into documents.

expression

an expression can be used to access content or trigger specific behaviour at runtime. Two types of expressions are used: frontend expressions and backend expressions.

form

a form is a graphical layout of fields that may be bound to work object data to allow this data to be displayed or modified within the edoras one application.

form widget

a form widget is a type of form field, e.g. text form widget, date form widget, number form widget. The form field represents the single element on the form whereas the form widget represents the type of these single elements. As such the form widget defines the look and behaviour of the corresponding form fields.

form field

a form field is a single element on a form. The user interacts with the form field, most of them are interactive but some of them are read-only.

form field part

a form field is composed of different graphical parts: a label, a control, a description, a required indicator. The user interacts with the control part only.

frontend expression

a frontend expression will be evaluated in the browser, for example to bind form fields to work object data.

model

a description of a workflow component which can be deployed together with other models to create a executable workflow in edoras one

process

a process is a workflow definition, described using a BPMN 2.0 model and executed within edoras one. It typically defines the automated and manual tasks that must be performed to complete the workflow.

system app

a special App that can only be seen by the administrator. It contains the models that are required for the correct operation of edoras one.

task

a task is a single action within a workflow, and may be either automated (a service task) or manual (a user task).

work object

an item that can be created or manipulated in edoras one. Different types of work object are supported. The work object types are typically grouped according to their role within the system and accessed through dashboards.

4. edoras one Modeler Tutorial

4.1. Intro

This step-by-step tutorial will help new edoras one modelers get started with defining Apps for the edoras one platform.

It’s a good idea to have read the basic edoras one intro (general guide) as well as the edoras one user guide, both of which can be found here: http://documentation.edorasware.com

4.1.1. What you will learn

By following this tutorial, step by step, you will learn how to create your own App, including the following:

  • Creating case models

  • Designing forms

  • Designing processes

  • Creating ad-hoc task models

  • Creating email templates

  • Creating documents models

  • Creating queries

  • Customizing dashboards

4.1.2. Tutorial App

For this tutorial we will use the scenario of building an App to handle travel requests. A person who needs to travel will start a new travel request, and a travel agent will organize all the necessary bookings for the trip.

The request process will be built step by step, adding approvers to the process, modeling a feedback-loop between travel agent and requestor and by adding mail tasks to send out information once the travel has been organized.

Everything around the travel request is modeled within a case, so we can attach any necessary information (such as reservation information or vouchers) directly to the case, as well as having an overview of everything going on while managing the travel request.

4.2. Basic Travel Request Case and Form

In this chapter you will create the Tutorial App with a new form and case model, deploy it and test the new case model within the user dashboard.

4.2.1. Creating a new App

In order to get started, go to the modeler dashboard and hit c or click the Create button in the menu and choose Create App.

Type Tutorial App as the name for the App.

Select English as the primary language for the App.

Select any other languages you want as secondary languages.

As an App can be modeled in several languages, you specify a main (primary) language for the App, which will act as the default language, if not all elements are translated. You will be able to design forms and processes with all languages you selected (primary will be default). Now click Create and navigate to the newly created App by clicking on the link in the green success message you see on the top of the screen.
create app 01

4.2.2. Creating a form to start the travel request

Let’s create a first form by typing again c (shortcut) or clicking the Create button in the menu. Now let’s choose Create Form Model and make sure the Tutorial App is selected as the parent App (meaning the new form model will be created inside that App).

Type Travel Request Form as the name for the new form model and click Create and design in order to create the model and directly go to the form designer.

create form 01
Getting familiar with the basics of the form designer

The form designer consists of three parts: on the left you can find the shape palette, the main canvas for the form design in the middle and on the right-hand side you can find the attributes of the currently selected widget (component) on the canvas.

You can add a new widget to the canvas by simply dragging & dropping it from the shape palette to the canvas. During the drag & drop you will get feedback by the responsive layout manager on where the widget can be dropped.

The layout is responsive, with twelve slots you can use to arrange your widgets. By using the handles on the left or right side of a widget, you can define the span of the widget from one up to twelve slots.

The shape palette has several sections to choose from. Use the predefined widgets if you don’t want to worry about bindings and any other technical issues. The widget section has a wide collection of all the available widgets, which will need configuration through the attributes section.

Add name and description widgets

To start with the design, let’s use two predefined fields: the name and description. These fields are always available and each work item supports them.

Now drag & drop the name and description field from the predefined bindings section on to the empty form. Rename the name label to Travel subject and the description label to Travel notes.

form design 01
Add traveling locations

Now let’s add two fields to enter the origin and destination of the travel. There is no predefined field for location, so let’s use the Text field from the Components section. Name the first one Origin and the second one Destination. By dropping the second field onto the first one, the row will split into two parts with both fields in the same row, each spanning six slots.

Instead of navigating through the shape palette, you can also use the filter functionality to quickly find a specific widget. Click the filter icon in the top right corner of the Shape palette and type the name of the widget into the search field (e.g. text).

To make the fields mandatory, select a field and click the red star icon. Do this for both Fields. You can also achieve the same result by clicking the Required attribute in right side panel.

form design 02
Getting familiar with the data model behind work items

Before we can define the data bindings for the new fields, let’s have a short look at how data is stored and managed within edoras one.

The basic structure to manage anything within edoras one is called a work item. A work item is an object of a particular type (e.g. a case, a task, a process or a document), its behavior is driven by its type and model (e.g. a process work item is driven by its process model, which in our case is modeled with BPMN 2). Besides its behavior, every work item is able to store arbitrary data, called variables. Variables hold different types of data, such as text, numeric value, a date or a boolean value. Variables can even hold lists of data or maps or even lists of maps with unlimited nesting.

In order to enter or display the data of work items, its variables can be mapped (bound) to fields.

Define data bindings for the fields

The next step is to set the binding for the newly added fields. Double-click the field or go to the Value attribute on the right side. Bindings tell the form engine where to save and load the data for a particular field.

Let’s save the origin in a variable named travelOrigin and destination in a variable named travelDestination, respectively. Bindings are specified using expressions, which start with a double curly brace {{ and end with a double curly brace }}.

If we don’t specify any prefix to the variable name, the data is stored and retrieved from the same work item the form is associated with.

form design 03
Add date pickers for the outward and return trip dates

Now let’s add two new fields to pick the starting and ending date for the travel. Drag & drop two Date fields on the form and name them Outward trip date and Return trip date, respectively.

Make the fields mandatory and set the bindings to {{outwardTripDate}} and {{returnTripDate}}.

form design 04
Add validation to the date pickers

As we want to make sure there is no date selected in the past, let’s add a validation rule to the date picker.

You can do so by selecting the date field and then clicking on the Minimum date attribute on the right side under Specific attributes. Select a relative date validation by choosing Today + 0 Days.

form design 05

For the Return trip date we also want to add a validation rule. Here we want to ensure that the selected date is not before the Outward trip date. To achieve this, we simply add {{outwardTripDate}} to the Minimum date attribute of the Return trip date widget.

form design 06

Save the form by clicking the Save icon in the designer menu on the left.

4.2.3. Create case model

Now switch back to the browser tab where you created the new form (not the form designer) and click the Create button once again and select Create case model.

Fill out the case model form:

  • Set Travel Request as the name

  • Choose the Travel Request Form as both the init form and the work form of the case

  • Everything else can be left as it is by default, we will make changes to that later in the tutorial

Click Create to create the new case model.

create case model 01

4.2.4. Deploy the App

Done! We have our very first version of the Tutorial App ready to be deployed and used.

Click the Tutorial App link from the previous green success message, or the link within the header of the current case model in order to navigate to the Tutorial App.

In the App, you should now see two models: the Travel Request case model and the Travel Request Form model.

From the list of actions on the right side menu you can select Deploy, opening the deploy dialog. Navigate to the end of the dialog and click OK to deploy the App. This will make it available within the user dashboard, so now we can test it.

app deploy 01

4.2.5. Test the App

In order to test the newly deployed App, we switch to the user dashboard. You can do so by selecting the User dashboard from the menu of dashboards or use the d shortcut. While modeling and testing, it is also a good practice to have two tabs open constantly, one with the user dashboard and one with the modeler dashboard.

Once in the user dashboard, click Create or type c to open the creation dialog. Select Create Case and choose Travel Request from the selection menu.

Fill out the request init form we’ve just designed. Please note the validation checks within the date picker, specifically notice that you will not be able to enter a date earlier than today.

create case 01

Click the Create button to complete creation of the new case. You will see the newly created case displayed using the same form, as we set it for both the init and the work form. Now you will be able to modify any values and click Save in order to change the data for that case.

create case 02
A copy of the tutorial App at this point is availble in the distribution bundle as ModelerTutorialApp1.zip.

4.2.6. Getting familiar with basic navigation

On the right side you will find available actions for the current work item (a case currently). The top right area shows the available views of the work item.

case menu 01

Actions, from top to bottom:

Assign

lets you specify the owner and current assignee of the work item

Share

lets you share the work item with one or more groups

Start Process

starts an ad-hoc process within the current case

Archive

closes the current work item and archives it

Views, from left to right:

Search

navigates to the list of children for the current case, where you can find open tasks, documents or whatever the current case is holding

Browse

navigates to the main work form of the current work item

Comments

navigates to the comment section of the current work item, where you can see all existing comments as well as add new comments or reply to existing ones

Edit Entity

(only available to modelers) shows a generic view with all data of the current work item and the ability to change it or even add new variables

Edit Entity JSON

(only available to modelers) shows the JSON representation of the current work item, which can also be modified. Great care needs to be taken as you could break data of the work item by incorrectly modifying its JSON representation.

4.3. Basic process modeling

In this chapter you will learn how to create your first process, attach it to the case model created previously, and then to start it automatically when a new travel request is created.

4.3.1. Create new "Travel Request Process" model

Switch back to the modeler dashboard (either through the dashboard switcher or by going to your second tab with the modeler dashboard still open).

Choose the Tutorial App if not yet open and click Create or hit c. Now let’s choose Create Process Model and enter Travel Request Management Process as its name, then click Create and Design to create the process model and immediately open it in the process modeler in one step.

create prc model 01

4.3.2. Getting familiar with the process modeler

The process modeler is quite similar in its basic functionality to the form designer. On the left-hand side you can find the shape palette with several sections from where you can choose process elements. The middle area is the main canvas area where you design the process. The right-hand side shows the attributes of the currently selected element in the process canvas.

You can add elements to the process by simply dragging and dropping them from the shape palette onto the canvas.

Hint: as you start modeling processes, the spacing tool is a very handy feature to make more space in your current process model:

prc modeler action 01

Activating it will allow you to easily expand sections of the process model or make a section smaller. Give it a try once you have some elements on the canvas and make yourself familiar with using the feature. Simply turn it off by clicking it once again to deselecting it.

4.3.3. Add a pool and lanes to the process

Let’s start the process model by adding a pool and lanes to it. This is optional in BPMN 2, but is a good practice in order to visualize the different roles, people and groups involved in the process.

Go to the Roles section in the shape palette, drag & drop a Pool onto the canvas and name it Travel Request Process. A single lane has been added automatically, double-click its label (called Lane) and rename it to Requestor.

prc modeling 01

Now let’s add a second lane for the travel agent managing the travel request. Select Lane from the Roles section of the shape palette and drag it to the bottom part of the pool; dropping it will add it as a second lane below the existing one. Name it Travel Agent. Using the spacing tool, it’s easy to make the lanes smaller or larger according to need.

prc modeling 02

4.3.4. Model two user tasks as the first version of the process

We’ve now created two lanes representing two different types of people involved in the process: the requestor actually creating the travel request, and the travel agent responsible for managing the travel.

Let’s add a start event to the process by dragging the Start event element from the Execution section of the shape palette onto the Requestor lane. When an element is selected, you should see the fast-modeling menu floating next to the element. The start event element should still be selected, so click the user symbol from its fast-modeling menu in order to add a user task immediately after the start event. Name it Manage Travel Request, click on the user symbol again and name the next task Review Travel Bookings, then finally click the thick rounded end event in the fast-modeling menu.

Done! We have our very first process with a start event, two user tasks and an end event, looking something like the following:

prc modeling 03

Now let’s get the tasks into the right lane simply by moving them. Move the Manage Travel Request task into the second lane, as it should be done by the travel agent. Make use of the spacing tool in order to add or remove space between lanes and elements.

prc modeling 04

4.3.5. Save process model and attach it to the case model

Save the process model by clicking on the Save action in the menu bar (we will add task forms later, so ignore any warning messages for now) and switch to the browser tab with the process model within the Tutorial App (not the designer window).

Navigate to the Tutorial App and select the travel request case model. In the Autostart Processes selection choose the newly created process model and save the case model again.

map prc case model 01

4.3.6. Re-deploy and test the App

We’ve now created our first, albeit simple, process model and attached it to the existing case model. We can now re-deploy the App by using the Deploy action as we did before and switch to the user dashboard in order to test the changes made.

After successfully deploying the Tutorial App, switch to the user dashboard and click Create then select Create Case. Select the Travel Request template, fill out the form and start the next travel request case.

Did you notice the gray badge in the left top corner of the children view button? It shows you that there is one child work item of the current case, which is the first task being created by the process.

case testing 01

Click the children list view to see that task. The open task should be named Manage Travel Request and behind it you should see the name of the travel request case (the same as in the header).

case testing 02

Navigate to the task by clicking its name. It will take you to the work form of that user task. You can still see the case in the header section of the task and use it to navigate back to the case, or you can also use the browser back button to go back. To navigate to the task, select it as the current work item. As you’ve probably noticed, this will change the available views and actions, always reflecting the possibilities with the currently selected work item.

case testing 03

The user task has a default form with the name of the task and a description field. But let’s have a look at the different options available when working with the task. There is a new view called Preview; selecting it will display the process with a red border highlighting the current task.

case testing 04

Go back to the work form by clicking on the Browse button, add some notes and click Complete. This will complete the task and hand control back to the process engine, continuing with the process execution and, in our case, leading to the second task being created. You can go to the preview again and see that the process execution has now moved to the second task. Complete the second task as well and this will finish the process execution. You can then navigate back to the case by using the case link in the header of the task, and check that the children view doesn’t show the badge anymore, as there are no more opened tasks available.

4.3.7. Create user task forms for process execution

As we haven’t created specific user task forms yet, you’ll have realized that default forms were used. Of course, this doesn’t make much sense for real use and we can improve the two user tasks by designing task forms for them, showing all necessary information needed to complete each task.

Switch back to the process designer (if still open, otherwise switch to the modeler dashboard, select the process model and click Design to open the process modeler).

Select the Manage Travel Request user task. There are two ways to create or select a form for this user task: either click the Add reference context menu; or, go to the attributes of the task and click the Form reference attribute.

Here, you can choose between selecting an existing form (of course we don’t have any suitable forms yet) or creating a new one. And that’s what we’re going to do, so choose New. The form designer is opened again, ready for a new form to be designed that will be automatically attached to that task.

Understanding the work item hierarchy

Before we start designing the new task form, let’s have a look at how the data is organized in the work item hierarchy. The process is started within the case, making the process instance a child work item of the case. If a user task is created automatically through the process, this task becomes a child element of the process. You can think of this as a hierarchy, where the case is the root, having a process as a child and the process having a task as its child:

WorkObjectHierarchy

You can store data on every work item, and every work item has also access to the data of its parent up to the root. But of course when building form data bindings, you need to be aware of the hierarchy and where the form is actually used. Bindings such as {{foo}} without any prefix are always bound to the work item that form is used with. If you want to store or read data from the case, use the root prefix, for example {{root.foo}} would store or read the data from the case’s variable named foo. You can also use the special parent in order to go up one level in the hierarchy of the current work item. For a user-task, its parent is the process the user-task is part of.

Show task information using an output widget

Now let’s go back to our user task form for managing the travel request. It’s good practice to display helpful information about the current task on the task form. As a first step, we can add an Output textarea to it in order to display the travel request details in a read-only way. Drag and drop an Output textarea from the shape palette onto the form, but don’t enter a label name, just leave it blank.

Double-click the widget on the form, or click the Value attribute, to open the rich editor to edit the content for the widget.

Let’s add something like this:

user task design 01

You can use formatting and add any text you want. Of course, you can also add expressions in the same way we did with the data bindings of fields. Please note that we are now designing the form of a user task and hence we need the root prefix in order to display data that is stored on the case. Make sure you use the same variable names that you used in the case init form.

Add editable information to the form with a rich text area

We want the notes for the travel request not only to be shown, but also to be editable by the travel agent, so let’s include a notes field to the form using the predefined widget named Case description. Drag & drop the Case description field from the Predefined bindings in the shape palette below the output widget on the form and rename its label to Travel notes.

We can now additionally add a hint in the notes field to let the travel agent know that he should enter additional information here. Select the travel notes field and click on the Description attribute on the right side. Enter something like Please add any additional information for the travel in here. You can also directly edit that description by double-clicking it directly in the form widget.

The form should now look like this:

form design 01

Save the form with the name Manage Travel Request Task Form. In order to re-use the output widget with all its configuration details, select the output text area widget and copy it. You can now close the form designer browser tab, which should take you back to the process modeler.

Create second task form

Switch back to the process modeler browser tab and click on the Add reference context menu for the second task, named Review Travel Bookings, and again select New. In the new form designer, paste the output widget we previously copied from the first user task form. Note that copy and paste is supported across models, not only within the same model, which can be quite handy for quickly modifying models.

Double-click the output widget in order to change its content to reflect the current task we want to create the form for. As this is just a review task, we’ll include the traveling notes in there directly rather than using a description field as we did in the previous form.

user task design 02

Now save the task form, name it Review Travel Bookings Task Form and close the form designer browser tab.

4.3.8. Redeploy the App and test again

We’ve successfully added two new task forms and attached them to the appropriate user tasks in the process. So let’s test it by deploying the App again, creating a new travel request and stepping through the process.

Make sure you save the process model too before you redeploy the App, as we have also changed it to map the newly created forms!

Once you have redeployed the App, create a new case, click on the children view and select the manage travel request task. You should now see the specific task form we designed:

prc testing 01

Add some notes, complete the task and check whether the data in the second task reflects this correctly.

A copy of the tutorial App at this point is provided in the distribution bundle as ModelerTutorialApp2.zip.

4.4. Improving the forms

In the last two chapters we created a new App, a case model, a case initialization form, a management process, as well as task forms in order to reflect our needs for the travel request case.

In this chapter we will further improve the forms, making them more user-friendly and add an attachment widget to it, then later turn it into a subform and reuse that in other forms.

4.4.1. Add an attachment widget to the case form

Instead of having to manually upload any booking documents, let’s place an attachment widget directly to the case form for easy access to this capability.

First, switch back to the App in the modeler dashboard, navigate to the Travel Request Form and click Design.

Let’s add a comment on the attachment widget for the user to understand how to use it in our context. Drag & drop an Output textarea to the bottom of the form, don’t add a label, and double-click the widget to open the rich editor and enter something like this:

form design 01

Below the output widget, drag & drop a new Attachment widget from the Component section of the shape palette and name it Attachments / bookings. Like text data bindings, the attachment widget can also be bound to a variable, which will hold all information about any attachments uploaded. Use the binding {{attachments}} this time and your form should look like this:

form design 02

Now let’s fine-tune the widget by selecting it and changing some attributes. First, let’s customize the Select file message by changing the default value to Upload any booking documents here or similar. Set the Preview type to Thumbnail, as we want to include a preview in the attachments, if possible. Set the Thumbnail maximum height to 200 to prevent big pictures from using too much space on the form.

4.4.2. Redeploy and migrate existing cases to reflect new version

Now save the case form and redeploy the App. Instead of creating a new case straight-away, let’s have a look at how versioning is done while deploying an App.

Understanding App and model versioning

Whenever an App is deployed, all of the models within it will be deployed to the runtime of the edoras one platform, and then they become available within the user dashboard. An App is deployed as a new version every time you deploy it, to make it fully consistent and compatible with all the models it contains. By default, the deployment mechanism uses a safe strategy of not migrating existing instances to the new models, including cases, processes and tasks. This means they will still be mapped to precisely the version they were created with until they are either completed or migrated to a newer version. So, even with an updated form in an App, existing instances of it will continue to display and use the older versions of the form.

Migrate existing travel request cases to latest version

For now, we want our cases to immediately reflect the latest changes within the form (the attachment widget), so go to the Tutorial App and navigate to the Travel Request case model by selecting it. Click the Migrate action in the right side action menu of the case model, and migrate all existing cases to the latest, just redeployed, version of the App.

Switch back to the user form and select one of your previously created travel request cases to make sure they now reflect the latest version. You should see the attachment widget now:

case testing 01

Click the upload icon and attach an image, for example. You will have to save the case form in order to see the preview (thumbnail) of the uploaded image:

case testing 02

4.4.3. Turn the attachment section into a subform

It so happens that we also want to add the same attachment widget to the task forms. We could do this the same way as we did before using copy and paste, but this time we want to try a new feature of forms, sub forms, a great way for re-using existing parts of forms, either for technical or business reasons.

Go to the Tutorial App and click Create, select Create Form Model and enter Attachment Section Sub Form as its name, then click Create and Design to directly open it in the form designer.

First, go back to the case form designer and select both the output widget and the attachment widget and copy them to the clipboard. Switch back to the new, still empty, subform and paste the widgets there. The subform should now look like this:

form design 03

Save the subform and switch back to the case form designer ready to add it there, but first we need to understand how the binding works for subforms.

Understanding bindings in subforms

In order to use a subform in different forms and therefore different contexts, it is essential to isolate its data bindings and make them configurable outside of the subform where they are used.

Assume a subform has two fields in it with bindings to {{foo}} and {{bar}}. The subform may be used within a case form as well as within a task form, displaying the same data in those different contexts. Or the subform may even be used several times on the same form, but with different meanings (for example, an address subform used once for the main address and again for the billing address). In order to be able to deal with situations like this the subform itself needs a data binding as well, following exactly the same rules as explained earlier in this tutorial. So, for instance, if a subform is bound to {{mySubFormData}}, there will be a variable named mySubFormData, which itself will be a map holding all data contained in that subform.

Example 1:

  • a subform with two fields bound to {{address}} and {{city}}, respectively

  • the same subform is used twice in another form

    • the first representing the main address is bound to {{mainAddress}}

    • the second representing the billing address is bound to {{billingAddress}}

  • the possible expressions (for example within an output widget) include:

    • {{mainAddress.city}} representing the city of the main address

    • {{billingAddress.address}} representing the address data of the billing address

Example 2:

  • a subform with fields {{foo}} and {{bar}}

  • the subform is bound to {{$this}} (a special expression representing the context of wherever the subform is used)

  • this will result in the same behavior as if the two fields had been placed on the form directly rather than within a subform

Example 3:

  • a subform with fields {{foo}} and {{bar}}

  • the subform is used within a case form with binding {{$this}}

  • the same subform is used in a task form

    • we want the subform to always represent the same data of the current case

    • the subform therefore needs a binding {{root}} to map it to the root context to make sure it represents the same data in the task form as it does within the case form

Example 4:

  • same as example 3, but this time the subform binding in the case form is {{myData}}

  • the subform binding within the task form then needs to be {{root.myData}} to represent the same data as within the case form

Understanding different types of subforms

That’s now given us the basics for the binding and isolation of data in subforms. There are also some useful possibilities of dynamically changing which form is actually used as the subform, as well as whether the subform should have one element or is able to show multiple elements.

Single-element or multi-element subform?

Subform widgets can be configured to hold exactly one element (single-element) or can hold zero to multiple elements. There is a difference is how the data is mapped in these configurations. Single-element subforms will store their data in a map directly within the variable they are bound to. Multi-element subforms will store their data into a collection (list) of maps in the variable they are bound to and are able to hold 0 to n (none, one or many) elements.

Single-type or multi-type subform?

There are basically two types of subforms available: single-type or multi-type. A single-type subform will render just one type of form for all entries it is showing. A multi-type subform can hold different types of forms and uses something called a discriminator variable to determine which form should be used for which type in the list. Assume there’s a subform showing a list of selected products. For each entry (each product), there might be a different type of form necessary in order to represent the relevant product information. The discriminator would be mapped to the type of the product, so then the appropriate product form would be used in the subform to represent that specific product the best way.

Adding the subform to the case form

Now having learned more about how subforms are bound to data and the different types of subforms, let’s use it in our case form to change how we represent the attachment section of the request.

Go to the form designer for the Travel Request Form, if not already there, and delete the output textarea and the attachment widget, as now we want to replace them with the subform we just created.

Drag & drop a Single-type subform from the Components section of the shape palette onto the bottom of the case form and label it Attachments.

Click the + button at the bottom of the widget to select the subform we want to use. Choose Reference and then select the Attachment Section Sub Form as the referenced form.

Double-click the subform or click the Value attribute to enter the binding for the subform. As we want the same behavior as we had before without the subform, bind it to {{$this}}, meaning the data in the subform will be directly stored in the case (this also means we’ll even be able to migrate the existing cases without having to migrate any data).

Make sure Multiple elements is turned off in the Specific attributes section. You can choose whether you want a border around the subform or not. Turn it off to be as similar to we had before adding the subform.

Because we entered a label name for the subform (although optional), we might decide to remove the label from the attachment widget to avoid duplicate information on the form. To do so, click the subform-name-link at the bottom of the subform widget to open it directly in the form editor and make the change.

Redeploy, migrate and test again with the subform

Go to the Tutorial App, deploy it again, navigate to the Travel Request case model and migrate the existing cases. Switch to the user dashboard and navigate to one of your previously created cases and you should see pretty much the same as before, but now achieved using a subform:

case testing 03
Add the subform to the task forms as well

Now we have a reuseable subform, let’s add it to both user task forms as well, so we have all the useful information available in the different contexts of the process.

Open both task forms in the form designer. There are different ways to do that:

  • Go back to the process model, open it in the process modeler, select the user task, open the attributes and click on the form reference in the Specific Attributes section. Then select Reference and click the OK button to open the form designer for the task form.

  • Go to the modeler dashboard and select the form in the My Form Models widget.

  • Navigate to the Tutorial App and choose the appropriate forms from there.

Once opened in the form designer, drag & drop a Single-type subform to the bottom of the form and label it Attachments. As we did before with the case form, click the + button at the bottom of the subform and select the Attachment Section Sub Form.

Turn off the border and make sure multiple elements are turned off. Now the binding will need to be slightly different than we used in the case form. Remember that we bound the subform to {{$this}}, meaning its data is directly stored within the case itself. In order to show the same data in the context of the task, we now need to bind it to the case, which can be done using {{root}}.

So, for the travel management task form, it should look like this:

form design 04

For the second user task form, you can simply copy and paste the subform widget from the first task form (not from the case form though, as the binding is different there).

Redeploy, migrate and test again with the subform in the tasks

Go to the Tutorial App, deploy it again, navigate to the Travel Request case model and migrate the existing cases. Switch to the user dashboard and navigate to one of your previously created cases (one that already has at least one attachment).

Now let’s see how we can start the process whenever we want, in an ad-hoc way. Remember that the first time the process was started automatically when we created the case. Now let’s see how this can be done manually.

Click the Start Process action in the right hand action menu and select Travel Request Management Process, then click Start. This will start a new instance of the process in the same case. This is how processes can be manually started as an alternative to automatically starting them during the creation of a case.

As before, the children view of the case shows one task because we started the process again within the case. Navigate to the task and check, whether you see the attachments there too:

case testing 04

4.5. Ad-hoc tasks and process improvements

In this chapter we will add a requestor <–> agent feedback loop to the process. If the travel agent needs more information, clarification, decisions about which flight or hotel to choose from and the like, we will enable that by adding a feedback-loop to the process.

But first, we’ll find out how this can be done using ad-hoc tasks.

4.5.1. Getting familiar with ad-hoc tasks

Assuming the problem as described above, there are several options for how the travel agent could solve it:

  • Use the phone, contact the requestor and clarify the open questions

  • Send an email to the requestor and clarify anything

  • Create an ad-hoc task within the case, assign it to the requestor and clarify details

  • Add a feedback-loop to the process for better tracking and audit

The first two options are probably the way we solve many unexpected business situations, but they are not integrated in a way that any new information is automatically available within the case. In a large organization there might be a team of travel agents working together and they would need to share that information somehow, so everyone can always be up to date.

As a first step, let’s create an appropriate ad-hoc task model to support this directly within the case. In parallel to the running process, a user can create ad-hoc tasks at anytime if enabled in the case model (which is the default).

4.5.2. Create ad-hoc task init form

Ad-hoc tasks can be built with forms in exactly the same way we’ve created forms so far. This time, we’re going to create a different init-form. Go to the Tutorial App, click Create, select Create Form Model and name it Ad-hoc Feedback Init Task Form. Click Create and Design to open the new form in the form designer.

This time we will also learn the difference between an init-form and a work-form. So far we’ve used the same form in the case for both. Additionally, we will use a subform to show the data of the case within the case form itself, a nice way to ensure all the data for a case is shown in another context.

First of all, we want to be able to set a subject for the ad-hoc task (like the subject you would put in an email). We can use one of the predefined widgets, so drag the Name widget from the Predefined bindings section of the shape palette onto the form and rename the label to Task subject.

For the description of the task (the request for additional information, review or whatever) we will also use a predefined widget, so drag & drop the Description widget onto the form and rename its label to Task description. Click the star button of the description widget to make it required, to force the user to specify a task description.

Remember, we’re still designing the init-form of the ad-hoc task, which is only used during the creation of the new task, so we also want to be able to select the assignee for the ad-hoc task. There’s a predefined widget to do exactly that, so drag & drop the Assignee selection widget from the Predefined selections section onto the form and rename its label to Assignee for the task. Let’s also add a due-date for the task (another default field as well), so drag the Due date widget from the Predefined bindings section and drop it onto the assignee field in the right part, splitting the row into two parts, and rename its label to Task due date.

Now the form should look like this:

form design 01

4.5.3. Create ad-hoc task work form

As mentioned before, this time we want different forms for initializing (creating) a new ad-hoc task and for working on it, so go back to the Tutorial App, select the Ad-hoc Feedback Init Task Form and click the Duplicate action, as we want to create a copy of the form so we only have to change what’s different between the init-form and work-form. In the duplicate name field, write Ad-hoc Feedback Work Task Form and click Ok to copy it. Go back to the Tutorial App (link in the header) and select that newly created duplicate form, then click Design to open it in the form designer.

Now we only have to make a few modifications to suit our needs. It doesn’t make sense to allow the subject and description to be changed, so let’s make them read-only by setting their attributes Editable to false. Next, remove the assignee selection and task due date, as we don’t want to be able to modify them.

As the requestor of the initial case, we want to be able to modify the case data itself, so let’s add that case information by using a subform. Previously we saw how data from the case can be shown in a task form by using an output textarea widget and then manually add all necessary data with appropriate expressions to it. This is one option, now let’s see a more generic way to include the case data in the task form by adding it as a read-only subform, using the very same form as we used for the case itself. This way, we make sure that whenever we add new stuff to the case form, it will automatically show up in this task form as well, because it’s a subform. Additionally, we want to be able to choose to show and hide the case information through a checkbox.

Drag & drop a Checkbox widget to the form, label it Show case information and bind it to {{showCaseInfo}}. Select the Default value attribute and set it to true as the default (so the case info is visible by default).

Now drag & drop a Single-type subform below the checkbox and label it Case information. Click the + button and select Reference and then Travel Request Form, our primary case form. Next, we need the binding for the subform. Remember, we want to show the case information in there, so we use {{root}} for the binding, which will map to the current case within which the ad-hoc task has been created. Last thing to do is to set the Visible (RT) attribute to the same binding as the checkbox {{showCaseInfo}} to make the visibility flag of the subform dependent of the state of the checkbox. Visible (RT) means visible runtime and lets you define an expression that must resolve to either true or false, then the visibility is dynamic based on the expression’s value. Also note that expressions are evaluated in real-time directly within the form engine of edoras one, whenever the data that the expression is based on changes. In our case with the checkbox value, the visibility flag is automatically adjusted appropriately. Make sure we have Show border set to true and Multiple elements to false, as there is exactly one case instance to be shown and we want it in a border to visually indicate its data is coming from somewhere else.

The interesting part now is that we can even modify data in one single form for both the task and the case instance simultaneously, so the user doesn’t even need to be aware of context that data is coming from or being saved.

The ad-hoc task work form now should look similar to this (the attribute section is the one from the selected subform):

form design 02

Now save the form and go back to the Tutorial App for our next step.

4.5.4. Create ad-hoc task model

Go to the Tutorial App and click Create and choose Create Task Model. Set the name to Travel Feedback Task.

Now select the appropriate init-form and work-form in the Init Form and Work Form selections of the task model and complete creation of the model by clicking Create.

task model 01

4.5.5. Deploy App and test ad-hoc task

Navigate back to the Tutorial App and deploy it again, which will make our new ad-hoc task available for use.

Switch to the user dashboard and select one of your previously created travel request cases. Now click Create and choose Create Task. If you do that in the context of a currently selected case, it should be automatically preselected in the Parent Case selection. Now choose the Travel Feedback Task Template, fill out a task subject and description, choose yourself as the assignee (so you don’t have to logout and login to complete it) and optionally also choose a due-date.

prc testing 01

Click Create to create the ad-hoc task. If you check Create another before hitting Create, the new task will be created and you will return back to the same init-form so you can quickly create another one.

Going to the newly created ad-hoc task there are several things you should note. First of all, you should be able to show and hide the case information by simply clicking the Show case information checkbox. Also note that the information in there reflects the case information and you are able to modify it directly while in the task. You can test that by changing some case information in there, clicking Save (not Complete yet) and navigating to the case. The data in the case itself should have been updated accordingly.

To complete the task, simply click Complete and it will be finished. By default, completed tasks are not shown in the children list of a case. If you would like to see them, go to the children list of the case and select status All within the search box. Now you will see all work items of the case, even completed ones.

4.5.6. Add feedback loop to the process

As an alternative to the ad-hoc task approach we just tried, we now want to incorporate the agent <→ requestor feedback loop directly into the management process.

And here is how we can do it:

  • Add a next step selector in the management task form, to let the travel agent choose between different options (need more information, travel organized, and so on)

  • Add a gateway in the process after the user task to take the appropriate sequence flow based on the selected next step

  • Add feedback-task as a new path in the process that loops back to the management task

  • In the review task at the end of the project, add a new checkbox to the form to give the requestor the option to loop back to the agent if he is not happy with how the travel has been organized

Add next step selection option to management task

Navigate to our travel request management process and open it using the Design action (if the process modeler is not already open).

Open the process model in the process modeler, select the Manage Travel Request user task, open the attributes and click on the form reference in the Specific Attributes section. Then select Reference and click the OK button to open the form designer for the task form.

In order to separate the previous form elements from the next one, drag a new Horizontal line from the Component section and drop it right after the Travel notes field.

Drag a Static select widget from the Component section onto the form between the travel notes and the attachment subform, and drop it inbetween. Label it Select next step and bind it to {{parent.nextStep}}. Why did we use the parent prefix? Note that our form is used within a user task created as part of a process. If we want to be able to use the data in the nextStep variable in the process context, we must not store the data in the local task context, but rather in the process context (parent-prefix) or even the case context (root-prefix). As this information is only needed during the lifecycle of the process, we’ll to store it in the parent process and not in the root case context.

Let’s make the selection mandatory by clicking the red star or setting the attribute Required to true. Now open the Options attribute dialog by clicking its attribute value, then enter two options in there:

  • Name: Need more information from requestor, Value: moreInfo

  • Name: Finish organization, travel has been fully organized, Value: finish

The name column defines the label used for that option, while the value column is used to define the variable to store the selection.

If we choose the first option, we want to show a new note field where the agent can describe what kind of information is needed from the requestor. So let’s drag & drop a Rich textarea from the Components section of the shape palette to below the selection widget on the form and label it Information request. Make that field required by clicking the red star, but note that the required-validation will only take place if the field is shown; if it stays hidden, there is obviously nothing to be entered and the validation takes this into account. Bind the field to {{root.infoRequest}}, as we want to keep that information, even after the process has been ended. We’ll store it within the case context and that’s why we’ve used the root prefix instead of parent that we used with the nextStep variable.

As we are already thinking ahead to when the feedback loop returns from the requestor back to the agent, we want to show the information the requestor entered, so let’s add an output textarea showing that information. Drag & drop a new Output textarea below the information request field and leave the label empty. Double-click it and add the following content to it:

form design 03

We only want to show the information request field if the next step selected is moreInfo, so select the Information request field and enter {{parent.nextStep=='moreInfo'}} in the Visible (RT) attribute, making it visible only if we select Need more info… in the next step selection.

The output text area should only be visible if it has content, so let’s enter {{root.infoRequestAnswer}} in the Visible (RT) attribute, making it visible only if the variable root.infoRequestAnswer has content.

The form should now look like this:

form design 04
Add feedback loop to the process model

We now have to add the feedback loop to the process model, so let’s open it in the process designer.

Still remember the spacing tool? We can make use of it now to add some extra space after the management task in order to add the gateway after the user task.

prc design 01

Now drag a new Exclusive gateway from the Execution section of the shape palette and drag it over to the sequence flow after the user task. As soon as the sequence flow becomes green we can drop it, as the modeler has recognized that we want to drop it inbetween the two user tasks.

prc design 02

As you can see, the modeler automatically splits the sequence flow into two and adds the gateway inbetween.

Select the gateway element (if not already selected) and drag & drop the small user task icon to add another outgoing sequence flow with a user task after the gateway:

prc design 03

Name the new user task Answer Info Request and align it right above the gateway and on the same horizontal level as the other requestor task:

prc design 04

Select the new user task and drag the arrow icon next to it onto the Manage Travel Request user task until it turns green, then drop it to connect the two tasks with a sequence flow.

prc design 05

We’ve now successfully modeled the feedback loop after the gateway. Our next step is to tell the engine which flow to use from the gateway by specifying conditions on all outgoing sequence flows.

Select the sequence flow between the gateway and the Answer Info Request user task, then click on the Condition expression attribute and enter #{nextStep=='moreInfo'} as the expression. We’ll explain the different expression syntax in just a minute, but first let’s add a label to the sequence flow. This can be done by clicking the Name attribute and entering the name, or simply by double-clicking the sequence flow directly in the process canvas. Let’s name it more info.

Now select the sequence flow between the gateway and the Review Travel Bookings user task and enter #{nextStep=='finish'} as the Condition expression attribute and name it finish.

It’s good practice to add a label to a gateway element, so double-click the gateway and type Decision?

prc design 06
Getting familiar with frontend and backend expressions

You probably noticed that there is a difference in the syntax for frontend expressions used within forms and backend expressions as we’ve just used in the process model. The difference is down to where they are being evaluated: directly within the browser (frontend / forms), or on the server (backend, everywhere else, such as process, email templates, document templates, and so on). Frontend expressions are limited to whatever the browser and form engine know, in contrast to the expressions on the server side, which could contain your own service calls, functions, any navigation through the work item network and much more. That’s why we use different syntaxes, to make the difference in their evaluation very prominent to the modeler.

But now, back to our sequence flow condition #{nextStep=='moreInfo'}. Why didn’t we use parent.nextStep as we did in the form? It’s very important to always remember in which context an expression will be evaluated. In the user task form we are in the context of a task work item, which is a child element of the process work item. The expression on the sequence flow, however, is evaluated in the context of the process itself and therefore we don’t need the parent prefix that we needed in the task context.

Create user task form for the answer task

We now have to create the user task form for the new task added to the process. If you remember, you can simply click the task ref link icon, select New and it will create a new form, attach it to the user task and open it up within the form designer.

Let’s add an Output textarea to the form so we can add the necessary information in there. Leave the label empty, double-click the widget and add the following content to it:

form design 05

Note that we can include expressions anywhere within the content as we like.

Below the output field, add a new Rich textarea widget, label it Your answer and bind it to {{root.infoRequestAnswer}} (the same expression we already used in the management task form). Additionally, make it required by clicking the red star icon.

The form should now look like this:

form design 06

Save the form, name it Answer Info Request Task Form and close it in order to return back to the process design.

Save the process model as well, with the new feedback loop, in order to test it.

4.5.7. Redeploy and test process with feedback loop

Go back to the Tutorial App and redeploy it. Now switch to the user dashboard and create a new case with our Travel Request template.

Did you notice the new attachment widget was also visible in the init-form? If you don’t want to be able to upload attachments while starting the travel request, just add {{root.id}} within the Visible (RT) attribute of the subform widget holding the attachment subform in the Travel Request Form. It will not show up as long as the case hasn’t been initialized, because the root.id variable is not available.

If you navigate to the Manage travel request task within the children view of the case you will see the updated management task form. Select Need more information… from the Next step selection and the new Information request field should appear, where you can enter the information you need from the requestor:

prc testing 02

Did you notice the rich text capabilities within the text editor? When selecting part of the text, a toolbox appears that allows you to change the formatting:

prc testing 03

If you now click Complete, the next task will be the answer info request task, where you can provide an answer, after which the process will go back to the management task. You can use this feedback loop as many times as you want. As soon as you choose Finish…, the process goes to the review task and will finish.

Did you notice the pre-selected next step combobox when returning back to the management user task? Remember that we bound the selection of this widget to parent.nextStep, and as the selection is stored in the process it will be remembered the next time that information is used again. As we don’t wont that behavior, let’s go back to the process and add a service task to reset its value before we return to the management task again.

Add service task to initialize variables to the process

Make some more space before the Manage Travel Request user task in order to add a service task there. Afterwards drag a new Initialize variables task from the Service tasks section onto the sequence flow between the start event and the user task, drop it and name it Reset next step selection.

Move the sequence flow connection that’s between the answer and the manage task so it points to the new reset service task by selecting the connection and dragging the green point at the end of the flow arrow, dropping it onto the reset service task. If you want to rearrange the sequence flows, there are several handles available to choose from. There is a red point on every bend of the sequence flow to allow you to move the bend location. Adding a new bend is easy too, simply click anywhere on the sequence flow and drag the red point that appears. You can move a sequence flow in parallel by moving the red rectangle that appears in the middle of the flow.

Your process model should now look like:

prc design 07

Of course, we still need to tell the engine which variables to initialize within the reset service task we just added. Select the service task and click the Init variables attribute, in the dialog that appears, enter the variables we want to initialize or reset for our case.

The first column can be left empty as our nextStep variable is in the process scope. Write nextStep in the variable name column and leave the last column empty as well as we simply want to clear the previous selection value. If you also want to clear the previously entered information request text, add an extra row to the dialog which should then look like the following:

prc design 08

Close the dialog and set the attribute Overwrite if existing to true (checked and green). This is necessary, as we explicitly want the variables to be overwritten if they already exist. If you left that option as false it would only initialize variables that do not exist yet, leaving any existing variable values untouched.

Save the process model and go back to the Tutorial App so you can redeploy it and test the updated behavior.

4.6. Model responsibilities / assignees

4.6.1. Getting familiar with responsibilities and sharing

Before we include the responsibilities (assignees) in our process, let’s have a look at the permission concepts behind edoras one. Every work item (a case, task, document, and so on) can have the following information concerning responsibilities and sharing:

Owner

By default, the creator of a new work item becomes its owner, although being the owner does not mean being responsible for working on it, rather more in a sense of being kept in the loop and always informed about what’s happening with that work item.

Assignee

The assignee is the person responsible for working and completing a work item. If manually set, the assignee is typically chosen by the owner of a work item.

Candidate groups

Setting one or more candidate groups makes the work item available to all users that are a member of any of the candidate groups. Assume you have a group named "Support" and use it as the candidate group for a support case. This makes all users who are members of the Support group potential assignees for the support case, and all of these members will have access to the work item.

Candidate users

The candidate users work the same way as the candidate groups, but instead of adding a group of users you can directly add selected users to be candidate users. They too will have access to the work item.

In order to have access to a work item you must either be the owner or the assignee of it, or be a member of one of the candidate groups, alternatively, you must have been added explicitly as a candidate user.

4.6.2. Getting familiar with account, group and user management

If we want to use groups and users in our App, it is important to also understand how they are managed in edoras one. Go to the Administrator dashboard by selecting it from the Dashboard menu (you need to have administrator permission in order to have access to this dashboard, of course). You will now see an overview of your accounts, groups and users in your tenant.

Accounts

Accounts are used to divide your tenants into organizational units, locations or whatever you want, but usually business units. Groups and users are then created within an account. Currently, the account does not have any impact on the visibility of work items. As we learned in the previous chapter, only groups and users directly control the visibility of work items.
What we can do is apply visual styling with CSS customizations for different accounts. The way to customise an account is by setting the field "CSS class" in the form for an account:

admin 01

Technically, this CSS class will be added to the same div that contains the class .edoras-one.
In custom.css there is a commented line to import the file accounts.css. This file contains an example of how to apply your custom styles. To use account CSS customizations, uncomment this line and replace account-example with the name of the CSS classes defined on your account. You can do this for several accounts by repeating the content and changing the class name. Elements that you do not want to customise can be safely removed from the accounts.css.

For "Cloud" solutions, there are some predefined account CSS classes:

Table 70. Account predefined "Cloud" css classes and colours
CSS Class Main Colour Main Dark Colour

account-brown

account-green

account-teal

account-blue

account-purple

account-pink

(empty/default)

To turn off UI customisation for the Account and use default colours, simply remove your class from the account form, leaving only the "account-" prefix.

To create a new Account, click Create or hit C and choose Create Account from the dialog, fill out the necessary information and create it by clicking Create.

Groups

Groups are used to specify a set of users. The meaning of a Group however, is entirely up to you. It could represent a group of people within your organization (for example, the support team, human resources or sales) or it could be used to represent a role (for example, approver, travel agent). By adding a group to a user, that user becomes a member of the group or role, and as a result will have access to any work item that has this group as a candidate group.
To create a new Group, click Create or hit C and choose Create Group from the dialog, fill out the necessary information and create it by clicking Create.

Users

Users allow people log in to edoras one and participate in the work. All users' settings are managed within their own user profile. A user’s profile can only be edited by the user or any administrator.
To create a new User, click Create or hit C and choose Create User from the dialog, fill out the necessary information and create it by clicking Create. It’s good practice to use their email address as the login name, although this is not mandatory.

Good Practice

Although accounts are not directly used for the visibility of work items, it’s good practice to create a Group for each Account with exactly the same name and use it to share work items with all users in that account. Of course, the users need to be added as members of that group as well.

4.6.3. Adding a travel agent group and requestor to task responsibilities

As we learned earlier, participants, groups and roles are modeled through pools and lanes in BPMN 2.
We currently have two different participants in our process: the requestor of the travel request, and the travel agent managing the request.

Creating a group for the travel agents

As we want to be able to assign tasks to the travel agent team, let’s first create a new group for it. Go to the Administrator Dashboard and click Create or hit C and choose Create Group from the dialog. Choose the primary account to which the group should be added (not the admin account) and set the group’s name to Travel Agents, and optionally add a description for that group, then hit Create in order to create our new group:

admin 02

Add yourself to the newly created group to make it easier to test the modified process later (so you don’t have to keep logging out and logging in to see and complete the travel agents tasks). In order to do that, choose User profile in the upper right corner menu, choose Manage Groups and select the new Travel Agents group, then hit Ok. You’ve just made yourself a member of the new group!

admin 03
Modeling the initial requestor’s responsibilities

The initiator of the travel request will be responsible for answering any open questions and eventually reviewing the travel bookings. In order to model that, navigate to our travel request management process and open it using the Design action (if the process modeler is not already open). Select the Answer Info Request user task and go to the Assignee (RT) property. RT means Runtime and allows us to use an expression to determine the assignee at runtime rather than a fixed user at design time. As we already know, the owner of a work item is set to the user that created it by default, so we simply can use an expression that references the owner of our root case to set the assignee of this task. Set the expression to #{root.ownerId} to automatically assign this user task to the same user as the owner of our travel request case. Remember that this is a backend expression, so we need #{} to tell the process engine what to do.

Your process should now look like this:

assignee 01

Select the Review Travel Bookings user task and follow the same steps, setting the Assignee (RT) property to #{root.ownerId}.

Modeling the travel agents responsibilities

For the travel agents tasks we will use the candidate group feature. This means the task will not be assigned to a single user directly, but rather to a group of users. This time, we leave the Assignee (RT) property empty but will set the Candidate groups property instead.
Select the Manage Travel Request user task and select Travel Agents from the Candidate groups property selection combobox:

assignee 02

If the Travel Agents group doesn’t appear, you might need to reload the process diagram first (only necessary if you created the new group after you opened the process diagram).

Now save the process model and go back to the tutorial App in order to redeploy it. If you create a new travel request, you should now see that the assignee for the requestor tasks is automatically set to the same user that started the request, and the management task is assigned to the Travel Agents group, so it will appear in all members' task list.

Use current user for future management tasks

In our previous step, we assigned the travel management task to a group rather than direct user assignment. This way, there are potentially several users that could claim the management task and organize the travel request. If there is no direct assignee set, the task will appear in the personal task lists of all users who are members of the group. This has implications later on, as we have a feedback-loop built into the travel request management process. If a travel agent needs some more information and the process goes back to the management task, ideally, we would like it to be automatically assigned to the same travel agent and not the whole travel agent group.
To do that, we’ll need to store the travel agent who completed the management task within the process instance, so we can use them again as the assignee for the management task.

Open the travel request management process (if not yet open) and make some space using the spacing tool after the Manage Travel Request user task. Drag & drop a new Initialize variables service task from the shape palette and drop it onto the sequence flow after the Manage Travel Request user task, naming it Store travel agent user. Whenever the previous user task is completed, this service task is executed and will store the current user ID to a process variable.

In the property section, select Overwrite if existing (true, green mark), so the variable will always be overwritten with the most recent travel agent. Now click the Init variables property and fill in the following information:

assignee 03

Set the first cell to root as we want to store the travel agent within the case context. We’ll use travelAgent as the variable name to store the current user ID. For the value, we can use the #{currentUserId} expression that always returns the ID of the current user, which in our case will be the travel manager who just completed the management task.

Our process should now look like this:

assignee 04

In order to use this new variable, select the Manage Travel Request user task and set #{root.travelAgent} as the 'Assignee (RT)' property, but still leave the candidate group property selected with our Travel Agents group:

assignee 05

What will happen now? Whenever the management task is completed, the current user ID is saved in a case variable named travelAgent, which will then used as the assignee expression if the management task is ever created again. This will result in an automatic assignment to the same travel agent handling the current travel request.

However, we still have a problem: the travelAgent variable is set the first time AFTER the management task, but the expression is used BEFORE that, so we need to add another Initialize variables task at the very beginning of the process to initialize this new variable in the case.
In order to do that, make some space just before the Reset next step selection task and drop a new Initialize variables task onto the sequence flow and name it Initialize travel agent variable. Select the Init variables property and enter the following information:

assignee 06

This time, we leave the value empty as we just want to initialize the variable; we don’t yet know the travel agent at this point of the process.

Now your process should look like this:

assignee 07

Save the process model and go back to the tutorial App in order to redeploy it. If you create a new travel request, use at least one feedback loop to create more than one management user task. You will see that the first one is not assigned to a particular user, but every further management task is assigned to the same user that completed the previous one.

4.7. Add approvers to the process

In this chapter we want to add optional approvers to the travel request. Let’s assume the travel agent has some regulations to follow, such as if the travel exceeds a certain cost, or if it includes traveling by airplane there must be an approval from one or more approvers.
To keep things easy, we’ll simply add a new option to the Select next step combobox in the Manage Travel Request user task to go into an approval phase of the travel request, so it’s up to the travel agent to decide whether an approval is necessary or not.
As a first step, we’ll just add one single approver and later extend it with as many as necessary. This way, we’ll learn how to use multi-subforms in combination with a multi-instance task to loop over the selected approvers.

4.7.1. Extend travel management task form for optional approval

First, we need to extend the travel management task form by adding a new possible next step.
Open the Travel Request Management process and click the + sign within the Manage Travel Request user task in order to open the task form.

Select the Select next step combobox and click the Options property. Now add a new option by clicking the Add button. Add the new approval option like the following:

approval 01

You can move the order of the new entry by selecting its row and clicking the up-arrow.

If the user selects this new option, we want to display a text field for them to enter any additional approval notes and, of course, select the approving user.
Drag & drop a new Rich textarea just below the Information request text area, name it Approval notes and bind it to {{root.approvalNotes}}. We only want to show this new field whenever the new step is selected, so set the Visible (RT) property to {{parent.nextStep=='approval'}}.

From the Predefined selections section of the shape palette, choose the User selection widget just below the Approval notes text area and name it Select approver. Change the binding expression to {{root.approver}}, make it required and set the Visible (RT) property to {{parent.nextStep=='approval'}} as well.

Your task form should now look like this:

approval 02

Now save the task form and switch back to the process in order to extend it with this new approval functionality.

4.7.2. Add approval step to the process

As we will be adding a new role to the process, let’s add a new lane to represent it. Drag & drop a Lane below the Travel Agent lane onto the existing process pool and name it Approver:

approval 03

From the existing gateway, drag a new user task out of it, drop it within the newly added Approver lane and name it Approve Travel Request.
Now select the sequence flow between the gateway and the newly added user task and name it approval. We also need to tell the process engine when to actually use this flow, so set the Condition expression to #{nextStep=='approval'}.

approval 04

Drag a new sequence flow out of the new approval task and connect it to the existing Reset next step selection task.
There are now three incoming sequence flows to that task and it’s good practice to use a joining gateway before that task for better visibility of the flow, although it isn’t necessary by the BPMN 2 standard.
To be able to do that, make some more space (using the spacing tool, if you remember) before the Reset next step selection task and drop a new Exclusive gateway onto the sequence flow. Then you have to re-connect the existing sequence flow leading into the Reset next step selection task to the newly added gateway. You can do so by hovering over the sequence flow you want to re-connect until the green circle handles become visible, then drag & drop it using those green handles to the new gateway.

Your process should now look like this:

approval 05

Next, we need to set the assignee for the approval task to be the person we selected in the management task. Select the Approve Travel Request user task and set the Assignee (RT) property to #{root.approver}.

The only remaining missing thing is the approval task form, so let’s create one. Select the Approve Travel Request user task, open the attributes and click on the form reference in the Specific Attributes section. Then select New and click the OK button to create a new task form.

Drag & drop a new Output textarea to the form in order to add some information for this approval task. Double-click it to open the editor for its content and add the following:

approval 06

Notice the expressions we used in the output widget. First of all, they are frontend expressions using double-curly braces, as they will be rendered in the form engine running on the frontend. {{root.name}} actually renders the travel requests name (case name or root name). {{root.approvalNotes}} is the notes field we added within the management task form to allow the travel agent to add special notes for the approver. Finally, we have {{root.travelAgent}}, which will be automatically set after the management task has been completed by the travel agent, using a Initialize variable task.

When it comes to the decision widget for the approver, we basically have two choices: using a checkbox (for instance, if we have yes / no options) or using a selection combobox, the latter being a little bit more verbose and, of course, can have more than two options.

Drag & drop a Static select widget below the output text area and name it Please make your decision. Then double-click the widget and enter {{root.approvalDecision}} for the data binding (or enter it in the value property). Also, make the field required (by either clicking the red small star of the widget or checking the Required property).

Now click the Options property and enter the following values to the dialog:

approval 07

Finally, let’s add a Rich textarea, name it Decision notes and set the data binding to {{root.approvalDecisionNotes}} to let the approver add any special notes about the decision.

The form should now look like this:

approval 08

Save the form, name it Travel Request Approval Task Form and switch back to the process model and save it too.

What did we do? We added a new option to the Manage Travel Request task for getting approval for the travel request, added the approval user task and routed the process back to the travel agent, who then needs to decide whether to further organize the travel or stop it (if approval wasn’t given). How does the travel agent know about the decision made by the approver? We can add this information back to the management task, so they have everything there.

Let’s go back to the process, select the Manage Travel Request user task, open the attributes and click on the form reference in the Specific Attributes section. Then select Reference and click the OK button to open the task form. You can also switch to the task form, if it is still open.
There are several options for how we could add this information. As it is read-only information, we can display it using another output widget that we only want to show if there is an approval already done.
Add a new Output textarea and drop it below the Travel notes rich textarea, double-click it and set it to this content:

approval 09

We only want to show this widget if the approval has already been given. We can do so by using the Visible (RT) property we’ve used before. Select the output widget and enter {{root.approvalDecision}} in the Visible (RT) property. This way, the widget will only be shown if the approval variable is set, which can only be the case after the approval task has completed.

Save the form and go back to the Tutorial App to redeploy it. Start a new travel request, select the Need approval option, select an approver (yourself, to avoid logging out and logging in again) and you should end up at our new approval task.

approval 10

As we look at the approval task now, we have some room for improvement. First of all, do you see how the expression {{root.travelAgent}} is rendered? It’s some cryptic user ID rather than the users name. The backend could support something like #{root.travelAgent.name} in order to access the name of that user, but the frontend doesn’t currently provide that.
So, what options do we have? Remember the Initialize variable service task we used to store the travel agent ID after the Manage Travel Request user task? Let’s add another variable to hold the travel agents name.
Open the Travel Request Management process and select the Store travel agent user task. Click the Init variables property and add the following variable initialization:

approval 11

Save the process and open the Travel Request Approval Task (or switch to it, if it’s still open). Double-click the output widget at the top of the form and replace {{root.travelAgent}} with {{root.travelAgentName}}, so it uses the user’s name rather than their ID.

Save the form, go back to the Tutorial App, redeploy it and test the process again.

To further improve the process, you can add the approvers name and ID as a variable and render it in the output widget in the management task, to let the travel agent know which approver finally approved or declined the travel request. If you remember how we saved the travel agents ID and name and used it in the approval output widget, hopefully, you should be able to do that on your own now.

If not, here are the basic steps:

  • Add a new Initialize variables task after the Approve Travel Request user task and add root | approverName | #{currentUserId.name} to it

  • In the Manage Travel Request user task, add this information to the output widget (something like The travel request has been {{root.approvalDecision}} by {{root.approverName}}…​).

4.8. Sending emails from within the process

In this chapter we’re going to learn how to create and use email templates within a process. The basic idea is to send out an email to the requestor and travel manager of a new travel request if it is declined by the approver.
Of course, this might not be the best way to end the process after the travel was declined, but it gives us the opportunity to use email templates in our existing example.

4.8.1. Create email template

We want to create the email template as the first step, so go to the Tutorial App and hit C or click the Create button and choose Create Mail Model and name it Travel Request Declined Email Template. You can hit Create now and fill in the rest of the template later, or complete the email template within the Create Mail Model form.

Now create the template so it looks like this:

email template 01

4.8.2. Add gateway for approval decision

As we only want to send the email if the travel request was declined, we need to add a new gateway after the approval user task. Open the Travel Request Management Process and make some space at the bottom of the lane in order to add a new gateway. Reroute the existing sequence flow so the process looks similar to this:

email template 02

After adding the new elements and rerouting the sequence flows accordingly, we need to add the conditions for the new sequence flows leaving our new gateway to tell the engine which flow to take.
Select the sequence flow with the label yes and set the property Condition expression to #{root.approvalDecision=='approved'} and for the no labeled flow use the expression #{root.approvalDecision=='declined'}. After this, whenever a travel request is declined, the process will end directly without any notification.

4.8.3. Send email if approval was declined

Abruptly ending the travel request process just because a request is not approved isn’t the most friendly solution, so we want to integrate our email template and send out a notification email once the request is declined.
Go to the Travel Request Management Process and make some space between the gateway and the end event, to give us room for a new email task. Now drag & drop a new Send mail service task onto the no sequence flow and name it Send decline notification email.

Select the Travel Request Declined Email Template as the Mail model for the Send mail service task, so this will be used when creating the email subject and body to be sent. We want to send the email to our initial requestor and CC to the travel agent. To do that, we’ll use #{root.ownerId} for the Mail recipient property and #{root.travelAgent} for the Mail CC one.
Your process should now look like the following:

email template 03
As an email recipient you can either specify a fixed email address, like john.doe@mycorp.com, or you can specify an expression that evaluates as an email address, like #{root.useEmail} (where useEmail might be a text field where an email address has already been provided) or you can specify an expression that evaluates as an edoras one user. In the latter case, the email address of that edoras one user is used to send the email to. For our travel request, #{root.ownerId} will resolve to the initial requestor and #{root.travelAgent} will resolve to the last travel agent managing the travel request.

When you are testing the email functionality, please note that it may take several minutes before you receive the email.

4.9. Create document models

In this chapter we will learn how to create document models, which can be used in a variety of ways, as we’ll see.
First of all, documents can either be created manually, in the same way that ad-hoc tasks are created, or they can be created as part of a process task.

Documents can have properties (metadata), designed using init-forms and work-forms, exactly as we did with task models.

4.9.1. Create document properties form

A document might have some properties (metadata) stored as variables that can be used to classify it or allow it to be found later. This is done using a form in just the same way as for cases or tasks, to create a document or to manage the metadata of a document.

Go to the Tutorial App and hit C or click Create and select Create Form Model, name it Travel Request Document Form and click Create and design. Drag & drop the Name and Description fields onto the canvas. Let’s assume we want to select an assignee for the document, so drag & drop the Assignee selection widget below the description. To share the document with other groups, we could drag & drop the Share with groups selection widget as well.

If you want to have more metadata for your document, just add more fields to the form; you can design the document form in the same way as for tasks or cases.

The document form should now look like this:

document model 01

If we want to be able to upload content during the creation of the document (init-form), we can add an upload-widget. Drag & drop the Upload widget to the top of the form (before the name field) and name it Upload document. This is a special widget that’s only used for uploading the content of a work item (in this case, a document), so we don’t need any special data binding.

We only want the upload widget, the assignee selection and the share with group field to be visible during the initialization of the document, but we’d like the form to be used as both init-form and work-form. There is a way to achieve this using the Visible (RT) property to show or hide a widget, depending on whether the form is used as an init-form or as a work-form.

Use the expression {{!root.id}} for the Visible (RT) property to show a widget only when the form is used as an init-form. If you want to hide a widget when the form is used as an init-form, use the expression {{root.id}} for the Visible (RT) property. What does {{root.id}} mean? Well, it references the ID of the root work item, typically a case, and when we use a form as the init-form, we don’t have a case yet, so there is no ID. We can use this expression to show or hide the widget based on the existence or not of the root ID.

With that knowledge, let’s add {{!root.id}} as the Visible (RT) property for the Upload widget, as well as for the Assignee and the Share with groups widgets.

The document form should now look like this:

document model 02

Save the form and go back to the tutorial app.

4.9.2. Document models with content being uploaded

Using the document form we just created, we want to create a new document model within our Tutorial App, so go back to the tutorial app and hit C or click the Create button and select Create Document Model, name it Travel Request Document and select Travel Request Document Form for both the Init form and Work form. Now create it, navigate back to the Tutorial App and deploy it, so we can test our new document model.

Upload new document to a case

Go back to the user dashboard and open one of your previous travel cases. The same way we created an ad-hoc task, we can create or upload a new document in the case by clicking the Create button and select Create document. In the Template selection, choose Travel Request Document and click the Add... button to select a document to upload. It should automatically set the name of your selected document to the form we created, but can you change it if you want.
Also, if you want, you can select an assignee for the document, as well as share it with some groups.

Creating a new document should look similar to this:

document model 03

After creating it, you will notice the assignee, share with groups and upload widget are no longer visible. As you’ll remember, we used the Visible (RT) flag to hide it for the work-form but show it within the init-form.

Getting familiar with the document views and actions
document model 04

Having created our new document, let’s look at the different views and actions a document provides.
The first view (eye-icon) is a preview of the document, which is currently provided for images, PDFs, OpenOffice and Microsoft Office documents (Word, Excel and Powerpoint). The second view is the work form for the document, similar to the forms for any work item (such as cases or tasks). Then we have the comment view where you can see and add comments for the work item. The last two views are for developers or modelers, allowing you to see all the data of the work item in a generic form or represented in JSON.

Here is the list of actions:

  • Assign lets you change the owner and assignee of the work item (document, in this case)

  • Share lets you share the work item with groups of users

  • Move to move the current work item to another case

  • Update Placeholders will update the content of placeholders within a document, if it was created from a template (more on this later)

  • Upload Document allows you to upload, optionally overwriting the current content with a new document.

  • Download allows you to download the content of the document to your local machine

  • Archive will close and archive the document

To manage the actions available in the document model form, select the document model in the Tutorial App, click Edit Entity and scroll to the section Allowed Actions.

4.9.3. Document models with a file template

We’ve learned how we can create and use a document work item from uploadable content. In our next step, we will attach a file template, also called a skeleton, to the document model. Go back to the tutorial app and select the Travel Request Document and click the Upload skeleton button. You can now upload a document that will be used as the template whenever we create a new document based on that model. Choose an empty Word document for now, and we will use it again later with placeholders.
After having uploaded the document, you will see it in the preview (even if it is a Word document).

document model 05

Now have a file template attached to the document model, we really don’t need the upload widget in the init-form anymore, so go to the Travel Request Document Form, remove the Upload widget and save the form.

Go back to the Tutorial App, redeploy it, switch back to the user dashboard and navigate into one of your previous cases. Click Create, select Create Document, select Travel Request Document, choose any name you want for the document and click Create. If you go to the Preview (eye icon), you will see a document that looks the same as you used for the skeleton in the document model.

Whenever there is a skeleton file attached to a document model in an App, it will create a copy of it and store it in the case in which the document was created.

4.9.4. Document models with a file template containing placeholders

We’ve learned how document skeletons can be used as the template that is copied when a new document is created. In our next step, we will add placeholder fields in the document so we can automatically fill in data from the root case of the document.
Go back to the Tutorial App, select our Travel Request Document and click Edit skeleton, which should open the document in Microsoft Word. If the Java plugin for the Office integration is not supported in your browser, you can just use the Download skeleton button, save it to your desktop and open the document from there.

Now write your travel request document template and use text fields for the placeholders (you typically find them in the developer tools of Microsoft Word). Your document could now look like this:

document model 06

Double-clicking a placeholder opens up its details:

document model 07

The important information is the text marker name, which we will use later for data binding. We’re using the expression we’re going to map to afterwards as the standard text, but this is not mandatory, only good practice to see where data will be filled in.

I used the following placeholder information:

  • caseName, will later be bound to #{root.name}

  • travelOrigin, will later be bound to #{root.travelOrigin}

  • travelDestination, will later be bound to #{root.travelDestination}

  • outwardTripDate, will later be bound to #{root.outwardTripDate}

  • returnTripDate, will later be bound to #{root.returnTripDate}

  • approverName, will later be bound to #{root.approverName}

  • approvalDecision, will later be bound to #{root.approvalDecision}

It’s good practice to use the same name for the text field as for the variable name that the field will be bound to later, although this is not strictly required.

Now save the Word document. You need to use the Upload skeleton action and upload the saved Word document again.

Navigate to the Tutorial App and redeploy it, then switch to the user dashboard, select one of your previously created cases and create a new document the same way we did before.

Your document in the case should now look similar to this:

document model 08

As you can see, the request name has not been properly set within the title, which is because we used caseName as the name of the marker and this is not a variable name that’s available in our travel request case. Not only that, we’d really like to change the formatting of the dates as well, so let’s see how we can do that.

Mapping expressions to placeholder names in a document template

If we do not want to use a direct mapping by using the same name for the text marker as the name of the variable to be filled in, we can create a mapping using an expression. To do that, go back to our Travel Request Document model in the Tutorial App and navigate to the work-form view (the preview is active by default).

At the bottom of the view, you will see a section labelled Placeholders from where you can add mappings by clicking the Add Placeholder button for each mapping you want to configure. For every placeholder with a mapping, the engine will first evaluate your expression and then use this as the value to substitute in the text field.

Add the following placeholder configurations to the document template:

  • caseName with expression #{root.name}

  • outwardTripDate with expression #{formatDate(root.outwardTripDate, 'dd.MM.yyyy')}

  • returnTripDate with expression #{formatDate(root.returnTripDate, 'dd.MM.yyyy')}

The placeholder section should now look like this:

document model 09
We used a function in our expression, formatDate(date, format), which takes a date object as its first parameter and a date formatting string as the second. Please refer to the reference documentation to see further functions and what you can do with the expression language.

Now save the document model, go to the Tutorial App, redeploy it and create another document in your case which should look similar to this:

document model 10

4.9.5. Create documents from within a process

We’ve so far learned how to create a document model, use skeletons and further improve them with placeholders (optionally with placeholder mappings using expressions). Our next step takes us back to the process model, where we want to automatically create our document as part of the process. Go to the Tutorial App and open the Travel Request Management Process.

Drag & drop a new Create document service task onto the sequence flow, right after the last Review Travel Bookings user task, and name it Create Travel Doc. In the property Document model, choose our recently created Travel Request Document model and use root.travelDoc as the Document id variable name property. You can optionally specify the name for the document using the Document name variable, so we’ll set it to #{root.name}.docx.

Your process should now look like this:

document model 11
Using a variable name for the document ID will give us the ability to reference this specific document later by using that variable.

You can now save the process model, redeploy the app and start a new travel request or start the travel management process within an existing case again. By the end of the process, our document will have been created from the template using the data from the case, and stored within the case.

4.9.6. Send documents as attachments to an email

As a final step, we want to send a document from our case as an attachment to an email. Go back to our Travel Request Management Process and make some space before the Send decline notification email task. Before we can use the document as the attachment in that email, we first have to create it using the same task we added in our last step. We could add a new Create document task again or we can copy & paste our existing one, so we don’t have to enter all properties again. You can do so by selecting the existing Create Travel Doc task, using the Copy button or hit Ctrl-C to copy it and then the Paste button or Ctrl-V to paste it. Drag this copy and drop it onto the sequence flow just before the Send decline notification email task.

Your process should now look like this:

document model 12

Select the Send decline notification email task, click the Attachment ids property and enter #{root.travelDoc} in the property dialog.

Save the process, redeploy the app and start the process again or create a new travel request. Make sure to use the approval path and decline it in order to send an email with the document as an attachment.

4.10. Create convenience queries

Queries are a kind of work item that allow the saving and optional sharing of a custom query, which when executed acts like a filter that returns a list of work items. If you’re familiar with the search in edoras one, then you’re almost there, as a query is nothing other than a saved search request that can be executed at any time later.

And that’s exactly how you can actually create a new query: simply type some search terms in the search box, hit Enter and then use the Create Query button to save it.

You can use a simple search just by entering words to search for. More powerfully, you can use advanced search terms, so for example, type:CAS or for:me would search for cases only assigned to the current user.

4.10.1. Create query to return all open travel request cases

If we want to get a list of all open travel request cases, here’s the way to create an appropriate query item:

  • click the search box and enter type:CAS and hit Enter to see a list of cases

  • now add state:open as a second term and hit Enter to see only open cases

  • add model:'Travel Request' as a next term and hit Enter to just see open travel request cases

You probably noticed that some of the terms are being removed from the search box and represented using the predefined, simple search selection, for example the state and type terms or even the sort term.

Once you have the results in the way you want them, click the Create Query button, add a name for it and click Create. If you go back to the user dashboard, you will see the new query item in the list of My Queries.
If you wish, you can share a query item with others by using the Share action. This will mean other users will have the opportunity to see and use that query in their own dashboards.

4.10.2. Execute and change an existing query item

Once you’ve created a query item, it’s simple to use it by just clicking it in the user dashboard. It will then be executed and return a list of work items matching the query terms.
If you select the Work Form view at a later time, you can change the name and query term for the item and save it the same way you would with a case or task item. Alternatively, you can use the Share action to add some groups you want to share the query item with.

4.10.3. Exporting the data returned by a query item

Once you’ve execute a query item, you can export its results and data by clicking the Export Query Data button. This will create an Excel file containing all data from the returned work items.
Currently, you can’t configure what data is exported, so the Excel file can become quite large.

4.11. Create your own dashboard

In this chapter, we are going to create our own dashboard and we will learn how to set it in our user profile to be used as our default dashboard.
Currently, there’s not a specific confugration feature for custom user dashboards, so we’ll be using one of the general customization capabilities of the edora one platform.

4.11.1. Using a case model to represent our own dashboard

We are going to model and design a case to act as our dashboard. Since we can design a working form for a case, we can design it in such a way that it could act as our dashboard. We can’t use it directly, so we need to create an instance of the case and find its unique URL, then store this URL as the default one in our user profile and we’re done!

4.11.2. Designing the form for our dashboard

This is exactly the same as we’ve done many times now in this tutorial, so go to the Tutorial App, hit C or click the Create button and select Create Form Model to create our dashboard view. Name the form Dashboard View as it’s more a view than a form, then click Create and Design to directly create the form model and open it in edoras vis to design it.

Drag & drop an Output textarea on to the top of the form, so we can add some information about the dashboard. Double-click it and add something like this to it:

dashboard 01

We want to add some lists of information to the dashboard, so drag & drop a new List widget onto the form and remove the label by deleting its predefined text. Lists show work items retrieved using a query term. Still remember the query items from our last chapter? A list widget is based on exactly the same query terms and uses the same search functionality as a query item or the global search action in edoras one.

Now select the newly added List widget and set the Title property to Open travel requests.

With the Format property we can specify how the labels of the items in the list will be displayed. By default, it will use the name of the work item. We would like to also include the original requestor of the travel request, so let’s set the Format property to {{item.name}} (Requestor: {{item.owner.name}}), which will include the name of the requestor after the name of the travel request case.

Set the Query property to the following search term: type:CAS state:open model:'Travel Request' sort:creation:desc

We can limit the height of the list widget by setting the property Maximum number of rows, for example, to 10.

Your form should now look like this:

dashboard 02

We would like to add two more lists, one of them only showing the Manage Travel Request user tasks, and the other showing all open tasks, regardless the type of case or app.
First the management tasks: drag & drop another List widget to the right-hand side of the existing list and configure the following properties:

  • set the Label property to an empty value to hide it (we’ll use the Title property instead)

  • set the Query property to type:TSK state:open for:me name:'Manage Travel Request' sort:creation:asc

  • set the Title property to My open management tasks

  • set the Format property to {{item.name}} ({{item.root.name}}), so we include the name of the travel request case after the task name

Add a third List widget to the far right of the same row as the two other lists. If we want the three list widgets to be equally spaced, use the handle on the right or left-hand side of the widget to drag it to the left or right until it spans as many cells as you want (four, in our case, to have three equally spaced lists).

Set the properties of the third list widget to the following values:

  • set the Label property to an empty string to hide it (again. we’ll use the Title property instead)

  • set the Query property to type:TSK state:open for:me sort:creation:asc

  • set the Title property to All my open tasks

  • set the Format property to {{item.name}} ({{item.root.name}}), so we include the name of the travel request case after the task name

Suppose we want to add an instant-filter field to the first list, to allow the user to filter the list to find a particular travel request. Drag & drop a new Text widget between the Output textarea and the List widget on the left. Then drag its right-hand side handle to the left in order to let it span the same number of columns as the list widget and name it Search. Set its value binding to {{caseSearch}}. We can now use that variable within the Query property of our first List widget to dynamically update the saved search terms for the resulting case list.

Select the first List widget (containing the open travel request cases) and add {{caseSearch}} at the end of Query, so it now is configured as type:CAS state:open model:'Travel Request' sort:creation:asc {{caseSearch}}.

The dashboard view should now look like this:

dashboard 03

Now let’s save the form and return back to our Tutorial App.

4.11.3. Creating the case model for the dashboard

As we said above, we’re going to model a case to represent our dashboard. Hit C or click the Create button and select Create Case Model then use Travel Management Dashboard as the name and set the Dashboard View for the Init Form and Work Form properties. Remove all selections from the Allowed Actions section, except the Create Variables action, as although we don’t want to work with that special case, we do want to display it. If you want to share the dashboard with others, you can select the appropriate groups within the Candidate Groups property.

Now click the Create button and redeploy the Tutorial App, then go to the user dashboard.

4.11.4. Creating an instance of our dashboard

Before we can set the dashboard as our default one, we need to create a case instance based on that case model, so hit C or click the Create button within the user dashboard, select our Travel Management Dashboard template and click Create.

If you want to avoid having a case with an empty name, use the Edit view (only available as an admin or modeler) and set the Name field to something like Travel Management Dashboard and click the Save button.

Your dashboard should now look similar to this one:

dashboard 04
Hiding the Save and Cancel buttons in the dashboard

Because our dashboard is a simple case, the Save and the Cancel buttons are still shown in our dashboard view, but we don’t want them there. Here’s a technique to hide those buttons by adding a hidden widget to the Dashboard View form that will cause the form engine to hide the buttons.

  • Go to the Dashboard View form and add a Checkbox widget at the end of the form.

  • Set the Value to {{_hideSavePane}}.

  • Set the Default value to true (enabled).

  • Set Style class to hidden.

  • Make sure the Visible attribute is enabled (true).

  • Label it (Hide Buttons Widget) to indicate what it’s used for.

Redeploy the Tutorial App and migrate the current dashboard case.

Your dashboard should now look similar to this one:

dashboard 05
The Manage Travel Request task will be assigned to you if it went through an approval loop.

4.11.5. Adding count widgets to the dashboard view

Assume we have a lot of open tasks or cases and we can’t see all of them in the list widget, but would like to know how many there are. There are special Count widgets that allow us to display a link with a count of work items based on its associated query.
Go back to the Dashboard View form designer and add new Search count link widgets just below each of our list widgets, making their width span equally with the list widget they belong to.
Remove the label, as we only want to display the link text that includes the count of work items in the list.

For the first count widget, use the following properties:

  • set the Link text property to $count open travel request [case|cases] found

  • set the Query property to type:CAS state:open model:'Travel Request' (for the count query we obviously don’t need the sort term and we always want to show all open travel request cases, so we remove the caseSearch term)

  • set the Target property to _self to set the navigation to the same window

For the second count widget, use the following properties:

  • set the Link text property to $count open travel management [task|tasks] found, assigned to me

  • set the Query property to type:TSK state:open for:me name:'Manage Travel Request' (again, we don’t need the sort term)

  • set the Target property to _self to set the navigation to the same window

For the third count widget, use the following properties:

  • set the Link text property to $count open [task|tasks] found assigned to me

  • set the Query property to type:TSK state:open for:me

  • set the Target property to _self to set the navigation to the same window

The $count term is a special term which will be set to the count result returned by executing the query.
In the [x|y] term, the x gives the text to be used if the count is exactly 1 and y will be used if the count is more than 1.

Your dashboard view should now look similar to this one:

dashboard 06

Go to the Tutorial App, redeploy it, go to the Travel Management Dashboard case and click the Migrate action in order to update our dashboard case to the latest version.

Your dashboard view now should look like this:

dashboard 07

4.11.6. Adding create buttons to the dashboard view

As a next step, we would like to add a new Create button to the dashboard view so a user can create a new Travel Request without using the general Create button.
Go back to the Dashboard View form and add a new Create button below the first count widget and resize it to only span four columns.
Use Create new travel request as the Button text property, choose Case as the Work item type property and select Travel Request as the Work item model property.
This will create a button that navigates directly to the init-form for a new travel request (the same URL, actually, as if you had clicked the create button and selected the travel request template).

Your dashboard view now should look like this:

dashboard 08

Go to the Tutorial App, redeploy it, go to the Travel Management Dashboard case and click the Migrate action in order to update our dashboard case to the latest version.

Your dashboard view now should look like this:

dashboard 09

If you click the Create new travel request button, you will go directly to the init form and be able to create a new Travel Request.

4.11.7. Passing local context variables to the init form with a create button

Let’s say we want to add some information we already have on the dashboard form and pass it to the init form being invoked by clicking a create button. We can do so by using context parameters.

To visually separate the create button from the list widgets, let’s add a horizontal line between them by dragging & dropping a new Horizontal line between the count widgets and the create button.
Then move the create button to the same four columns as the second list widget, giving us space to add a new text field to the first four columns.
Now drag a new Text widget and drop it on the left-hand side of our create button, name it Request name and bind it to {{travelRequestName}}. Optionally, you can specify a description by setting the Description property to Set the new travel request name used for creating a new travel request.

Next, select the create button and click the Context variables property and enter the following in the property dialog:

dashboard 10

We’ll use the value from our newly added text field, ({{travelRequestName}}), and pass it along to the init-form as the name property, so our name field in the init-form will become prepopulated with that value.

Your view should now look like this:

dashboard 11

Go to the Tutorial App, redeploy it, go to the Travel Management Dashboard case and click the Migrate action in order to update our dashboard case to the latest version.
If you now enter some text in the request name field and click the create button, that text is passed along and directly added to the init-form.

If you want, you can add even more fields and functionality to your dashboard view.

4.11.8. Setting our dashboard as the default one

Now we’ve created our dashboard case, we would like to use it as the default one for the user dashboard.
First, make sure our new custom dashboard is currently shown and copy the URL-part starting with the CAS part (something like CAS/GEAR-xxxx/browse).
We can then set it as the default dashboard by going to our user profile (select the User profile menu action in the top right menu bar) and pasting the copied URL to the Home URL field, finally saving the user profile.

dashboard 12

To make the changes visible, you will probably need to refresh the current view, and then you should find yourself looking directly at your new, custom dashboard!
You can always navigate to it by clicking the logo in the top menu bar. If you want to go back to the standard user dashboard, you can do so by selecting it from the dashboard menu or with the Home icon in the menu bar.

5. edoras one DMN Tutorial

5.1. Intro

This tutorial will guide you through the DMN integration in edoras one.

As a prerequisite you need to know how to model BPMN and CMMN models and have a basic understanding of the app concept. If you need a refresher, then please have a look at the modeler tutorial chapter.

5.1.1. What you will learn

During the tutorial you will learn more about the following topics:

  • Basic understanding of DMN

  • How to create DMN models

  • Integration into BPMN processes

  • Integration into CMMN processes

  • DMN hit policies

5.2. What is DMN

DMN (Decision Model and Notation) is a published standard to describe decisions and business rules. The DMN standard is complementary to the BPMN standard and extends it by integrating specific DMN decision tasks into the process model.

With DMN you are able to:

  • document and comply with business rules for e.g. regulatory compliance, security audits

  • automate manual decision making

  • improve and simplify BPMN processes where decisions were modelled using BPMN expressions

You will find more detailed information about DMN in the standard itself at http://www.omg.org/spec/DMN/Current.

5.3. Tutorial context

The tutorial walks through a simplified version of a client onboarding process in a banking environment. It abstracts the gathering of the client data, the validity checks with external systems and the following tasks to successfully onboard the client.

These abstractions are hidden behind service/manual tasks and the title of the tasks properly reflect their intention.

The following image shows the whole process with two DMN decision tasks integrated:

client onboarding process

The two DMN decision tasks name Verify Client and Evaluate Client Category are the ones where we put the focus on in this tutorial. They include the following business rules:

  1. Verify Client: Based on the two upfront service tasks, which check the client data against external services and create a risk analysis, plus the business related rules, the Verify Client decision task outputs if the client can be automatically verified or not. If the client could not be automatically assigned based on the rules, a manual verification is needed.

  2. Evaluate Client Category: With business rules based on the initial client data like funds on deposit and estimated net worth, a category gets assigned to the client.

5.3.1. Tutorial prerequisites

The following prerequisites are mandatory to successfully finish the tutorial:

  1. Create an app which holds all the models.

  2. Create a process model in which we will add the needed tasks in the upcoming sections.

  3. Create a case model to be able to test the process in the scope of a case.

In the next section we will start with the tutorial.

5.3.2. Retrieving initial data

First we need to retrieve the initial data needed for the business rules in the Verify Client DMN decision task. The following image shows the three tasks which we first need to model before we dive into the DMN decision tasks.

client onboarding process 1 part
Enter client information

This user task is used to gather upfront data from the client like funds on deposit and estimated net worth in dollars. This data is needed as part of the business rules in the Verify Client DMN decision task.

In the already created process model add a start event followed by the Enter client information user task. The form for the task looks as the following one:

client onboarding process enter client information form

Both fields are number fields and the data is stored on the case (root prefix). Please check that the expressions in your form matches the one in the above image.

Verify client against external services

This service task should mock a service call needed to verify the client data. This could be a check against a criminals database or any other service to prove that the client is trustworthy.

To mock the return value without any real implementation you need to set the Expression attribute of the service task to the following expression:

#{root.fundsOnDeposit % 2 == 1 ? true : false}

This expression takes the fund on deposit and returns with the help of the modulo operation true or false. As the output is based on the funds on deposit we are able to predict the result of the expression.

Risk analysis

This service task should mock a service call needed to check the risks based on the client data. This could be a call to the internal risk analysis system which calculates the risks connected to this client.

To mock the return value without any real implementation you need to set the Expression attribute of the service task to the following expression:

#{root.estimatedNetWorth % 11 * 10}

This expression takes the estimated net worth and returns with the help of the modulo operation a percentage from 0 to 100% in steps of 10. As the output is based on the estimated net worth we are able to predict the result of the expression.

5.3.3. Verify Client decision task

Now we finally start modelling our fist DMN decision task. For that click on the Create button in the Modeler Dashboard and click the Create Decision Model button as shown in the following image:

create dmn model

Next give it Verify Client as a name and click on the Create button. After that, click on the Design action in the right actions bar and then you see the DMN decision table editor.

The DMN decisions table editor

The editor is split up in multiple parts with inputs on the left and outputs on the right. We will now go through the specific parts in detail:

dmn table editor
  1. This is the input section where you are able to click on the title and then define the details for the inputs. In addition to that you can click on the + sign to add another input. The details of the input are the following:

    dmn table editor input details
    • Label: The label is used to give the input a name which is used for documentation.

    • Variable name: This field is used to define from which variable the input data should be retrieved. If no context (root or parent) is given, the process context where the DMN decision task is executed is taken.

    • Variable type: Here you need to define the type of the variable.

    • Allowed values: In the allowed values you define the values which you need in your business rules and which you select in the drop down for the value.

      The entered information is also shown in the table header in the same order as in the input dialog.

  2. This is the output section where you are able to click on the title and then define the details of the output. In addition to that you can click on the + sign to add another output. The details of the output are the following:

    dmn table editor output details
    • Label: The label is used to give the output a name which is used for documentation.

    • Variable name: This field is used to define to which variable the output data should be written. You are only able to use process level variables as output. You cannot use root, parent or any other context, as this is not supported.

    • Variable type: Here you need to define the type of the variable.

    • Complex expression: Check this flag if you have a non string type variable and you want to use a complex expression as output.

    • Allowed values: In the allowed values you define the values which you need in your business rules and which you select in the drop down for the value.

      The entered information is also shown in the table header in the same order as in the output dialog.

  3. This field is used to select the comparison operator which is used to define the input rules based on the specified input. In the following image you see an example of where the Funds On Deposit input value needs to be less or equal to 100'000 such that the rule is triggered.

    dmn table editor comparison operator
  4. This field is used to select the input value for the rule based on the defined allowed values. If the input should not be included in the rule evaluation, then choose the - option to omit the input value for this rule.

  5. This menu is shown when you right click anywhere on the editor. It provides actions to add/remove rules, rearrange them, add inputs/outputs and also to revert to a previous state of the decision table.

  6. Clicking this button will save the model.

  7. By clicking the top left cell, you can choose the Hit Policy for this DMN model. The following tables show the different hit policies(single and multiple) with their official description taken from the specification:

Table 71. Single Hit Policies
Name Behavior

First (default)

Multiple (overlapping) rules can match, with different output entries. The first hit by rule order is returned (and evaluation can halt). This is still a common usage, because it resolves inconsistencies by forcing the first hit. However, first hit tables are not considered good practice because they do not offer a clear overview of the decision logic. It is important to distinguish this type of table from others because the meaning depends on the order of the rules. The last rule is often the catch-remainder. Because of this order, the table is hard to validate manually and therefore has to be used with care.

Any

There may be overlap, but all of the matching rules show equal output entries for each output, so any match can be used. If the output entries are non-equal, the hit policy is incorrect and the result is undefined.

Unique

No overlap is possible and all rules are disjoint. Only a single rule can be matched.

Priority

Multiple rules can match, with different output entries. This policy returns the matching rule with the highest output priority. Output priorities are specified in the ordered list of output values, in decreasing order of priority. Note that priorities are independent from rule sequence.

Table 72. Multiple Hit Policies
Name Behavior

Rule order

Returns all hits in rule order. Note: the meaning may depend on the sequence of the rules.

Output order

Returns all hits in decreasing output priority order. Output priorities are specified in the ordered list of output values in decreasing order of priority.

When a multiple hit policy is used and multiple rules were hit, the output value is a list of maps (as there can be multiple output values per rule). The variable name of the list of maps will be following the pattern of {activityId/planItemId}_dmn_output where activity id is the id of the DMN task in the BPMN model or a plan item id of the DMN task in the CMMN model. In the single hit policies a single value will be returned as output using the variable name defined in the output column.

Rules for the Verify Client decision task

Now that we know how to use the DMN decision table editor, we are able to add some rules based on our tutorial context about the client onboarding. Please add the following rules and then save the model:

dmn table editor verify client

As you see, we use the two outputs of our previously defined service tasks as inputs, plus the initial funds on deposit value to check if the client is valid or not. The service task inputs are read from the process level variables validClient and riskAnalysis and the funds on deposit is a variable stored on the case and therefore is read with the root context prefix like root.fundsOnDeposit. The output is then stored in a process level variable with name automatedValidation.

As a last step link the newly created Verify Client DMN model with a new Decision Task in the process by selecting the model in the Decision Table Reference attribute in the right attributes pane. After that change the process should look like the following:

client onboarding process 2 part

5.3.4. Process output of DMN decision task

After the DMN decision task did its job and verified if the client is valid or not, we can add a check based on the automatedValidation output variable. If the automatedValidation is false then we can add a manual verification task and if it is true, the process can continue automatically. The following image shows how this can be done:

client onboarding process 3 part

The expression used for the false path is #{automatedValidation == false}, and the true path is set as default flow. In the Verify Client Manually task we have the following simplified form to manually set the client as verified or not. Based on that value we have another check done in the same way as for the automatedValidation, except that we now use the manualValidation variable name and #{manualValidation == false} as false path expression.

client onboarding process verify client manually form

5.3.5. Evaluate Client Category and further processing

If the client was not properly verified, we are able to get back to the client if there is an issue with the verification (see the Notify client about failed onboarding manual task), and if the client was verified successfully, go ahead with the onboarding and create another Evaluate Client Category DMN decision task which categorizes the client based on the initial data entered. In the following image you see all the rules defined for this decision task:

dmn table editor evaluate client category

The evaluated category can then be used for further processing in the onboarding process. Both manual tasks at the end are mocks which are there to show that a real life business process would continue to onboard the client.

5.3.6. Conclusion

In this tutorial we learned how to integrate the DMN decision task into a BPMN process and use the business rules to determine if a client is verified for an onboarding process.

5.4. DMN Integration in CMMN

We are also able to integrate the DMN decision tasks into a CMMN case. The only difference to the execution of DMN decision tasks on a process level is that the execution context is different. You are able to set the execution context by changing the expression in the Target object attribute in the attribute list of the DMN decision task in the CMMN modeler. By default the execution context is root, meaning that the output variables are stored on the CMMN case itself. The following image shows where to find the DMN decision task and the above mentioned property:

dmn integration in cmmn

Everything else behaves the same way as in a process scope.

6. edoras one Administrator Guide

6.1. Administration Overview

The admin dashboard can be accessed by authorized users through the dashboard menu and is used to manage users and work item access permissions within edoras one.

6.1.1. Tenants

An edoras one installation may provide one or more tenants. A tenant is an isolated environment for a specific group of users. No data can be shared between tenants and users are always logged into a specific tenant. The edoras one tenant support allows multiple edoras one environments to be provided by a single server instance.

Tenants are not directly visible in the administration dashboard and cannot be administered there, as the tenant selection has already been made when the user logged in, but it is perhaps useful to know that the administration operations described here take place within the context of a particular tenant.

6.1.2. Users

User entries define the people who are allowed to log into the system and their settings.

The following attributes may be set for a user:

Table 73. User attributes
Name Required Description

Display name

Yes

the name that will be shown in the edoras one application

Login name

Yes

the name used to login to edoras one

Email address

Yes

the user’s email address

Language

No

the user’s language

Password

Yes

the user’s password

Last name

No

the user’s last name

First name

No

the user’s first name

Address

No

the user’s address

Phone

No

the user’s phone number

Mobile

No

the user’s mobile phone number

Notes

No

additional notes

A user can also enable automatic email notification of specific events within the system:

  • when a task is assigned to the user

  • when the user is a candidate for a created task

  • when a task assigned to the user is edited

  • when a task owned by the user is edited

If a task has both an assignee and candidates, a notification will only be send to the assignee (not the candidates).

The password may be changed at any time by entering a new password in the two password fields. The password will be changed only when the two fields contain the same value and password matches regular expression set in password.validation.pattern.

The non-required fields are provided for information purposes only and are not used by edoras one itself.

A user belongs to an account and can be moved between accounts using the move action.

User entries can be activated and deactivated. Deactivated users will not be able to log into the system and will not be shown in the application, for example when reassigning a work object.

Predefined users

Each tenant in edoras one has an administration user. This user has full access to all work items in the system and certain special access permissions for system administration tasks.

6.1.3. Accounts

Accounts are used to collect users and groups that are related to each other, making it easier to organize and locate particular entries.

The following attributes may be set for an account:

Table 74. Account attributes
Name Required Description

Name

Yes

the account name

Description

No

the account description

CSS class

No

account css class added to the html

The CSS class will be used when any user that belongs to the account is logged in. Then this CSS class will be applied to the app div (.edoras-one).

For "Cloud" solutions, there are some predefined account css classes:

Table 75. Account predefined "Cloud" css classes and colours
CSS Class Main Colour Main Dark Colour

account-brown

account-green

account-teal

account-blue

account-purple

account-pink

(empty/default)

Leave CSS class empty to turn off UI customisation for the Account and use default colours.

If an account is activated or deactivated then all users and groups in that account will also be changed to the new state.

Predefined accounts

The following accounts are defined by default in edoras one:

admin

contains the standard users and groups provided by edoras one and needed for correct operation of the system

<tenant name>

a tenant-specific account which contains any additional tenant users and groups

6.1.4. Groups

Groups are used to control the accessibility of objects within edoras one.

The following attributes may be set for a group:

Table 76. Group attributes
Name Required Description

Name

Yes

the group name

Description

No

the group description

As with a user, the group belongs to an account and can be moved between accounts using the move action.

A group can also be activated and deactivated. Note that deactivating a group simply means that objects cannot be shared with that group in the future. Existing objects that are shared with a deactivated group will be unaffected.

Predefined groups
All users

A group for all users in the tenant.

edoras one Admin

The administration group with access to the administration dashboard.

edoras one Manager

The manager group with access to the management dashboard.

edoras one Modeler

The modeler group with access to the modeler dashboard. This is also the default group for sharing models.

edoras one User

The user group with access to the user dashboard.

edoras one Supervisor

Users that belong to the supervisor group can view all work items in the system, regardless of who they are assigned to or shared with.

6.1.5. Apps

It is possible to manage the properties from the app models with the apps. By clicking on one app, the same property view is showed as with the deploy action view, however, the static properties are read-only. Only dynamic properties might be changed.

6.1.6. Access permissions

Access permissions in edoras one are controlled by group membership. To change a user’s group membership settings, select the user to be updated and then use the Group membership action to add or remove groups as required.

Work item visibility

A work item in edoras one is visible to a particular user if one of the following conditions is satisfied:

  • the work item is owned by the user

  • the work item is assigned to the user

  • the user is a member of a group that appears in the work item’s sharing group list

If a work item is visible by a particular user then it can also be edited. No fine-grained access control mechanism is provided, for example to allow read-only access.

Dashboard visibility

A particular dashboard is visible to a given user if the user is a member of the relevant group. For a list of the predefined dashboard groups please refer to the section Predefined groups.

6.2. Glossary

tenant

a tenant is an isolated environment in edoras one where users can work and processes can be executed without risk of affecting the contents of other tenants in the same server.

user

a user work item gives access to a particular tenant in edoras one, with associated attributes and permissions.

group

groups are used to control access to work items (and dashboards, in the case of the predefined groups).

accounts

accounts are used as a container for related users and groups. They can also be used to control the appearance of edoras one.

apps: a "singleton" work item from the app model. The app model properties are accessible from the app.

7. edoras one Operator Guide

7.1. Overview

This document describes the operational aspects of edoras one and its integration with other systems.

It is intended for system administrators responsible for configuring an edoras one installation.

7.2. Server Requirements

7.2.1. Java

The minimum Java version to run edoras one is 8.

7.2.2. Database

If you use MySQL or MSSQL you need to set a case sensitive collation such that edoras one has the same functionality as on any other database. We recommend the following collation for MySQL and MSSQL:

  • MySQL collation: utf8_bin

  • Execute the following query to change it on your database: ALTER DATABASE {DATABASE-NAME} CHARACTER SET utf8 COLLATE utf8_bin;

  • MSSQL collation: Latin1_General_CS_AS

  • Execute the following query to change it on your database: ALTER DATABASE {DATABASE-NAME} COLLATE Latin1_General_CS_AS;

7.2.3. Fonts

The edoras one server requires a number of Microsoft TrueType fonts to be available to run correctly. On many systems the required fonts will already be installed by default, but in some cases this may not be the case. If the fonts are not available, the result may be a long wait while the server attempts to find the fonts somewhere in the filesystem and it may not be possible to start the server at all.

On Linux systems (e.g. CentOS) the required fonts can be obtained by installing the msttcorefonts package.

7.3. Tenant configuration

A new tenant in edoras one is created by adding a tenant definition file to the tenant data folder and restarting the server. The tenant data may either be built into the edoras one WAR file (see the :developer-guide: for more information) or placed in an external folder. The tenant data location can be configured using the system.tenant-cfg-location property. To use an external folder, the value of this property should have a file: prefix, for example:

file:${edoras-one.home}/tenants

7.3.1. Overall structure

The tenant definition is a JSON object definition, something like the following:

{
    "id": "tenantId",
    "name": "acme",
    "adminUserLogin": "testAdmin1",
    "adminUserEmail": "testAdmin@test.com",
    "accounts": [
        {
            "name": "account",
            "domain": "test.com",
            "cssClass": "account-blue",
            "groups": [ "group" ],
            "users": [
                {
                    "displayName": "John Smith",
                    "firstName": "John",
                    "lastName": "Smith",
                    "login": "john.smith",
                    "email": "john.smith@email.es",
                    "language": "en",
                    "memberGroups": ["group"]
                }
            ]
        }
    ]
}

The following sections describe the available attributes for each part of the definition.

7.3.2. Tenant information

The top level of the JSON contains information about the tenant. The following attributes are supported:

Table 77. Tenant attributes
Attribute name Description

accounts

a list of the initial accounts

adminUserLogin

admin user’s login

adminUserEmail

admin user’s email address

name

tenant name

7.3.3. Account information

An account entry defines an initial account within the tenant. The following attributes are supported:

Table 78. Account attributes
Attribute name Description

domain

domain name (used to create user email addresses automatically)

cssClass

account css class added to the html

groups

a list of group names

name

account name

users

a list of the initial account users

For each account entry, an account will be created with the given name, groups and users.

The CSS class will be used when any user that belongs to the account is logged in. Then this CSS class will be applied to the app div (.edoras-one).

For "Cloud" solutions, there are some predefined account CSS classes:

Table 79. Account predefined "Cloud" css classes and colours
CSS Class Main Colour Main Dark Colour

account-brown

account-green

account-teal

account-blue

account-purple

account-pink

(empty/default)

Leave CSS class empty to turn off UI customisation for the Account and use default colours.

7.3.4. User information

A user entry defines an initial user within the account. The following attributes are supported:

Table 80. User attributes
Attribute name Description

displayName

user’s display name

firstName

user’s first name

lastName

user’s last name

login

user’s login

email

user’s email address

language

user’s language

memberGroups

groups that the user belongs to

For each user entry, a user will be created with the given information.

If no email address is provided and the account domain is set, then an email address will be created from the domain and user’s first and last names.

When defining a user’s group membership, both the default edoras one group names (edoras one Modeler etc.) and the group names explicitly defined in the account may be used.

7.4. Standard properties

edoras one provides a number of configuration properties that can be used to control the behaviour of the application. These properties can be set in a number of different ways:

  • in a property file built in to the application (this can only be changed by a developer)

  • in an external property file: one.properties

  • as a system property, for example on the application command line

These are listed in order of increasing precedence, so a property value defined by the application can be overwritten by an external property file, for example.

Properties are used to configure individual settings within edoras one’s Spring configuration. As an on-premise project may replace some or all of this Spring configuration, the properties that may be used in any given installation may also vary. The remainder of this section assumes that the installation uses the standard edoras one Spring configuration files.

7.4.1. Locating the external property file

edoras one looks for external property file in the edoras one configuration folder. By default this is the folder .edoras-one in the user’s home directory. An alternative configuration folder can be selected by setting the system property edoras-one.home.

If no external property file can be found then a message to that effect will be produced by edoras one during the application startup.

7.4.2. Basic configuration properties

Table 81. Basic properties
Property Default value Description

edoras-one.home

${user.home}/.edoras-one

the location of the edoras one configuration folder. This can only be set as a system property.

system.application-endpoint

http://localhost:8080/one

the base URL where the application is running

system.license-location

file:${user.home}/.edorasware/edorasware.license

the location of the edoras one license

system.tenant-cfg-location

classpath*:/com/edorasware/config/custom/tenant/*.json

the location of the tenant configuration files

Application endpoint

The system.application-endpoint property is used in several features of edoras one including the automatic email sender which sends an assigned task URL or the linked resource filter which is used to map constant front end resources names to hashed/versioned versions of these. This endpoint needs to be set to the endpoint where the clients are able to access edoras one. If the endpoint is set to https://edoras-one.com then the clients need to access it through this URL.

There are two setup methods on how you are able to access edoras one: first directly through the servlet container and second via a proxy. If you use the first option everything should work properly when you set the correct system.application-endpoint, but when you use the second option (behind a proxy) then you need to set the application .endpoint property to the endpoint of the proxy and not the one of the proxied servlet container.

If you have several endpoints accessing the same edoras one instance, then you need to ensure that the application.endpoint is set to one of these endpoints which is working correctly, but keep in mind that all generated URL’s will have this endpoint as prefix.

7.4.3. Content storage properties

Table 82. Content storage properties
Property Default value Description

content.provider-type

database

select the content persistence type (file or database)

content.enable-versioning

false

when set to true, the content manager will keep all the versions of the content on every update

content.cache.folder

${edoras-one.home}/temp/converted-content

the location for the on-disk content conversion cache

When file-based content persistence is used, the following properties may also be set:

Table 83. File-based content storage properties
Property Default value Description

content.provider.file.root-folder

none (REQUIRED)

the root folder for content persistence

7.4.4. App management properties

When the system is started, the system App from the product will be updated automatically (or installed if the system is being started for the first time). Apps from addons or the project will be also be installed if they are available.

When an App is imported, the version information from the new App will be compared against the version information of the App currently installed on the system. If the App on the system has changes that would be lost (for example the App has been locally edited) then the import will normally fail and the problem will be logged. The version check can be overridden by setting the appropriate force properties as described below.

Failure to update a pre-installed App will normally terminate the server startup with an error, as it is assumed that the Apps are critical to correct operation of the system. This behaviour can be overridden by setting the appropriate properties to ignore any errors, although this may mean that some Apps will not be updated in the running system.

The behaviour of the automatic App installation can be configured using the following properties:

Table 84. App management properties
Property Default value Description

apps.import.addons-location

classpath*:/com/edorasware/addons/app/*.zip

The location of pre-installed Apps from addons

apps.import.custom-location

classpath*:/com/edorasware/config/custom/app/*.zip

The location of pre-installed custom Apps

apps.editable-system-app

false

When true, allows system models to be seen and edited by everyone instead of just the supervisor

apps.import.force-system-app

false

Forces the import of the system App when true

apps.import.force-addons-app

false

Forces the import of Apps from addons when true

apps.import.force-custom-app

false

Forces the import of custom Apps when true

apps.import.ignore-system-app-errors

false

Ignore failures when importing the system App

apps.import.ignore-addons-app-errors

false

Ignore failures when importing Apps from addons

apps.import.ignore-custom-app-errors

false

Ignore failures when importing custom Apps

7.4.5. Clustering properties

The clustering support for edoras one can be enabled by setting the following properties:

Table 85. Clustering properties
Property Default value Description

cluster.enable

false

enables clustering support when set to true

cluster.redis.hostname

localhost

the hostname where the Redis server is running

cluster.redis.port

6379

the port where the Redis server is listening to incoming connections

cluster.redis.password

(empty)

the password of the Redis server

For more details on configuring an edoras one cluster please refer to the section on Clustering.

7.4.6. Query export properties

Table 86. Query export properties
Property Default value Description

export.date.format

yyyy-MM-dd’T’HH:mm:ss.SSS’Z'

the format to be used for exported dates (see SimpleDateFormat)

export.date.timezone

UTC

the timezone to be used for exported dates (see TimeZone)

7.4.7. Elasticsearch integration properties

The following properties can be used to configure the Elasticsearch integration so that it can connect to a suitable Elasticsearch cluster. When a property is not defined then the default value will be used. The settings currently in use are also shown in the server log on system startup.

Table 87. Elasticsearch integration properties
Property Default value Description

search.elasticsearch.enable

false

Enables the elasticsearch integration

search.elasticsearch.cluster-name

edorasone

the elasticsearch cluster name

search.elasticsearch.node-addresses

127.0.0.1:9300

a comma-separated list of network addresses that should be used to connect to an external cluster

search.elasticsearch.failed-job-retries

3

the number of retries for a failed indexing job before it is abandoned

7.4.8. Mail properties

The following properties can be used to configure the mail integration and several default mail models.

Table 88. Mail properties
Property Default value Description

ui.support-mail

support@edorasware.com

when a user clicks on the support button in the footer the local mail client will open with the specified mail address as 'to address'

mail.smtp.host

smtp.office365.com

the SMTP host. If this property is empty then mails will simply be logged and not sent.

mail.smtp.port

587

the SMTP port

mail.smtp.username

no-reply@edorasware.com

the SMTP user name for the authentication

mail.smtp.password

*

the SMTP password for the authentication

mail.smtp.encoding

UTF-8

the encoding used to send the mails over SMTP

mail.smtp.debug

false

true if SMTP debug log output should be written, false otherwise

mail.smtp.transport-protocol

smtp

the SMTP transport protocol

mail.smtp.auth

true

true if SMTP authenticates using the user name and password properties, false otherwise

mail.smtp.enable-starttls

true

true if SSL should be used to communicate with the SMTP server, false otherwise

mail.smtp.from

no-reply@edorasware.com

the From mail address to be used

mail.test-recipient

``

when set, all emails (of all users) are sent to this email address. WARNING: Only use this for testing purposes.

mail.model.assignee-changed

MAIL_MODEL-ec56a716-36c7-4850-8081-5daa9912872f

the model id (technically the global ID) of the mail model used to send notification emails if a work item is assigned to the user

mail.model.candidate-groups-changed

MAIL_MODEL-499f4935-0987-46ba-ac1e-ba6632927f16

the model id (technically the global ID) of the mail model used to send notification emails if a work item is created of which the user is a candidate user

mail.model.work-object-edited

MAIL_MODEL-0252639c-df22-4d4e-9262-0890587c192f

the model id (technically the global ID) of the mail model used to send notification emails if a work item is edited of which the user is assignee or owner

validation.email-address

^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]\+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$

the pattern used to validate the email addresses that a user enters in the user profile

7.4.9. Graphical modeler properties

The following properties can be used to configure the graphical modeler:

Table 89. Graphical modeler properties
Property Default value Description

modeler.addons-palette-location

classpath:com/edorasware/addons/palette

The location for additional addon palette configurations

modeler.custom-palette-location

classpath:com/edorasware/config/custom/palette

The location for additional project palette configurations

7.4.10. Encoding properties in property files

Sometime sensitive values need to be configured (such as user names or passwords) and storing these in plain text in the property files is a potential security risk. You can encode property values in a production property file so that the plain text value is not readable. Encoded values will be decoded when the property is loaded, so the original plaintext value is used for configuration.

As an example, we start with a plain text property:

sensitive.value=password:topSecret

We mark any sections of the property that should be encoded using the <ENCODE> delimiters. A property value may contain any combination of delimited encoded values and plain text:

sensitive.value=password:<ENCODE>topSecret<ENCODE>

This property definition (or the complete property file) is then passed through the command-line encoding tool (see below), resulting in an encoded equivalent marked with the <ENC> delimiters:

sensitive.value=password:<ENC>1TOKpX5hMQCd5mcSduoRxCofjybs6xgIEi4yo/zsW+E=<ENC>

This encoded value can then be used in the production property file. Encoded values in a property file will be decoded by edoras one when the property files are loaded, so the original property value can be used in the Spring configuration without exposing the plain text in the property file. A different encoding will also be used each time a value is encoded, so it is also not possible to identify encoded passwords using a known encoded value.

Running the command-line encoding tool

To run the command-line encoding tool you need to unpack the WAR file used to deploy the edoras one application. Next browse to the WEB-INF/lib folder of the extracted WAR file and run the command-line tool as follows:

java -cp edoras-one-server-core-2.0.5.jar:* com.edorasware.one.util.CommandLineParser -encode <value>

The value may either be a plain string to be encoded (e.g. the sensitive.value property value above) or the name of a complete property file. In both cases, the encoded text will be written to the standard output and can be either copied directly from the terminal window or redirected to a new file:

$ java -jar edoras-one-server-core-2.0.5.jar \
    -encode '<ENCODE>topSecret<ENCODE>'
<ENC>bnMeD/y2jbVzzw1OpLkTTo2qsO8obc4vwxmPzZJR3ao=<ENC>
$ java -jar edoras-one-server-core-2.0.5.jar \
    -encode /tmp/input.properties > /tmp/encoded.properties
$
Use " instead of ' on Windows

7.5. Tomcat configuration

7.5.1. Connector configuration

To allow to send UTF-8 characters in URIs (e.g. the search requests) we need to allow UTF-8 URI encoding in tomcat (server.xml).

    <!--
        Define a non-SSL HTTP/1.1 Connector on port 8080
        URIEncoding is set to UTF-8
    -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
      URIEncoding="UTF-8"
      />

    <!--
        Define an AJP 1.3 Connector on port 8009
        URIEncoding is set to UTF-8
    -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>

7.6. Clustering

To deploy edoras one on two or more nodes you will need the following prerequisites:

  • Apache HTTPD Server with mod_jk/mod_proxy or any other load balancing component (Apache HTTP Server, mod_jk, mod_proxy)

  • Two or more Apache Tomcat instances (or any other application server)

  • File content synchronization (like Gluster)

  • Redis 2.8 and greater (Redis)

mod_jk is only needed if you use an Apache Tomcat application server. If you use another application server, you will need mod_proxy.

As a load balancer we use the Apache HTTPD Server which sends the request to the Apache Tomcat nodes as configured in the mod_jk configuration. The file content (like documents in edoras one) are stored on the file system which is synchronized beteween the nodes with the help of Gluster. The last part is the Redis server which acts as central point for the distributed caches and the user sessions.

The following diagram shows this setup graphically:

cluster configuration

This guide will just show you how to configure edoras one to use Redis as distributed cache and as a distributed session store. Please refer to the following guides on how to install, configure these tools:

7.6.1. Configuration of edoras one

The properties needed to enable and configure the edoras one clustering support are described in the section Clustering properties.

The following list shows the configuration options needed to run edoras one in a clustered environment:

  • Enable clustering support by setting the cluster.enable property to true and configure the Redis connection properties

  • Use the shared file system to store cached converted document content. Because converted document content cache is shared between the nodes, each node has to point to the shared directory where converted content is stored. Each node has to point to the same shared directory for the all nodes. When you start the node in the cluster, evict the cache to keep nodes synchronized.

  • if you are using file-based content storage, please follow the instructions below to make sure that this is supported by your installation

When you have completed these steps edoras one is configured to run in a clustered environment.

File-based content storage

If you use file-based content management in a clustered environment, you first need to check if the shared file system supports the locking mechanisms needed to ensure data consistency. We provide a command-line lock check tool which creates a test file in the same folder and then tries to lock the file, write a line to the file and unlock it again. This will be executed as many times as specified in the given iterations parameter. Later in this section we also provide a bash script which executes this process several times to simulate concurrent access to this lock file which then tests the real use case.

To run the command-line encoding tool you need to:

  • unpack the WAR file used to deploy the edoras one application

  • browse to the WEB-INF/lib folder of the extracted WAR file and run the command-line tool as follows:

java -cp edoras-one-server-core-2.0.5.jar:* com.edorasware.one.util.CommandLineParser -lockcheck <iterations>
You need to run the lock check test tool, and extract the WAR file, on the shared file system you set up before (see first point in the clustered configuration) as there are network file systems which do not properly support the locking. If there is any error while executing the lock check please contact our edorasware support.

The <iterations> parameter is used to set the number of iterations as described above. This check simulates accessing the file with a single instance. You need to use the following bash script to simulate access of multiple processes on the same file which then checks if the file is properly locked and that there are no data inconsistencies. Please create a new file called lock-check.sh inside the WEB-INF/lib folder of the extracted WAR file on the shared file system with the following content:

#!/bin/bash

echo Starting $1 lock check processes ...
pids=""
result=0

# start the lock check java processes
for i in $(seq 1 $1);
do
    java -cp edoras-one-server-core-2.0.5.jar:* com.edorasware.one.util.CommandLineParser -lockcheck $2 &
    pids="$pids $!"
done

# wait for all the processes to finish
for pid in $pids; do
    wait $pid || let "result=1"
done

if [ "$result" == "1" ];
    then
       echo A lock check process failed.
       exit 1
fi

echo All lock check processes completed successfully!

Next make the file executable and then execute it with the following parameters:

./lock-check.sh 10 1000

This will then spawn 10 Java processes with the lock check tool running with 1000 iterations. When everything completes, a success message is shown and this ensures that file-based content storage can be used inside the cluster.

8. edoras one Developer Guide

8.1. Developing applications with edoras one

This document describes best practices for developing a customized application based on edoras one. It is mainly intended for software developers, although some topics address system installation and configuration and may therefore also be of interest to system operators.

Various topics are presented, grouped by general theme, with each topic describing a specific development task. The topics are generally independent of each other and can be read on their own without having to read the entire document. A working knowledge of the concepts underlying edoras one is required, and some topics will also require knowledge of edoras gear or some additional external technologies.

8.2. Setting up a development environment

Developing applications with edoras one is fairly straightforward if you are familiar with standard Java development workflows:

  • create a new project using a build tool (e.g. Maven or Gradle)

  • include the edoras one artifacts in your project as normal dependencies

  • provide the basic configuration needed to start edoras one

  • extend edoras one by adding your own configurations and / or classes as required

This section describes setting up your development environment and including edoras one into your project. The following sections describe the edoras one extension points and how they can be used to customize edoras one and integrate it into your IT infrastructure.

The minimum Java version to develop with edoras one is Java 8.

8.2.1. Configuring the build system

Basic project build information

The example project provides build configurations for both the Maven and Gradle build systems. You can use whichever build system you prefer. For the Maven build Maven 3.0.0 or greater is required. The Gradle build is based on the Gradle wrapper and downloads the appropriate version automatically.

You can download the build tools here:

Basic Maven configuration

The project information and compiler version (Java 7 is required) should be set in the Maven pom.xml:

Project information in pom.xml
  <project xmlns="http://maven.apache.org/POM/4.0.0"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                               http://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>

          <groupId>com.edorasware.one</groupId>
          <artifactId>edoras-one-bootstrap</artifactId>
          <version>1.0.0</version>
          <packaging>war</packaging>
Compiler configuration in pom.xml
  <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.1</version>
          <configuration>
                  <source>1.8</source>
                  <target>1.8</target>
          </configuration>
  </plugin>

You should also configure the resource encoding to avoid warnings during the build:

Resource configuration in pom.xml
  <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-resources-plugin</artifactId>
          <version>2.6</version>
          <configuration>
                  <encoding>UTF-8</encoding>
          </configuration>
  </plugin>
Basic Gradle configuration

First you need to apply the war plugin and define the project information:

Project information in build.gradle
  apply plugin: 'war'

  allprojects {
    group = 'com.edorasware.one'
    version = '1.0.0'

    sourceCompatibility = 1.8
    targetCompatibility = 1.8
  }
Artifact repository configuration

To build the project you will need access to a Maven repository containing the edoras one artifacts so that the edoras one dependencies can be resolved. The artifacts can either be uploaded to a repository manually, or if you have access to the edorasware public repository then the connection details may be configured into your local repository and artifacts will be downloaded from edorasware automatically when they are needed.

After adding the edoras one artifacts to your repository you will also need to provide a suitable repository configuration and access credentials.

Maven repository configuration

The Maven repository configuration will typically be located in the pom.xml file. The following snippet shows the configuration for the edoras repository. The configuration for your local repository will look similar.

Repository configuration in pom.xml for Maven builds
  <repositories>
          <repository>
                  <id>repo.edorasware.com</id>
                  <url>https://repo.edorasware.com/edoras-repo</url>
                  <snapshots>
                          <enabled>true</enabled>
                          <updatePolicy>always</updatePolicy>
                  </snapshots>
          </repository>
  </repositories>

  <pluginRepositories>
          <pluginRepository>
                  <id>repo.edorasware.com</id>
                  <url>https://repo.edorasware.com/edoras-repo</url>
          </pluginRepository>
  </pluginRepositories>

Add the repository credentials to the servers section in your local Maven configuration file. By default you can find the Maven configuration file at <USER_HOME>/.m2/settings.xml.

Add this block to the settings file
  <servers>
      <server>
          <id>repo.edorasware.com</id>
          <username>customer-username</username>
          <password>customer-password</password>
      </server>
  </servers>

Additional details of how to configure a Maven repository can be found on the Maven project page.

Gradle repository configuration

The Gradle repository configuration will typically be located in the build.gradle file. The following snippet shows the configuration for the edoras repository. The configuration for your local repository will look similar.

Repository configuration in build.gradle for Gradle builds
  repositories {
    mavenLocal()
    maven {
      credentials {
        username DOWNLOAD_REPO_USERNAME
        password DOWNLOAD_REPO_PASSWORD
      }
      url "https://repo.edorasware.com/edoras-repo"
    }
    mavenCentral()
  }

Add the credentials that you received from edorasware to your local gradle.properties file. By default you can find the Gradle configuration file at <USER_HOME>/.gradle/gradle.properties.

Add this block to the gradle.properties file
  DOWNLOAD_REPO_USERNAME=customer-username
  DOWNLOAD_REPO_PASSWORD=customer-password
edoras one dependency configuration

The edoras one artifacts can now be added to the project as a dependency.

Maven dependency configuration

By adding a property to the <properties> tag of the Maven pom.xml file the edoras one version can be set in a single place:

edoras one version property in the Maven pom.xml
  <properties>
          <com.edorasware.one.version>@projectVersion@</com.edorasware.one.version>
  </properties>

This property can then be used in the dependency configuration to import the required dependencies:

edoras one dependencies in the Maven pom.xml
  <!-- Compile dependencies -->
  <dependency>
          <groupId>com.edorasware.one</groupId>
          <artifactId>edoras-frontend</artifactId>
          <version>${com.edorasware.one.version}</version>
  </dependency>

  <dependency>
          <groupId>com.edorasware.one</groupId>
          <artifactId>edoras-one-server-rest</artifactId>
          <version>${com.edorasware.one.version}</version>
          <exclusions>
                  <!-- TODO fix for https://issues.apache.org/jira/browse/BATIK-1038 -->
                  <exclusion>
                          <groupId>org.apache.xmlgraphics</groupId>
                          <artifactId>batik-extensions</artifactId>
                  </exclusion>
          </exclusions>
  </dependency>
  <dependency>
          <groupId>com.edorasware.license</groupId>
          <artifactId>edoras-license-one</artifactId>
          <classifier>development</classifier>
          <version>1.0.7</version>
  </dependency>
Gradle dependency configuration

By adding a property to the <properties> tag of the Gradle build.gradle file the edoras one version can be set in a single place:

edoras one version property in the Gradle build.gradle
  def edorasOneVersion = '@projectVersion@'

This property can then be used in the dependency configuration to import the required dependencies:

edoras one dependencies in the Gradle build.gradle
  compile "com.edorasware.one:edoras-frontend:$edorasOneVersion"
  compile("com.edorasware.one:edoras-one-server-rest:$edorasOneVersion")

  compile "com.edorasware.one:edoras-one-index:$edorasOneVersion"

  testCompile "com.edorasware.one:edoras-test:$edorasOneVersion"
  testRuntime "com.edorasware.license:edoras-license-one:1.0.7:development"
Database dependency configuration

In addition to the edoras one dependencies, at least one database dependency is also required, e.g.:

Database dependencies in pom.xml for Maven builds
  <dependency>
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
          <version>1.4.194</version>
  </dependency>
Database dependencies in build.gradle for Gradle builds
  compile "com.h2database:h2:1.4.194"
Logging dependency configuration

edoras one uses the Simple Logging Facade for Java (SLF4J) for logging. SLF4J is a framework that allows the end user to plug in the desired logging framework at deployment time. You can learn more about slf4j on the {slf4j-page}.

Maven dependency configuration

By adding a property to the <properties> tag of the Maven pom.xml file the slf4j version can be set in a single place:

Logging version property in the Maven pom.xml
  <org.slf4j.version>1.7.25</org.slf4j.version>

This property can then be used in the dependency configuration to import the required dependencies. The following dependencies instruct SLF4J to send all logging output from components used in edoras one to slf4j:

Basic logging dependencies in pom.xml for Maven builds
  <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>jul-to-slf4j</artifactId>
          <version>${org.slf4j.version}</version>
  </dependency>

  <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>jcl-over-slf4j</artifactId>
          <version>${org.slf4j.version}</version>
  </dependency>

  <dependency>
          <artifactId>commons-logging</artifactId>
          <groupId>commons-logging</groupId>
          <version>1.2</version>
          <scope>provided</scope>  <!-- globally replace commons-logging with jcl-over-slf4j -->
  </dependency>

A suitable adapter can then be configured to send the slf4j output to a particular logging system. Foe example we can include the slf4j-to-log4j adapter:

Logging adapter in pom.xml for Maven builds
  <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>${org.slf4j.version}</version>
  </dependency>
Gradle dependency configuration

By adding a property to the <properties> tag of the Gradle build.gradle file the slf4j version can be set in a single place:

Logging version property in the Gradle build.gradle
  def slf4jVersion = '1.7.25'

This property can then be used in the dependency configuration to import the required dependencies. The following dependencies instruct SLF4J to send all logging output from components used in edoras one to slf4j:

Basic logging dependencies in the Gradle build.gradle
  runtime "org.slf4j:jul-to-slf4j:$slf4jVersion"
  runtime "org.slf4j:jcl-over-slf4j:$slf4jVersion"

  // globally replace commons-logging with jcl-over-slf4j
  providedRuntime "commons-logging:commons-logging:1.2"

A suitable adapter can then be configured to send the slf4j output to a particular logging system. For example to use log4j, so we include the slf4j-to-log4j adapter:

Logging adapter in the Gradle build.gradle
  runtime "org.slf4j:slf4j-log4j12:$slf4jVersion"

8.2.2. License file

To start edoras one you will need a valid edoras one license file. The license location is defined by the system.license-location property.

8.2.3. Build and deploy the WAR file

The project WAR file can now be built using the Maven package target or the Gradle war task. The generated war can then be deployed in a suitable application server.

8.3. Configuring edoras one

edoras one is configured using Spring Java configurations. For details of the Spring project, please refer to the {spring-page}.

The basic configuration is provided by the edoras one artifacts and can be reused, although it can be customized in a number of ways:

8.3.1. Additional Spring configurations

To add your own Spring configuration to the application context, simply add your configuration class to the package com.edorasware.config.custom and annotate it with the standard Spring annotation @Configuration:

  @Configuration
  public class BootstrapConfiguration {

      // custom configuration

  }

This is simply a plain Spring configuration file and configurations can be added using the standard Spring functionality. In this case we also import additional indexing configurations (provided by edoras one) and configure an additional component scan.

Project-specific beans can be added directly to this configuration in the standard way:

  @Bean
  public StaticReferenceDataManager staticReferenceDataManager() {
      List<String> countries = new ArrayList<>();
      countries.add("Switzerland");
      countries.add("Swaziland");
      countries.add("Spain");

      return new StaticReferenceDataManager(countries);
  }

In addition to defining new project-specific Spring configurations and beans, the functionality of the edoras one product can also be extended. The extension points in the public Java API are marked in the Javadoc by the @ExtensionPoint annotation. For each extension point, the Javadoc should contain basic instructions on how the extension point can be used. A summary of each extension point together with specific use case information is provided in the section Customizing edoras one.

8.3.2. Property settings

Properties have default values provided by edoras one and these can be overwritten by adding property definitions to one of the following locations:

  • an application.properties (as a resource in the project root package)

  • a custom property file location set by the property system.custom-properties

  • the one.properties file in the edoras-one.home location

  • system properties

Properties defined later in this list have priority (so a system property setting has precedence over a property setting in the application.properties file).

8.3.3. Configuration customization

The default edoras one configurations can be customized directly for specific supported use cases using the ConfigurationConfigurer implementations in the project-specific configuration. Each part of the base configuration that supports customization provides a specific implementation of the ConfigurationConfigurer interface. For example the property configuration can be customized using the PropertyConfigurationConfigurer.

To customize a given part of the base configuration, simply declare a bean with the correct interface, and implement the configure() method. The builder parameter to this method provides an API that supports the available customizations. In this example we customize the property configuration to add an additional blacklisted property name:

  @Bean
  public PropertyConfigurationConfigurer propertyConfigurationConfigurer() {
      return new PropertyConfigurationConfigurer() {
          @Override
          public void configure(PropertyConfigurationBuilder builder) {
              builder.addBlacklistedPropertyNames("secret");
          }
      };
  }
These bean declarations can usually be expressed more concisely using Java 8 lambda expressions.

8.3.4. Overriding edoras one bean definitions

Generally, the officially supported mechanisms should be used to extend or modify the application for a particular use case. From time to time the supported mechanisms may be insufficient, however, and in this case it may be necessary to overwrite bean definitions from the base configuration directly. Doing so is not supported and may break without notice when upgrading to a newer edoras one version.

The default edoras one Spring bean configurations can be overridden if a new Spring bean is defined with the same ID as the base configuration (if two bean definitions have the same ID then the last definition wins). The bean ID in the case of Java configuration is the method name used to create the bean, so simply copy the bean creation method from the base configuration and replace it with the implementation that you require.

Note that application-specific configurations will be loaded last by default. If you need to control the order in which configurations are loaded then you can use the @Order annotation on the configuration class.

8.4. Configuring edoras vis

The edoras vis configuration is optional as the defaults should be sufficient for most project. If you still need to change the palette or adapt the edoras vis editor then please read on.

8.4.1. Palette configuration

Palette configuration should be added into the project’s Spring configuration as shown below.

  <bean id="paletteConfiguration" class="com.edorasware.bpm.modeler.config.PaletteConfiguration">
      <property name="paths">
          <list>
              <value>classpath:com/edorasware/vis/palette</value>
          </list>
      </property>
      <property name="baseProcessPalette" value="classpath:com/edorasware/vis/palette/base.process.palette.xml"/>
      <property name="baseFormPalette" value="classpath:com/edorasware/vis/palette/base.form.palette.xml"/>
      <property name="baseCasePalette" value="classpath:com/edorasware/vis/palette/base.case.palette.xml"/>
      <property name="defaultProcessPaletteName" value="default.process.palette.xml"/>
      <property name="defaultFormPaletteName" value="default.form.palette.xml"/>
      <property name="defaultCasePaletteName" value="default.case.palette.xml"/>
  </bean>
Table 90. Supported palette configuration bean properties
Name Description

paths

List of palette folder paths

baseProcessPalette

Fully qualified base process palette file name

baseFormPalette

Fully qualified base form palette file name

baseCasePalette

Fully qualified base case palette file name

defaultProcessPaletteName

Fully qualified default process palette file name

defaultFormPaletteName

Fully qualified default form palette file name

defaultCasePaletteName

Fully qualified default case palette file name

8.4.2. Editor configuration

Editor configuration should be added into the project’s Spring configuration as shown below.

  <bean id="editorConfiguration" class="com.edorasware.bpm.modeler.config.EditorConfiguration">
      <property name="disableSaveDialog" value="true"/>
      <property name="showSystemFormPalette" value="false"/>
      <property name="showSystemProcessPalette" value="false"/>
      <property name="showSystemCasePalette" value="false"/>
      <property name="saveNotificationUrl" value="../rest/modeler"/>
  </bean>
Table 91. Supported editor configuration bean properties
Name Description

disableSaveDialog

Flag to enable or disable showing the save dialog for each save operation

showSystemFormPalette

Flag to show/hide system form palette in the form designer

showSystemProcessPalette

Flag to show/hide system process palette in the process designer

showSystemCasePalette

Flag to show/hide system case palette in the case designer

saveNotificationUrl

URL to which the save notification will be posted

8.5. Work object API

The edoras one runtime environment uses a unified representation for all workflow items (e.g. cases, tasks, processes) that is accessed through the work object API. The work object API has a number of aspects:

Multi-tenant

A single edoras one server can support multiple tenants. A tenant is a separate, self-contained partition of the persistence layer where the work objects for a particular group of users are stored. A user is assigned to a particular tenant, and normally only work objects within that tenant will be accessible.

Persistence and transactions

Work objects are backed by a transactional JDBC persistence layer. All work object operations should be carried out within a valid JDBC transaction. A work object is a collection of persistent values that may have a limited range of types (see the Javadoc for the package com.edorasware.api.value). Some values are predefined and are common to all work objects, but a work object can also contain any number of additional type-specific or use-case specific values.

Hierarchical organisation

Work objects are organised in a tree hierarchy, where a work object may either be unattached or have a single parent work object. Work object operations can make use of this hierarchy information, e.g. to search for all open tasks within the scope of a given case or find the top-most parent process for a given work object.

Provider-based architecture

The provider architecture used by the work object framework allows edoras one to integrate with external systems. For example edoras one has providers that integrate with the Flowable process engine, mirroring process executions and user tasks to work objects in edoras one. Work objects can be manipulated and searched for using a single API regardless of the provider that is responsible for managing them.

Work object definitions

A work object can either be created from scratch on an ad-hoc basis by application code, or it can be created from a work object definition which acts as a template for the work object and its behaviour. Work object definitions are normally created from the models in an App when that App is deployed.

As an example, when a process work object is created with a reference to a particular process definition the relevant provider will be notified and can perform other actions in response to the work object creation, in this case starting a new process execution in the Flowable process engine.

Once a work object has been created, it keeps a reference to the definition that it was created from, so the behaviour of the work object will normally remain unchanged even if the App is redeployed to create an updated definition.

Lifecycle listeners

The work object framework also supports the use of listeners for work object lifecycle events (such as state changes or changes to the values stored in a work object). These listeners can either be used to simply respond to particular changes or may actively modify the changes that will be made to the work object before they are persisted.

8.5.1. Work object structure

A work object is a unit of data persistence, which has a collection of values, some of which are common to all work objects and some of which are used only by specific work object types or even specific instances. The common values generally have specific accessor methods in addition to being accessible through the generic value access interfaces.

Among the values stored on a work object are IDs used to identify the work object in a particular context, or to identify objects related to that work object instance. The IDs used are:

Work object ID

The work object ID is unique across all tenants and systems and identifies the work object uniquely.

Tenant ID

The tenant ID identifies the tenant containing the work object. For most application code, the current user context defines the tenant to be used, and only work objects from that tenant will be accessible. The tenant ID is mainly of interest to framework code that is operating across multiple tenants.

Global ID

The global ID is only unique within the scope of a particular tenant. The same global ID may be used for work objects that represent the 'same' entity in different tenants, the . An example is a model work object, which has the same global ID for the same model on all tenants and all installations.

External ID

The external ID can be used by the work object provider to link to an external system. It is normally not of interest to application code.

Provider ID

The optional provider ID links to the provider that is responsible for managing the work object.

Definition ID

The optional definition ID links to the specific definition from which the work object is derived.

8.5.2. Working with work objects

The main starting point for working with work objects is the service WorkObjectService.

Creating work objects

Using the service interface WorkObjectService you can either create a work object directly from a definition or create a work object with all of the values that you require in memory and then persist it.

To create a new work object in memory, use the WorkObject builder method. You can also build a new in-memory work object using another work object as a template. Once the work object has been created, it can be persisted using one of the create methods on the work object service:

  WorkObject toDoTasks = WorkObject.builder()
          .type(WorkObjectTypes.CASE_TYPE)
          .name("My ToDo task list")
          .build();

  String toDoListWorkObjectId = this.workObjectService.create(toDoTasks);

A work object can also be added as a child of another work object:

  WorkObject milkTask = WorkObject.builder()
          .type(WorkObjectTypes.TASK_TYPE)
          .name("Order the milk")
          .build();

  String taskId = this.workObjectService.create(milkTask, toDoListWorkObjectId);

To base a work object on a particular definition, simply add the definition ID to the in-memory work object before it is persisted. The provider will be notified and any necessary actions performed automatically. For example starting a new process from a process definition will start a new process execution in the Flowable engine:

  WorkObject process = WorkObject.builder()
          .type(WorkObjectTypes.PROCESS_TYPE)
          .definitionId(processDefinition.getId())
          .name("Test Process")
          .build();

  String processId = this.workObjectService.create(process);
Modifying work objects

Work objects can be modified using a work object update builder. To get an update builder for a particular work object the methods createUpdateBuilder or createReadableUpdateBuilder should be used. Using an update builder, multiple changes can be made to the same work object and then persisted in a single step using the apply() method:

  WorkObjectUpdateBuilder updateBuilder =
          this.workObjectService.createUpdateBuilder(taskId);

  WorkObject updatedWorkObject = updateBuilder
          .name("Reassigned task name")
          .ownerId(newOwnerId)
          .apply();

The readable update builder also allows the current work object values to be read from the builder itself, although this incurs additional overhead when the update builder is created.

Querying for work objects

The WorkObjectService interface allows work objects to be searched for using a Predicate or Predicate. Either a specific matching work object, a list of matching work objects, or the count of matching work objects can be returned.

The easiest way to create a predicate for a particular work object value is to use the relevant constant in the WorkObjectValues class. Each value can be used directly to create predicates, with the available predicate builder methods matching the value type:

  // range comparisons for date values
  Predicate isDueThisMonth = WorkObjectValues.DUE_TIME.between(startOfMonth, endOfMonth);

  // relative comparisons for numeric values
  Predicate isHighPriority = WorkObjectValues.PRIORITY.greaterThanOrEq(8);

  // wildcard comparisons for string values
  Predicate matchesWildcardName = WorkObjectValues.NAME.like("Smi*");

Predicates can be combined through using AND/OR operators, as well as negated via the NOT operator. This can be done either using the fluent predicate API or the static helper methods in the Predicates class:

  Predicate isActive = WorkObjectValues.STATE.isActive();
  Predicate assigneeJane = WorkObjectValues.ASSIGNEE_ID.eq("jane");
  Predicate candidateUserJane = WorkObjectValues.CANDIDATE_USER_IDS.containsAnyOf("jane");
  Predicate candidateGroupAdmin = WorkObjectValues.CANDIDATE_GROUP_IDS.containsAnyOf("admin");

  // fluent API to construct AND/OR combinations of two predicates
  Predicate predicate = isActive.and(assigneeJane.or(candidateUserJane));

  // alternative API to construct AND/OR combinations of any number of predicates
  Predicate otherPredicate = Predicates.and(isActive,
          Predicates.or(assigneeJane, candidateUserJane), candidateGroupAdmin);

  // fluent API to negate a predicate
  Predicate isNotCompleted =
          WorkObjectValues.STATE.isCompleted().not();

  // alternative API to negate a predicate
  Predicate isNotAssignedToJane =
          Predicates.not(WorkObjectValues.ASSIGNEE_ID.eq("jane"));

When querying for work objects using a predicate, a SearchScope may be supplied to remove some of the normal restrictions on work object access that are imposed by the framework (for example to include work objects that are outside of the current tenant or are not normally visible to the current user:

  List<WorkObject> tenants =
          this.workObjectService.findWorkObjects(
                  WorkObjectValues.TYPE.eq(WorkObjectTypes.TENANT_TYPE),
                  SearchScope.ALL_TENANTS_NO_RESTRICTIONS);

A Query wraps a predicate to define the work objects that should be matched, but also allows for paging and ordering of the results and for some parts of the work objects to be left out if they are not required. A QueryBuilder is used to assemble a query:

  // Search for the 20 oldest active tasks, omitting variable data.

  Predicate isActivePredicate =
          WorkObjectValues.SUB_STATE.eq(WorkObjectSubState.SUB_STATE_ACTIVE);

  Query query = Query.builder()
          .predicate(isActivePredicate)
          .limit(20)
          .sorting(WorkObjectValues.CREATION_TIME.orderAsc())
          .hints(WorkObjectQueryHints.OMIT_VARIABLES)
          .build();
Query hints

The class WorkObjectQueryHints defines query hint constants. These can mostly be used directly, for example to suppress the loading of variables in the query results.

Restricting the returned variables

The RESTRICT_VARIABLES constant is a builder for hints that restrict the returned variables returned to a limited subset. In the simplest case you can just give the plain names of the variables that you want returned:

  Query query = Query.builder()
          .predicate(WorkObjectValues.ID.eq(this.workObjectId))
          .hints(WorkObjectQueryHints.RESTRICT_VARIABLES.matching("foo"))
          .build();
Constraining the returned variables using plain string names is not currently supported for List or Map variables, and may result in incorrect results (such as empty collections). The value accessor variant is therefore preferred.

You can also restrict the returned variables using value accessors.

  static final StringValue<String> FOO = newStringValue("foo");
  // ...

      Query query = Query.builder()
              .predicate(WorkObjectValues.ID.eq(this.workObjectId))
              .hints(WorkObjectQueryHints.RESTRICT_VARIABLES.matching(FOO))
              .build();

This variant will also work for value accessors that are backed by a list value (e.g. a set):

  static final ComplexValue<Set<String>> TEST_SET =
          newSetValue("testSet", String.class);
  // ...
      Query query = Query.builder()
              .predicate(WorkObjectValues.ID.eq(this.workObjectId))
              .hints(WorkObjectQueryHints.RESTRICT_VARIABLES.matching(TEST_SET))
              .build();
It is not currently possible to restrict variables if the results should contain a map value. Attempting to restrict the results using map variable accessor will result in an unrestricted query, i.e. all variables will be returned, including the required map value.
Work object values

In the simplest case, work object values can simply be set and accessed using a string for the value name:

  WorkObject task = WorkObject.builder()
          .type(WorkObjectTypes.TASK_TYPE)
          .value("foo", "bar")
          .build();

  String fooValue = task.getValue("foo", String.class);

This approach has a number of disadvantages:

  • the value type is not checked when the value is written

  • only the raw work object value types are supported (as described in the package Javadoc)

  • the type has to be explicitly given everywhere that the value is accessed

  • predicates to search for this variable must be created using verbose low-level primitives

The package com.edorasware.api.value provides a number of classes that are useful when working with work object values. The WorkObjectValues class provides typed constants for the common work object values:

  String taskName = task.getValue(WorkObjectValues.NAME);

as well as static methods to create custom typed value accessors:

  static final StringValue<String> FOO = WorkObjectValues.newStringValue("foo");

      // ...

      WorkObject task = WorkObject.builder()
              .type(WorkObjectTypes.TASK_TYPE)
              .value(FOO, "bar")
              .build();

      String fooValue = task.getValue(FOO);

The different static methods correspond to the 'raw' type that will be persisted in the work object, so newStringValue() will create a typed accessor for a String value, newLongValue() will create a typed accessor for a Long value etc.

Typed value accessors can also make use of a ValueConverter to map between an application-specific data type and one of the supported 'raw' types. For example we may want to represent airport codes in application code in a type-safe way using the following class:

  /**
   * Type-safe representation of an airport code.
   */
  public class AirportCode {
      private static final Set<String> VALID_CODES =
              ImmutableSet.of("LAX", "LHR", "ZRH", "VLC");

      private final String code;

      /**
       * Constructs a new instance.
       *
       * @param code the airport code as a string value
       * @throws IllegalArgumentException if the code is not valid
       */
      public AirportCode(String code) {
          if (!VALID_CODES.contains(code)) {
              throw new IllegalArgumentException("Invalid value: " + code);
          }
          this.code = code;
      }

      /**
       * Returns the 'raw' airport code as a string value.
       *
       * @return the airport code
       */
      public String getCode() {
          return code;
      }

      // other implementation (hashcode, equals, business logic etc.)
  }

To conveniently store airport code values in a work object we can define a suitable ValueConverter implementation:

  public class AirportCodeConverter implements ValueConverter<AirportCode, String> {
      @Override
      public String serialize(AirportCode airportCode) {
          return airportCode.getCode();
      }

      @Override
      public AirportCode deserialize(String stringValue) {
          return new AirportCode(stringValue);
      }

      @Override
      public TypeToken<String> getSerializedValueType() {
          return TypeToken.of(String.class);
      }
  }

This converter can then be used to define specific typed values and use them to access AirportCode values in a type-safe way:

  static final StringValue<AirportCode> DESTINATION =
          newStringValue("destination", new AirportCodeConverter());

      // ...

      AirportCode destination = new AirportCode("ZRH");

      WorkObject task = WorkObject.builder()
              .type(WorkObjectTypes.TASK_TYPE)
              .value(DESTINATION, destination)
              .build();

      AirportCode value = task.getValue(DESTINATION);

As well as solving the problems with restricted type support and poor type checking seen with accessing values using the plain string name, the typed value constants also allow the simple creation of type-safe query predicates directly from the application type:

  AirportCode requiredDestination = new AirportCode("VLC");
  Predicate predicate = DESTINATION.eq(requiredDestination);
in addition to the common work object values defined in WorkObjectValues some type-specific value constants are defined in separate type-specific classes (e.g. DocumentValues).

8.6. Time provider API

The current system time in edoras one is managed by the configured TimeProvider implementation. Using a time provider across the system allows changes in the system time to be simulated (for example in unit tests) without having to wait for them to elapse in real-time.

Always use time provider to get the current time instead of calling System.currentTimeMillis() or System.nanoTime(). This makes sure that the system has a consistent view of the current time everywhere.

8.7. Customizing edoras one

This section describes the extension points for common use cases. If no suitable extension point is documented for a feature that you require then contact edorasware support to find a solution.

8.7.1. Logging configuration

If we use log4j as the logging framework then the logging configuration for log4j is provided by the log4j.properties file in the root package.

Default logging configuration in log4j.properties
  # Comment this line and uncomment the following to allow log writing to a local file
  log4j.rootLogger=INFO, A
  # log4j.rootLogger=INFO, A, local.file

  log4j.appender.A=org.apache.log4j.ConsoleAppender

  log4j.appender.A.layout=org.apache.log4j.PatternLayout
  log4j.appender.A.layout.ConversionPattern=%d{ISO8601} %-5p %-85.85c - %m%n

  log4j.appender.local.file=org.apache.log4j.FileAppender
  log4j.appender.local.file.append=false
  log4j.appender.local.file.file=/tmp/edoras.log
  log4j.appender.local.file.threshold=INFO
  log4j.appender.local.file.layout=org.apache.log4j.PatternLayout
  log4j.appender.local.file.layout.ConversionPattern=%-5p %c: %m%n

  ## Quieten distracting noise
  log4j.logger.org.springframework=WARN
  log4j.logger.com.edorasware.commons.core.maintenance.internal.jdbc.JdbcMaintenancePersistence=WARN

  ## Spring integration
  #log4j.logger.org.springframework.integration=DEBUG

  ## Spring web
  #log4j.logger.org.springframework.web=DEBUG

  ## Project
  #log4j.logger.com.edorasware.customer.acme=DEBUG

If an alternative logging configuration is needed in a given environment, this can be specified without rebuilding the WAR file by setting the appropriate system property when the application server is started, for example by adding -Dlog4j.configuration=file:C:/tmp/log4j.properties to the application server command line.

8.7.2. Database configuration

You can specify an alternative data source by declaring a PersistenceConfigurationConfigurer bean in your application’s Spring configuration.

The builder supplied to this bean’s configure() method allows the application data source and transaction manager to be defined. It is also possible to set a separate data source and transaction manager for database schema manipulation. This can be used environments where the default database connection does not have permissions to modify the database schema.

8.7.3. Web security configuration

The application web security can be configured using the following two extension points:

8.7.4. Mail server integration

edoras one can be configured to send mail using an external SMTP server by setting the relevant system properties as described in the edoras one Operator Guide. No additional Spring configuration is required.

If you want to configure a completely different mail sender implementation then you should use a MailConfigurationConfigurer bean declaration.

8.7.5. Tenant initialization

To use edoras one, you also need to create a tenant. An edoras one installation may support multiple tenants using a single database, where each tenant is completely isolated from the others (i.e. it has its own set of users, work objects, Apps etc.).

On startup, edoras one looks for tenant JSON configuration files in the locations configured by the system.tenant-cfg-location property. By default this will be the resource folder /com/edorasware/config/custom/tenant on the server’s classpath. If a configuration file is found for a tenant not already present in the database then that tenant will be initialised according to the tenant configuration file, e.g.:

Tenant initialization in acme.json
  {
      "name": "acme",

      "accounts": [
          {
              "name": "acme",
              "domain": "acme.com",
              "groups": [ "Manager" ],
              "users": [
                  {
                      "firstName": "John",
                      "lastName": "Smith",
                      "login": "john",
                      "email": "john.smith@acme.com",
                      "memberGroups": [ "Manager" ],
                      "language": "en"
                  }
              ]
          }
      ]
  }

Once a tenant is initialised it will not be updated, even if the tenant configuration file is changed at a later date.

For a full description of the tenant JSON format, please refer to the edoras one Administrator Guide.

8.7.6. Preinstalled Apps

Pre-installed Apps can be automatically installed into all tenants on the system by adding the ZIP files to the resource folder com/edorasware/config/custom/app in the application classpath. The location for pre-installed Apps can be changed using the system property apps.import.custom-location. If the system is started with a new version of a pre-installed App then the App will be updated automatically as long as this doesn’t conflict with changes on the local system.

For more information on working with Apps please refer to the section on <app-workflows>.

8.7.7. Content storage

In addition to the work object storage, edoras one also uses a content storage for work object attachments, document content etc. The content storage can be configured using standard system properties as described in the edoras one Operator Guide.

8.7.8. Action event listeners

The work object service notifies the rest of the application about changes to a work object via work object action listeners which are invoked whenever a work object is modified or its status is changed. Action listeners implement the interface AnyWorkObjectActionListener and declare two methods:

  • the actionWillBePerformed() method is invoked before the action is performed and the listener can modify the planned changes using the modification builder before they are written to the database

  • the actionPerformed() method is invoked after the changes have been written to the database

In both cases the event parameter passed into this method contains a description of the changes being made, which can be interpreted by the listener implementation as required.

Custom work object action event listeners can be added by implementing a class that implements the required interface, e.g.:

  package com.edorasware.acme.listeners;

  import com.edorasware.commons.core.any.support.AnyWorkObjectActionEvent;
  import com.edorasware.commons.core.any.support.AnyWorkObjectActionListener;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;

  import static com.edorasware.api.workobject.WorkObjectTypes.TASK_TYPE;

  public class LoggingTaskActionListener implements AnyWorkObjectActionListener {
      private static final Logger LOG =
              LoggerFactory.getLogger(LoggingTaskActionListener.class);

      @Override
      public void actionWillBePerformed(AnyWorkObjectActionEvent event) {
          if (!event.isEventForType(TASK_TYPE)) {
              return;
          }

          if (event.isCreationEvent()) {
              LOG.info("About to create task {}", event.getNewWorkObject().getId());
          }
      }

      @Override
      public void actionPerformed(AnyWorkObjectActionEvent event) {
          if (!event.isEventForType(TASK_TYPE)) {
              return;
          }

          if (event.isCreationEvent()) {
              LOG.info("Created task {}", event.getNewWorkObject().getId());
          }
      }
  }

and declaring a corresponding listener bean in the application’s Spring configuration file, e.g.:

  @Bean
  public LoggingTaskActionListener loggingTaskActionListener() {
      return new LoggingTaskActionListener();
  }

By default custom listeners declared in this way will have lowest precedence, so they will be executed after any built-in listeners have been executed. If the order of execution is important then this can be controlled using the standard Spring @Order annotation on the bean declaration method.

8.7.9. Automatic App updates

When a new tenant is initialized an App called the System App is automatically installed. This App contains the models required for correct operation of the edoras one software, and is typically loaded from the edoras one artifacts as it is strongly tied to a specific edoras one release.

It is strongly recommended that the System App be updated automatically to make sure that the latest version is active after the edoras one dependency has been updated to a newer version (which may also include a new System App).

Section Defining App development workflows describes how to configure workflows to support transfer of Apps between systems with automatic updates, and the section [incoming-adapter-lifecycle] describes how the pre-defined system app adapter can be configured to perform automatic updates of the System App.

8.7.10. Expressions and service beans

The powerful expression resolver used in the edoras one server supports access to arbitrary Spring bean property values and methods. This capability can be used to integrate custom Java code with process models via expressions: service beans can be written in Java and registered with the expression resolver, and the appropriate methods can then be invoked from a process model at the appropriate time. There are many potential ways to use this capability, but some typical use cases might be:

  • data initialization

  • data conversion

  • encapsulation of complex business logic

  • integration with external systems

Defining service beans

Service beans are simply plain Java objects registered as a Spring bean with a particular ID.

As an example, if we want to create a service to generate new task names, we can create the Java class:

TaskNameService.java
  package com.edorasware.acme.expression;

  import com.edorasware.api.expression.ExpressionBean;
  import java.util.concurrent.atomic.AtomicInteger;

  /**
   * An example service bean that allows unique task names to be created.
   */
  @ExpressionBean
  public class TaskNameService {

      protected static AtomicInteger taskCount = new AtomicInteger();

      /**
       * Returns a new task name based on the given base name.
       *
       * @param baseName the base name
       * @return the task name
       */
      public String nextTaskName(String baseName) {
          return baseName + "-" + taskCount.incrementAndGet();
      }
  }

and use this to create a corresponding Spring bean with a suitable ID, either explicitly:

  @Bean
  public TaskNameService taskNameService() {
      return new TaskNameService();
  }

or by adding an appropriate Spring annotation (e.g. @Service) to the class definition and enabling the Spring component scan for the relevant package:

  @ComponentScan("com.edorasware.acme")

To allow open access to all available Spring beans from a process expression would be a big security issue, so edoras one only allows the expression resolver to access only a limited set of beans. A specific bean can be enabled for expressions by adding the @ExpressionBean annotation to the bean class.

Accessing service beans

Once the bean has been defined and made accessible, it can be used by expressions within process definitions. As an example we can use the taskNameService bean to generate task names for user tasks:

serviceBean
Passing values using method parameters

The simplest way to pass values to a service bean method is to simply use the expression to provide the relevant values to the method call. We used this approach in the previous example when we passed in the name of the parent case:

Method invocation with method parameters
  #{taskNameService.nextTaskName(case.name)}

This approach has a number of advantages:

  • the input values are modeled, and it is therefore relatively easy for the modeler to understand what is happening

  • the same method may be used in different contexts where the source values come from different places

  • changes to variable names can be made without affecting running processes (old processes will continue to use the old variable name)

It works well for simple utility function when only a few parameters are required, but as the number of parameters increases, the method invocations become complex and therefore awkward to write and maintain.

Passing values using the execution context

For more complex use cases, an alternative is to provide the current Activiti execution context as a parameter to the service task method and allow the method itself to extract the information it needs and make any changes that may be required. When doing this, it is useful to extend the AbstractActivityService class, as this provides a number of useful utility methods for working with execution context, such as locating the current work object. The following example service uses the execution context to add a message to a variable in the root work object:

AcmeService.java
  /**
   * An example service bean that uses an execution context.
   */
  @Service
  @ExpressionBean
  public class AcmeService extends AbstractActivityService {

      // type-safe variable definition for the service message
      public static final StringValue<String> SERVICE_MSG = newStringValue("serviceMsg");

      public AcmeService() {
          super(false);
      }

      /**
       * Adds a service invocation message to the root work object.
       *
       * @param execution the execution context
       */
      public void invoke(DelegateExecution execution) {
          AnyWorkObject workObjectInScope = getWorkObjectInScope(execution);
          AnyWorkObject rootObject = getRootCase(workObjectInScope);

          WorkObjectUpdateBuilder updateBuilder =
                  getWorkObjectService().createUpdateBuilder(rootObject.getId());

          String message = "AcmeService was invoked at " + getTimestamp()
                  + " with tag " + getTag(execution);

          updateBuilder.value(SERVICE_MSG, message);

          updateBuilder.apply();
      }

      /**
       * Returns the value of the tag property in the task definition.
       *
       * @param execution the execution context
       * @return the value of the tag property
       */
      protected String getTag(DelegateExecution execution) {
          Map<String, String> properties = getEdorasPropertyMapForCurrentActivity(execution);
          String value = properties.get("tag");
          return hasText(value) ? value : "UNDEFINED";
      }

      /**
       * Returns a string with the current timestamp.
       *
       * @return the current timestamp
       */
      protected String getTimestamp() {
          DateTimeFormatter dateFormat =
                  DateTimeFormatter
                          .ofPattern("yyyy-MM-dd hh:mm")
                          .withZone(ZoneId.of("UTC"));

          return dateFormat.format(Instant.now());
      }
  }

The execution context is passed into the method call by using the execution keyword within the expression:

Method invocation with execution context
  #{acmeService.invoke(execution)}

This approach delegates full control to the service implementation, allowing it to navigate the work object hierarchy to read or modify whatever it needs to. Obviously, this is very powerful, but it also means that the values used by the method are not visible to the modeler, making it hard to see what is really going on. It is therefore important to try to make the behaviour as intuitive as possible and to provide good documentation for the available services to the modelers.

As the data used by the implementation is coded in Java rather then being part of the model, it is also more complicated to change the way that values are stored in the work object hierarchy. Any change to the values used by the service will take effect immediately for all processes that use that service in the future, including processes that are already running.

Managing database transactions in service beans

Service bean method invocations are typically executed from within a process. The process engine already manages the transactions used during process execution, and so no additional transaction handling needs to be provided by service bean implementations.

Security

As service beans have access to the full functionality of Java and edoras one, it is also important that security is considered when creating a new service bean implementation. Users should not be able to use a service bean to gain access to confidential information to which they would not otherwise have access, to corrupt or delete information, or to interfere with the normal functioning of edoras one.

Creating custom service tasks in the process palette

We have already seen how service beans can be invoked using expressions. When specific service beans are used on a regular basis, it may be convenient to extend the process palette in the process modeler to include customized service tasks for common use cases.

Details of how to customize the process palette can be found in the section [customizing-palettes].

As an example, we start by creating a patch to the default edoras one process palette (thereby reusing all of the existing palette configuration):

acme.process.palette.xml
  <palette id="acme-process-palette"
           resource-bundle="translation"
           apply-patch-to-palette="edoras-one-process-palette"
           xmlns="http://www.edorasware.com/schema/vis/palette"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.edorasware.com/schema/vis/palette http://www.edorasware.com/schema/vis/edoras-vis-process-palette-2.0.58.xsd">

      <!-- palette configuration... -->
  </palette>

To make our custom tasks easy to find, we will create a separate group to contain them:

acme.process.palette.xml
  <group id="acme-tasks">
      <component id="acmeservicetask" extends="ServiceTask"
                 attribute-groups="acmeServiceTaskAttributes"/>
  </group>

In the process modeler, this group is now added to the existing ones:

acme group

We can then define the attributes that should appear when the service task is edited. For our example, we will provide a default name and background color, set the expression to invoke the service (not visible in the modeler), define a new tag attribute, and suppress some of the additional service task attributes that are not needed:

acme.process.palette.xml
  <attribute-groups>
      <attribute-group id="acmeServiceTaskAttributes">

          <!-- Provide suitable default values for base attributes -->
          <attribute category="common" id="name" type="SimpleText"
                     value="ACME service task"
                     readonly="false" optional="true"
                     ref-to-view="text_name"/>
          <attribute id="bgcolor" category="common" type="Color"
                     value="#ccffcc" index="190"
                     readonly="false" optional="false"
                     ref-to-view="fill_el" fill="true" stroke="false"/>

          <!-- use a fixed expression to invoke the service -->
          <attribute id="expression" category="edoras" type="SimpleText"
                     value="#{acmeService.invoke(execution)}"
                     readonly="true" optional="false" visible="false"/>

          <!-- add a custom attribute that we can access in the service -->
          <attribute id="tag" category="edoras" type="SimpleText"
                     value="default" export="true"
                     readonly="false" optional="false"/>

          <!-- suppress attributes that aren't needed -->
          <attribute id="delegateExpression" category="edoras" type="SimpleText"
                     value=""
                     readonly="false" optional="true" visible="false"/>
          <attribute id="resultVariable" category="edoras" type="SimpleText"
                     value=""
                     readonly="false" optional="true" visible="false"/>
          <attribute id="class" category="edoras" type="SimpleText"
                     value=""
                     readonly="false" optional="true" visible="false"/>

      </attribute-group>
  </attribute-groups>

Note that the tag attribute is marked as 'exported', meaning that it will be added to the final task definition as a property, where it can be accessed by the service bean. The resulting definition property key has the edoras: prefix to avoid possible collisions with other properties used in the process engine.

The display strings used in the modeler are supplied by the corresponding resource bundle, allowing them to be translated:

translation.properties
  acme-tasks.title = ACME tasks
  acmeservicetask.title = ACME service task
  acmeServiceTaskAttributes.tag.title = Tag
  acmeServiceTaskAttributes.tag.description = Tag

When we add the custom task to a process in the modeler, we can see that the default attribute values are applied, and that some of the normal service task attributes are no longer available:

acme attributes

8.7.11. REST services

Custom REST API

To add your own REST API, you first need to define your own servlet context. This can be done by providing an implementation of the CustomWebApplicationInitializer interface in a sub-package of com.edorasware.config.custom:

  public class AcmeWebApplicationInitializer implements CustomWebApplicationInitializer {

      @Override
      public void preConfigureServletContext(ServletContext servletContext,
                                             WebApplicationContext rootContext)
      {
          AnnotationConfigWebApplicationContext servletAppContext =
                  new AnnotationConfigWebApplicationContext();
          servletAppContext.setParent(rootContext);
          servletAppContext.register(AcmeDispatcherConfiguration.class);

          DispatcherServlet dispatcherServlet = new DispatcherServlet(servletAppContext);
          ServletRegistration.Dynamic oneRegistration =
                  servletContext.addServlet("acme dispatcher", dispatcherServlet);

          oneRegistration.setLoadOnStartup(1);
          oneRegistration.addMapping("/acme/*");
      }

      @Override
      public void postConfigureServletContext(ServletContext servletContext,
                                              WebApplicationContext webApplicationContext) {
      }

      @Override
      public void postConfigureServletFilters(ServletContext servletContext,
                                              WebApplicationContext webApplicationContext) {
      }
  }

This specifies a request mapping context of "/acme" and also registers the dispatcher configuration class. This configuration contains a single controller, created explicitly rather than using a component scan:

  @EnableWebMvc
  @Configuration
  public class AcmeDispatcherConfiguration extends WebMvcConfigurerAdapter {

      @Bean
      public AcmeController acmeController() {
          return new AcmeController();
      }
  }

The controller is a standard REST controller implementation:

  @RestController
  public class AcmeController {

      @RequestMapping(value = {"/acme-test"}, method = RequestMethod.GET)
      @ResponseBody
      public String hello(@RequestParam(required = false, defaultValue = "World") String name) {
          return "Hello, " + name + "!";
      }
  }

The resulting REST endpoint will then be accessible under the URL acme/acme-test under the server root URL.

Custom REST API security

By default, custom REST endpoints defined as shown above will use the default security of the edoras one server. This is generally fine for endpoints that are accessed by forms, as the user must be logged in to access the form.

If you need an alternative security configuration, you simply need to define this in a separate configuration class:

  @Configuration
  @Order(Ordered.HIGHEST_PRECEDENCE)
  public class AcmeWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

      @Autowired
      protected UserDetailsService userDetailsService;

      @Autowired
      protected PasswordEncoder passwordEncoder;

      @Override
      public void configure(WebSecurity web) throws Exception {
      }

      @Override
      protected void configure(final HttpSecurity httpSecurity) throws Exception {
              httpSecurity
                      .antMatcher("/acme/**")
                      .authorizeRequests()
                      .antMatchers(HttpMethod.OPTIONS, "/acme/**").permitAll()
                      .antMatchers("/acme/**").authenticated()
                      .and()
                      .httpBasic()
                      .and()
                      .sessionManagement().sessionFixation().none()
                      .and()
                      .csrf().disable();
      }

      @Override
      protected void configure(final AuthenticationManagerBuilder authenticationManagerBuilder)
              throws Exception
      {
          authenticationManagerBuilder
                  .userDetailsService(userDetailsService)
                  .passwordEncoder(passwordEncoder);
      }
  }
This configuration has the highest priority order set so that it has precedence over the default security config, as the default security config defines the security context for all URLs under the server root.
Customizing the public REST API

The public REST API servlet Spring configuration can be customized by:

Additional REST controllers can be added to the public REST API servlet by:

  • placing the controller class in a com.edorasware sub-package

  • annotating the class with @ApiController instead of @RestController

Managing database transactions in REST services

edoras one uses Spring Transaction Management to manage transactions.

If your REST controller methods access a database then you should add the appropriate Spring transaction annotations so that Spring can correctly manage the transactions.

You can either add the annotations to the REST controller methods directly, or to classes invoked by the REST controller.

The recommended pattern is to delegate the business logic for the REST endpoint to a separate class and annotate that class with the appropriate transaction annotations. Using this pattern, exceptions from the business logic will result in the transaction being rolled back before control returns to the REST controller, which is then free to reply to the client in any way that it likes. If transaction annotations are added directly to the REST controller then the REST controller must itself throw an exception to force a rollback of the transaction. If this is not done then partial changes may be committed inadvertently.

Wherever the annotations are added, it is important that the scope of the annotated methods is sufficient for all related operations to be grouped correctly within a single transaction.

As an example, the REST controller for the reference data service delegates calls to a ReferenceDataManager implementation:

DatabaseReferenceDataManager.java
  /**
   * Manages reference data using persistent database storage.
   */
  public class DatabaseReferenceDataManager implements ReferenceDataManager {

      @Override
      @Transactional(readOnly = true)
      public List<Domain> getDomains(String typedText) {
          // ...
      }

      // ...

Note that only the database-driven implementation needs to be annotated in this way. The alternative StaticReferenceDataManager implementation used for testing is driven by static data and therefore does not need any transaction annotations.

Supporting edoras form REST-based widgets

The REST APIs needed to support specific form widgets in edoras one are described in detail in the edoras one Modeler Guide.

The Dynamic Link Button widget requires a REST endpoint with a specific response (see the edoras one Modeler Guide for details). To simplify the implementation of REST endpoints to support this widget, a Java class is provided that directly supports this response (NavigationResponse):

NavigationController.java
  // ...

  /**
   * Create a navigation response for the next (oldest) task.
   *
   * @return the navigation response or NOT_FOUND if no task is available
   */
  @RequestMapping(value = "/navigation/nextTask", method = RequestMethod.GET)
  @ResponseBody
  public ResponseEntity<NavigationResponse> getNextTask() {
      LOG.debug("Requesting next task navigation");

      Query query = Query.builder()
              .predicate(WorkObjectValues.TYPE.eq(TASK_TYPE).and(WorkObjectValues.STATE.isActive()))
              .sorting(WorkObjectValues.CREATION_TIME.orderDesc())
              .limit(1)
              .build();

      AnyWorkObject task = this.anyWorkObjectService.findWorkObject(query);
      if (task == null) {
          return new ResponseEntity<>(HttpStatus.NOT_FOUND);
      }

      NavigationResponse response = NavigationResponse.get(task, ViewName.BROWSE);
      return new ResponseEntity<>(response, RestUtils.JSON_HTTP_HEADERS, HttpStatus.OK);
  }

8.7.12. Message bundles

The server-side message bundles can be extended or patched by providing a suitable I18NConfigurationConfigurer bean declaration:

  @Bean
  public I18NConfigurationConfigurer acmeI18NConfigurationConfigurer() {
      return (configurationBuilder) -> {
          configurationBuilder.addMessageSourceBaseNames(
                  "classpath:com/edorasware/acme/i18n/messages");
      };
  }

The base names are resolved to a message bundle containing translation resources. e.g. "classpath:com/acme/i18n/messages" will correspond to the classpath resources:

  • com/acme/i18n/messages.properties

  • com/acme/i18n/messages_de.properties

  • com/acme/i18n/messages_fr.properties

  • …​

8.7.13. Custom database schema and data upgrades

The current database schema and data upgrade mechanism is based on Flyway. In edoras one we use so called upgrades to manage database schema and data changes. There are two kind of upgrades: SQL and Java data upgrades.

In the following sections we discuss each of these upgrades in detail.

SQL database schema upgrade

If you need to create a customized SQL upgrade, then create your upgrade file (with the .sql file type) with all the needed SQL statements and save it inside the com/edorasware/commons/core/persistence/schema/${databaseType} package such that edoras one is able to retrieve and execute it. The ${databaseType} needs to be one of these values and the SQL upgrade filename must have the edoras-gear_ prefix and a proper version suffix in the following format:

edoras-gear_A.B.C.X_Small_description.sql

The filename has three main parts, the prefix, the version number and a small description of the upgrade. You need to set all these three parts such that the upgrade will be executed automatically.

The version format is A.B.C.X where A, B, C and X are numbers. The first three places in the version A.B.C are reserved for the edoras one upgrades so you can use the fourth X number for your custom database schema upgrades. So a valid SQL database schema upgrade file could look like this:

/com/edorasware/commons/core/persistence/schema/h2/edoras-gear_1.0.1.1_Small_description.sql

This upgrade will be executed after the 1.0.1 upgrade from edoras one is executed and it will have Small description as description. To check which version number you need to use please have a look at the /com/edorasware/commons/core/persistence/schema/h2/ folder inside the edoras-gear-commons library and see which versions are used by edoras one.

Migration to another database

If you want to migrate for example from Oracle 11 to Oracle 12 and you have custom database schema scripts you need to follow these steps:

  1. Retrieve the database type for the new database (in the example it would be oracle12c) from these values.

  2. Next create a new package in your project for the new database at com/edorasware/commons/core/persistence/schema/${databaseType}.

  3. Then move the custom schemas from the old database package to the new one and adapt the DDL to match the new database SQL dialect.

After that you are able to run edoras one with the your custom database schema upgrades on the new database.

Java data upgrade

Besides the SQL schema upgrades we also need to upgrade data from time to time. We use the same mechanism here but we do the upgrades in Java. Here you can implement a subclass of the com.edorasware.one.upgrade.OneBaseUpgrade which has an abstract upgrade(TenantId) method which you need to implement. This method gets called when Flyway executes this upgrade and it is called for each tenant once.

You can define the class as Spring bean and use the comfort of autowiring the needed beans for the data upgrade. You just need to pass the version and the description to the super class. This is similar to the version and description part in the filename of a SQL database schema upgrade. The OneBaseUpgrade class provides you with some helper methods to easily iterate over the work objects. Please have a detailed look at the class before doing the custom upgrade such that you do not duplicate the needed logic.

8.7.14. Elasticsearch integration

Edoras one supports flexible Elasticsearch integration. Content from the edoras one database can be mirrored into one or more Elasticsearch indices and used for custom search functionality based on the Elasticsearch query API. For some queries this may be significantly faster than running equivalent queries directly against the edoras one database.

The edoras one database is the definitive data store, and the Elasticsearch index may lag behind the database slightly, as updates have to be passed from edoras one to Elasticsearch and then indexed. If a particular use case requires definitive current data then you should retrieve this from the database not the Elasticsearch index.

This section describes how the Elasticsearch integration can be configured.

Set up an Elasticsearch cluster

To set up a cluster, simply follow the instructions from the Elasticsearch web page. To get started you can just download the Elasticsearch distribution (version 5.6.3), unpack it and run the start script.

You should set the Elasticsearch cluster name to edorasone (see the config/elasticsearch.yml file in the Elasticsearch distribution).

If you want to include document content from edoras one in the index then you will also need to install the mapper attachments plugin plugin (now deprecated) or the ingest attachment plugin in the Elasticsearch cluster nodes.

For small installations the default cluster settings should be sufficient. If you need more information then please refer to one of the many good resources available on Elasticsearch cluster administration. This is a complex topic that will not be covered here.

Elasticsearch integration dependency

Once you have a cluster running, you can configure edoras one to mirror database content to the Elasticsearch index.

The first step is to add the edoras-one-index module as a dependency to your project, e.g.:

pom.xml
  <dependency>
          <groupId>com.edorasware.one</groupId>
          <artifactId>edoras-one-index</artifactId>
          <version>${com.edorasware.one.version}</version>
  </dependency>
Enable Elasticsearch

To enable the Elasticsearch integration code you need to set the search.elasticsearch.enable property to true.

Configuration properties

The properties used to configure the Elasticsearch integration (e.g. to connect to an external Elasticsearch cluster) are described in the standard property documentation in the edoras one Operator Guide.

Elasticsearch index handling

Before looking at how to configure an index to be mirrored from edoras one, we need some background information on how the edoras one Elasticsearch integration manages its indices.

Working indices and aliases

Each index has a public index name (e.g. edoras-objects) which can be used by application code to access the index and perform queries, but in fact this index name is just an alias for a 'real' working index. Working indices have the the same name but with a timestamp appended (e.g. edoras-objects-20160913111617). Thus the index structure for an active edoras one index may look like this:

index structure

There may be multiple working index copies (some of which may be inactive) but there will only be one alias.

Initial synchronization and resynchronisation

edoras one will automatically check whether a valid index is available when it is started. If an index is not found then a synchronization process will be started, copying all of the required data from the edoras one database into a new working index. When this synchronization process is complete, the alias will be created so that the new working index may be accessed. In a large database this may mean that it takes some time before the index is available.

Once the synchronization is complete and the index alias has been created, further changes to the edoras one database will automatically be mirrored to Elasticsearch.

If for some reason the Elasticsearch index is out of step with the edoras one database then a resynchronization can be performed. When resynchronizing, a new working index will be created in the background and the alias will only be switched over to the new index when the synchronisation is complete. Thus the stale index can still be used up to the point where the new index is ready.

To trigger a resynchronization of all indices, the current user should have administrator permissions and access the following URL (relative to the edoras one root context):

/rest/api/v1/maintenance/index/synchronizeAll

A specific index can be resynchronized using the following URL:

/rest/api/v1/maintenance/index/{index}/synchronize
Database reset

When the database is reset (normally this is done in a development environment) then the existing indices are obviously no longer valid. In this case both the working indices and the current alias will be deleted (unless configured otherwise) and a new index will be created.

Index configuration

The application indexing configuration can be customized using the IndexingConfigurationConfigurer extension point.

The configuration builder allows custom IndexConfiguration implementations to be registered. Each implementation defines the structure of a custom index and provides the code needed to populate it whenever the contents of edoras one are changed:

  @Bean
  public IndexingConfigurationConfigurer acmeIndexingConfigurationConfigurer(
          DocumentAdapter documentAdapter,
          AcmeIndexEntrySerializer serializer)
  {
      return builder ->
              builder.addIndexConfigurations(
                      new AcmeIndexConfiguration(documentAdapter, serializer));
  }

  @Bean
  public AcmeIndexEntrySerializer acmeIndexEntrySerializer() {
      return new AcmeIndexEntrySerializer();
  }

You can create custom index configurations that index specific parts of the edoras one database, or index only part of the information stored in each work object.

The creation of a custom Elasticsearch index is described in the following sections.

Custom indices

To configure a custom Elasticsearch index, you will need the following:

  • an Elasticsearch template file describing the JSON content of your index

  • a serialization implementation to convert edoras one work objects / definitions into index JSON documents

  • an optional deserializer and DTO class to simplify handling of JSON documents from search results

  • an index configuration defining which edoras one content should be indexed and how this should be done

  • optional utility classes to simplify access to the index (e.g. by providing shared implementations of common searches, returning DTO instances rather than raw JSON documents)

Template file

To define the template file for your custom index, please refer to the Elasticsearch documentation. The following example defines an index with a small set of work object fields:

acme-template.json
  {
    "template": "#{index.name}*",
    "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 1,
      "refresh_interval": "1s",
      "index.mapping.attachment.indexed_chars": -1
    },
    "mappings": {
      "_default_": {
        "dynamic": "strict",
        "_all": {
          "enabled": false
        }
      },
      "indexEntry": {
        "properties": {
          "id": {
            "type": "string",
            "index": "not_analyzed"
          },
          "globalId": {
            "type": "string",
            "index": "not_analyzed"
          },
          "name": {
            "type": "string",
            "index": "analyzed"
          },
          "type": {
            "type": "string",
            "index": "not_analyzed"
          }
        }
      }
    }
  }

One important point is that the template attribute contains the placeholder #{index.name} followed by a *. The placeholder will be replaced by the configured index name when the template is loaded, and the * allows this template to be used for the working indices which have the index name as prefix and a timestamp suffix. This attribute value can therefore be used in all index templates.

Index serialization / deserialization

The index configuration will need to convert the incoming work objects and definitions into corresponding JSON documents that match the configured template file. It may also be useful to provide a Java interface for working with the indexed JSON content. There are several ways that this can be achieved, but one possibility is to define a DTO class with the appropriate attributes that can be initialised from an edoras one entity and serialised to JSON using a JSON object mapper:

AcmeIndexEntry.java
  public class AcmeIndexEntry {

      @JsonProperty
      protected String id;

      @JsonProperty
      protected String globalId;

      @JsonProperty
      protected String type;

      @JsonProperty
      protected String name;

      protected AcmeIndexEntry() {
          // needed for JSON mapper
      }

      AcmeIndexEntry(WorkObject workObject) {
          this.id = workObject.getId();
          this.globalId = workObject.getGlobalId();
          this.type = workObject.getType();
          this.name = workObject.getName();
      }

      AcmeIndexEntry(Entity entity) {
          this.id = entity.getId();
          this.globalId = entity.getGlobalId();
          this.type = entity.getType();
          this.name = entity.getName();
      }
  ...

In this case the DTO is simple and only contains fields that are shared between work objects and definitions. We can therefore reuse the same DTO for all index content.

The DTO can also be initialized from a JSON document (as parsed by a JSON object mapper):

AcmeIndexEntry.java
  AcmeIndexEntry(JsonNode jsonNode) {
      this.id = jsonNode.findPath("id").asText();
      this.globalId = jsonNode.findPath("globalId").asText();
      this.type = jsonNode.findPath("type").asText();
      this.name = jsonNode.findPath("name").asText();
  }
A separate JSON object mapper with qualifier indexObjectMapper is provided by the elasticsearch integration code, and should be used for index serialization / de-serialization operations.
Custom index configuration

Custom index configurations can index all of the edoras one database or just a subset, or may index only part of the information stored in each work object. An IndexConfiguration implementation may look as follows:

AcmeIndexConfiguration.java
  public class AcmeIndexConfiguration implements IndexConfiguration {
      static final String INDEX_NAME = "acme";
      static final String DOCUMENT_TYPE = "indexEntry";

      protected final DocumentAdapter documentAdapter;
      protected final AcmeIndexEntrySerializer serializer;

      public AcmeIndexConfiguration(DocumentAdapter documentAdapter,
                                    AcmeIndexEntrySerializer serializer) {
          this.documentAdapter = documentAdapter;
          this.serializer = serializer;
      }

      // ...
Basic index setup

The IndexConfiguration interface defines a number of methods. Firstly there are some basic index setup methods (index name etc.):

AcmeIndexConfiguration.java
  @Override
  public String getIndexName() {
      return INDEX_NAME;
  }

  @Override
  public String getIndexDescription() {
      return "Acme sample index configuration";
  }

  @Override
  public Resource getTemplateResource() {
      return new ClassPathResource("acme-template.json", AcmeIndexConfiguration.class);
  }

  @Override
  public boolean deleteOnReset() {
      // if the database is reset then an existing index will also be deleted
      return true;
  }

  @Override
  public boolean requiresExplicitSynchronizationRequest() {
      // this index can be synchronized as part of a synchronizeAll operation
      return false;
  }

The migrate() method can be used to patch the template of an existing index if the template is changed at a later date. This won’t usually update the existing index information (for which a full resynchronization may be required) but it will allow the existing index to accept new JSON documents without throwing an exception. In our case we only have one template version so no migration code is required:

AcmeIndexConfiguration.java
  @Override
  public void migrate() {
      // nothing to do
  }
Indexing during normal edoras one operation

We now come to the 'normal' indexing methods that are used to mirror changes from edoras one into the index:

AcmeIndexConfiguration.java
  @Override
  public void indexWorkObject(WorkObject workObject) {
      String document = this.serializer.serialize(new AcmeIndexEntry(workObject));
      this.documentAdapter.indexDocument(
              INDEX_NAME, DOCUMENT_TYPE, workObject.getId(), document);
  }

  @Override
  public void deleteWorkObject(String workObjectId) {
      this.documentAdapter.deleteDocument(
              INDEX_NAME, DOCUMENT_TYPE, workObjectId);
  }

When a work object is created or modified, the work object will be passed to the indexWorkObject() method to be added to the index. This converts the work object to a corresponding JSON document using the serialization code described above, and adds it to the current index using the document adapter. The document adapter is just a simple wrapper around the Elasticsearch client API provided by the edoras one Elasticsearch integration code.

The indexWorkObject() method may also filter the work objects that are indexed.

work object indexing

Any work object deletions are passed to the deleteWorkObject() method so that the corresponding index entry can be removed.

A corresponding set of methods is provided to support the normal indexing of work object definitions and content manager content.

Resynchronization indexing

The resynchronization indexing process is managed by a different set of methods:

AcmeIndexConfiguration.java
  @Override
  public Optional<Predicate> getWorkObjectSynchronizationPredicate() {
      return Optional.of(Predicates.EMPTY);
  }

  @Override
  public void syncUpdateWorkObject(SyncWriter syncWriter,
                                   String workingIndexName,
                                   WorkObject workObject) {
      syncWriter.indexDocument(
              workingIndexName,
              DOCUMENT_TYPE,
              workObject.getId(),
              this.serializer.serialize(new AcmeIndexEntry(workObject)));
  }

  @Override
  public void syncDeleteWorkObject(SyncWriter syncWriter,
                                   String workingIndexName,
                                   String workObjectId) {
      syncWriter.deleteDocument(workingIndexName, DOCUMENT_TYPE, workObjectId);
  }

The getWorkObjectSynchronizationPredicate() method returns an optional predicate that is used to select the work objects that should be indexed. In this case we want to index all work objects in the system, so we return the empty predicate.

The predicates from all index configurations are combined by the framework to obtain the superset of work objects that will be synchronized. In this way each work object is only read once even though it may be needed to synchronize multiple indices. The work objects matched by the combined predicate are passed to the syncUpdateWorkObject() which should also filter the incoming work objects in the same way as normal indexing, as the combined predicate will probably return additional work objects that would not be matched by the predicate provided by the specific index configuration.

synchronization indexing

The syncUpdateWorkObject() method will contain similar code to the normal indexing method, indexWorkObject() but should update the index using the SyncWriter implementation provided. SyncWriter is optimised for the high throughput needed by index resynchronisation.

One other thing to consider in the resynchronisation code is the indexing of content manager content. For normal indexing, changes to work objects and content are handled by separate indexing methods, and so a work object index entry can be updated without having to re-index all attached content. During index synchronization there is no separate content synchronization path, so content attached to work objects should be indexed when the parent work object is indexed.

Additional index customisation

When the index is resynchronized, the customizeIndex() method will be called. This method can add additional content to the resynchronized index as required using the SyncWriter (e.g. from an external system). If you are only indexing edoras one content then nothing needs to be implemented here.

If the external content is dynamic then you may have to detect changes and add them to the index. The Elasticsearch integration framework provides no explicit support for this.

AcmeIndexConfiguration.java
  @Override
  public void customizeIndex(SyncWriter syncWriter, String workingIndexName) {
      // synchronize additional index content here
  }
Querying the Elasticsearch indices

You can use the indices that are created by the Elasticsearch integration to perform your own queries. Currently there is no specific support for this other than the Elasticsearch client API. It may be useful to create utility classes to support common queries, e.g.:

AcmeIndexSearch.java
  /**
   * Provides search functionality for the sample Elasticsearch index.
   */
  public class AcmeIndexSearch {

      @Autowired
      protected AcmeIndexEntrySerializer serializer;

      @Autowired
      protected Client elasticClient;

      /**
       * Finds a single index entry with the given ID.
       *
       * @param workObjectId the work object ID
       * @return the matching index entry
       */
      public AcmeIndexEntry findIndexEntry(String workObjectId) {
          List<AcmeIndexEntry> searchResults = findIndexEntries(idsQuery().addIds(workObjectId));
          if (searchResults.size() == 0) {
              return null;
          } else if (searchResults.size() == 1) {
              return searchResults.get(0);
          } else {
              throw new RuntimeException("Too many results for ID lookup");
          }
      }

      /**
       * Finds the index entries that match the given Elasticsearch query.
       *
       * @param query the Elasticsearch query
       * @return the macthing index entries
       */
      public List<AcmeIndexEntry> findIndexEntries(QueryBuilder query) {
          SearchResponse searchResponse =
                  this.elasticClient
                          .prepareSearch(AcmeIndexConfiguration.INDEX_NAME)
                          .setTypes(AcmeIndexConfiguration.DOCUMENT_TYPE)
                          .setQuery(query)
                          .get();

          return getSearchResults(searchResponse);
      }

      protected List<AcmeIndexEntry> getSearchResults(SearchResponse searchResponse) {
          return Arrays.stream(searchResponse.getHits().hits())
                  .map(input -> getSerializer().deSerialize(input.getSourceAsString()))
                  .collect(Collectors.toList());
      }

      protected AcmeIndexEntrySerializer getSerializer() {
          return serializer;
      }
  }

Elasticsearch query results may also be made available for use by form components using custom REST endpoints.

8.7.15. Customizing the edoras one web interface

The edoras one web interface can be customized by adding any custom Javascript code or CSS to the custom.js and custom.css files respectively. These files should be located in the root folder and will be included by the edoras one application automatically. No other changes are required to include these files.

For example we can customize the CSS to add a red box around the work item lists:

custom.css
  .thumbnailList {
     border: 1px solid red;
  }
css example

8.7.16. Customizing the edoras one UI

All templates have been merged into one (index.html) and now you can select which parts of the UI should be visible.

To activate the parameters you have to set them as 'true' or '1'

There are 2 master parameters, which you can combine:

  • emb: When true, the UI is configured in the same way of the old embedded.html

  • cmmn: When true, the UI is configured in the same way of the old case.html

A part from that, there are other available parameters:

  • hm (refers to Hide Menu): When true, the menu is not rendered.

  • hh (refers to Hide Header): When true, the header is not rendered.

  • ha (refers to Hide ActionsPane): When true, the actions pane is not rendered.

  • hvr (refers to Hide Version): When true, the version (in footer) is not rendered.

We have also available some useful methods in the api which you will find in: edoras.ui.configuration

The available methods are:

  • isEmbedded: Returns true when embedded is enable

  • isCmmn: Returns true when cmmn is enabled.

  • isPresent(x): Returns if 'x' is enabled when 'x' can be:

    • menu

    • header

    • cmmnHeader

    • viewContainer

    • ngView

    • cmmnNgView

    • version

    • actionPane

  • showActionsPane(boolean): Set the boolean value to actionPane

  • showMenu(boolean): Set the boolean value to menu

  • showHeader(boolean): Set the boolean value to header (it can be 'header' or 'cmmnHeader' depending on if cmmn is enabled)

  • showVersion(boolean): Set the boolean value to version

  • setIsEmbedded(boolean): Set the embedded configuration

  • setIsCmmn(boolean): Set the cmmn configuration

Some examples:
http://localhost:1339/?emb=true#/dashboard/user ==> Enables embedded configuration
http://localhost:1339/?hm=true#/dashboard/user ==> The menu is not rendered

8.7.17. Customizing the requested files

There are 3 parameters to manage the css and js files loaded. You can avoid the load of widgets, custom and VIS. They are loaded by default, but if you set to 'true' or '1' the right parameter you will avoid the load of them.

The available parameters are:

  • nv (refers to No Vis): When true, the js and css files of VIS won’t load

  • nw (refers to No Widgets): When true, the js and css files of Widgets won’t load

  • nc (refers to No Custom): When true, the js and css files of Custom won’t load

8.8. Customizing graphical modeler palettes

The graphical modeler allows the palette used to design processes, forms and cases etc. to be customized. One or more customized palettes of form, process or case widgets can be created by extending the generic widgets supported by default. Once created, each custom palette can be associated with one or more models of the appropriate type. When a custom palette has been associated with a model all the widgets from the palette will be available in the appropriate editor view.

A custom form palette has to be configured in an XML file that has the .form.palette.xml file extension. It should conform to the edoras-vis-form-palette XML schema definition.

A custom process palette has to be configured in an XML file that has the .process.palette.xml file extension. It should conform to the edoras-vis-process-palette XML schema definition.

A custom case palette has to be configured in an XML file that has the .case.palette.xml file extension. It should conform to the edoras-vis-case-palette XML schema definition.

8.8.1. Configuring palette locations

The locations for additional palette configurations can be set using system properties as described in the edoras one Operator Guide.

Classpath locations simplify deployment but mean that palette changes will need to be deployed by rebuilding the deployment artifact.

Filesystem locations may be system-specific but would allow palettes to be updated without rebuilding the deployment artifact. The latter may be especially useful in a development environment where palettes are being modified regularly. A filesystem location may look like this:

file:${user.home}/acme/palette

All of the custom palette XMLs located directly under the configured folder will be available and can be associated with an edoras vis model. One model can only be associated with one custom palette configuration.

If a custom palette XML is deleted or if any of its custom widgets are deleted, the widgets in models associated with that custom palette will automatically fallback to their respective generic widget parent(s) when the models are subsequently opened for editing.

8.8.2. Configuring a custom palette

The root element of a custom palette XML file supports the following attributes:

Table 92. Attributes and elements supported by the palette element
Name Mandatory Description

id

true

ID of the palette.

title

false

The title of custom palette that is displayed in edoras vis editor view.

parent-palette

false

The parent palette from which a custom palette is extended.

edoras vis supports the following parent process palettes:

  • edoras-gear (default value)

  • bpmn2.0

edoras vis supports the following parent form palette:

  • edoras-forms (default value)

edoras vis supports the following parent case palette:

  • case1.0 (default value)

Note that only the values shown here are supported and for normal edoras one development there is no use case that requires this attribute to be set.

This attribute does not support arbitrary creation of new palettes based on an existing palette. To create a separate palette based on existing one, you have to make a new copy and change all of the element IDs (as they must be unique).

To modify an existing palette use the apply-patch-to-palette attribute.

hide-parent-palette-elements

false

The boolean value to hide stencils of the parent palette. Defaults to true.

apply-patch-to-palette

false

The ID of a palette to be patched. The contents of the referenced palette will be modified / extended instead of a new palette being created.

resource-bundle

false

Resource Bundle File containing language specific translations. All resource bundle files should be placed under an i18n directory in the same directory as the palette XML file. Refer to Defining resource keys for language specific attributes in custom palette for more details.

See Sample custom palette for an example.

Defining widget groups in a custom palette

edoras vis supports grouping of widgets within custom palettes.

Table 93. Attributes supported by the group element
Name Mandatory Description

id

true

Unique Id of the group

title

false

Title of the group

description

false

Description of the group

index

false

Index of the group, Sorted in ascending order

Sample group element is shown below.

<group id="Events" title="Events" description="Events description" index="5" >
    <component id="events_start" extends="StartNoneEvent"
               attribute-groups="commonAttributes, formControlAttributes"/>
    <component id="events_end" extends="EndNoneEvent" description="End Event">
        <attribute id="custom_event_attribute" title="Custom Event Attribute" value="custom"/>
    </component>
</group>
Defining widgets in a custom palette

edoras vis supports creating of custom widgets in a custom palette by extending/referencing available generic widgets.

To add a widget to the custom palette, a widget element has to be added to the group element.

The widget element in turn may contain one or more attribute elements which define the widget specific properties.

Table 94. Attributes supported by the widget element
Name Mandatory Description

id

true

Unique Id of the widget

title

false

Title of the widget

description

false

Description of the widget

visible

false

Configure visibility of the widget in editor.

extends

false

Id of the widget that is extended

ref

false

Id of the widget that is referenced

roles

false

Comma separated list of roles supported by the widget, Which are inturn used by rules. See Defining rules in a custom palette for more details.

attribute-groups

false

Comma separated list of attribute group id that need to be added to the widget. See Defining attribute groups in a custom palette for more details.

presentation-id

false

Presentation reference required to render the widget SVG/Image on the editor canvas. See [defining-custom-component-presentation-in-a-custom-palette] for more details.

default-lane-id

false

Applicable only for Pool type.Configure default lane Id for a pool.

shortcut-menu-index

false

Applicable only for Process palette. Configure index for short cut menus from process widgets.

index

false

Index of the widget, sorted in ascending order

behaviour-type

false

Applicable only for Form palette. Describes the behaviour of the referred widget.

Widget extending StartNoneEvent with attribute-groups:
<component id="events_start"
           extends="StartNoneEvent"
           attribute-groups="commonAttributes, formControlAttributes" >
</component>
Widget extending Task with custom widget-presentation and short cut menu index:
<component id="formtask"
           extends="Task"
           presentation-id="presentation.task"
           shortcut-menu-index="1" >
</component>
Widget referencing EndNoneEvent with a custom attribute and index:
<component id="events_end"
           description="End Event"
           ref="EndNoneEvent"
           index="5">
    <attribute id="custom_event_attribute"
               title="Custom Event Attribute"
               value="custom"/>
</component>
Widget behaving like a password widget:
<component id="base-password"
           extends="component"
           presentation-id="password.presentation"
           behaviour-type="Password" />
Defining custom categories in a custom palette

edoras vis supports defining of custom categories for attributes. These categories can be used to display the attributes of a widget under different headings in the property window of the editor view.

Table 95. Attributes supported by the category element
Name Mandatory Description

id

true

Unique Id of the category

title

false

Title of the category

index

false

Index of the category. It decides the position of category in property window

visible

false

Boolean value to hide the attributes category in property window

Sample custom-categories element is shown below.

<custom-categories>
    <category id="custom_category_1" index = "101" title="custom category 1(en)" />
    <category id="custom_category_2" title="custom category 2(en)"/>
    <category id="custom_category_3" title="custom category 3(en)" visible="false"/>
</custom-categories>

Sample application of custom categories to attributes is shown below.

<attribute id="namekey"  value=""   type="SimpleText" category= "custom_category_1" />
<attribute id="name" title="Name" description="Name" value="" type="SimpleText" category="custom_category_2"/>
<attribute id="behavior" type="ComboBox" category= "custom_category_1"  index="3" title="behavior">
    <items>
        <item id="none" title="none" value="none" />
        <item id="all" title="all" value="all" />
        <item id="one" title="one" value="one" />
        <item id="complex" title="complex" value="complex" />
    </items>
</attribute>
Defining attributes in a custom palette

edoras vis supports defining custom attributes in the custom palette configuration.

To add an attribute with in custom palette, an attribute element has to be used. This element can only exist with in any of the following parent elements:

  • attribute-group

  • custom-attributes-group

  • model-attributes

  • component

Table 96. Attributes supported by the attribute element
Name Mandatory Description

id

true

Unique identifier of the attribute

title

false

Title of the attribute

description

false

Description of the attribute

value

false

Value of the attribute

type

false

Type of the attribute. Check Attribute types supported in a custom palette for more details.

category

false

Name of the category under which the attribute should be displayed in the property window of editor view.

export

false

Boolean value to specify whether an attribute should be exported to the xml and json(only for forms).

index

false

Integer value to define position of the attribute in the property window of the editor view.

ref-to-view

false

Id of the SVG element to which attribute value is mapped. Know more ref-to-view

readonly

false

Boolean value to make the attribute readonly.

optional

false

Boolean value to make the attribute mandatory.

visible

false

Boolean value to make the attribute visible in the property window.

filter

false

Applicable only for TreeView type. A comma separated list of file extensions. Know more filter

multilanguage

false

Boolean value to specify whether the attribute supports multilanguage. Know more multilanguage

fill

false

Applicable only for Color type. Know more fill

url

false

Applicable only for RestComboBox type.

stroke

false

Applicable only for Color type.

multiselect

false

Applicable only for RestComboBox type.

constant

false

Boolean value to make attribute value as constant.

length

false

Integer value to support maximum length for value.

popular

false

Boolean value to make attribute to has higher priority while displaying.

field-map

false

Applicable only for RestComboBox type. To map item display-name and value returned in the REST end point’s response.

item-icon-visible

false

Applicable only for RestComboBox type. To make each item’s icon visible.

select-all

false

Applicable only for RestComboBox type. To pre-select all the items returned by the REST end.

custompalette

false

Applicable only for TreeView type. To provide name of the palette for default selection in tree view editor’s drop-down list.

model-id

false

Applicable only for TreeView type.

runtime

false

Applicable for all type attributes. To make run time attribute visible. Know more runtime and runtime-value

runtime-value

false

Provide default value to run time attribute. Know more runtime and runtime-value

readonly-editor

false

Applicable only for RestComplex and Complex type. To provide non editable editor.

placeholder

false

Applicable only for TreeView type.

output-mapping

false

Applicable only for complex editor type.

edoras vis support multiple languages.

Table 97. Language specific attributes supported by the attribute element
Name Mandatory Description

title

false

If title is Resource bundle key, Then title will be picked form resource bundle file.

description

false

If description is Resource bundle key, Then description will be picked form resource bundle file

value

false

If value is Resource bundle key, Then value will be picked form resource bundle file

Defining resource keys for language specific attributes in custom palette

edoras vis supports defining language specific for custom attributes/widgets in the custom palette configuration.

edoras vis follows below format while generating translation keys.

Table 98. Tranlation keys for supported elements
Element Translation Key Format

Component

Component supports title and description as language specific property

<component-id>.title
<component-id>.description

Group

Group supports title and description as language specific property

<group-id>.title
<group-id>.description

Attribute

Attribute support only title, description and value as language specific property

If attribute element is within the widget element then the format of key is

<component-id>.<attribute-id>.title
<component-id>.<attribute-id>.description
<component-id>.<attribute-id>.value

If attribute element is within the attribute-goup element then the format of key is

<attribute-group-id>.<attribute-id>.title
<attribute-group-id>.<attribute-id>.description
<attribute-group-id>.<attribute-id>.value

If attribute element is within the custom-attributes-goup element then the format of key is

<custom-attributes-group-id>.<attribute-id>.title
<custom-attributes-group-id>.<attribute-id>.description
<custom-attributes-group-id>.<attribute-id>.value

If attribute element is within the model-attributes element then the format of key is

<model-attributes-id>.<attribute-id>.title
<model-attributes-id>.<attribute-id>.description
<model-attributes-id>.<attribute-id>.value

Category

Category support only title as language specific property

<category-id>.title
Defining validation rules for attributes in a custom palette

edoras vis supports defining validation rules for custom attributes in the custom palette configuration.

edoras vis supports following validation rules.
Table 99. Validation rules
Rule Description Example

Range

This rule can be applied to integer attributes to specify minimum and maximum allowed values.

<attribute id="cCardCvv" type="Integer"  title="Credit Card CVV" description="Credit Card CVV" optional="false">
    <validation-rules>
        <range min="100" max="999" />
    </validation-rules>
</attribute>

Length

This rule can be applied to specify the minimum and maximum length of value.

<attribute id="cCard" type="SimpleText"  title="Credit Card Number" description="Credit Card Number" optional="false">
    <validation-rules>
        <length min="0" max="16" />
    </validation-rules>
</attribute>

Expression

This rule can be applied to validate value against JavaScript expression.

<attribute id="cCard" type="SimpleText"  title="Credit Card Number" description="Credit Card Number" optional="false">
    <validation-rules>
        <expression pattern="^4[0-9]{12}(?:[0-9]{3})?$" />
    </validation-rules>
</attribute>
Named validations support in edoras vis

Refer Configuring named validations in palette section for details on named validation configuration in edoras vis.

Attribute types supported in a custom palette

edoras vis supports following attribute types.

Table 100. Attribute types
Type Field Type Example

SimpleText

Text Field

<attribute id="name" title="Name" description="Name" value="" type="SimpleText"/>
simpletext

TextArea

Text Area

<attribute id="summary" title="Summary" description="Summary" value="" type="TextArea" />
textarea

Integer

Number Field

<attribute id="age" title="Age" description="Age" value="15" type="Integer" category="common" />
integer

Float

Number Field

<attribute id="price" title="Price" description="Price" value="1.11" type="Float" category="common" />
float

Boolean

Check Box

<attribute id="isValid" title="Is Valid" description="Is Valid" value="true" type="Boolean"/>
boolean

ComboBox

ComboBox

<attribute id="selectnumber" title="Select Number" description="Select Number" value="2" type="ComboBox">
    <items>
        <item id="1" title="One" value="1" />
        <item id="2" title="Two" value="2" />
        <item id="3" title="Three" value="3" />
    </items>
</attribute>
combobox

Check Special attribute items for more details.

RestComboBox

ComboBox

<attribute id="company" title="Company" description="Company" url="http://www.company.com" type="RestComboBox"/>
restcombobox

TextEditor

Text Editor

<attribute id="notesShort" title="NotesShort" type="TextEditor" value="" description="Short notes."/>
texteditor

RichText

Rich Text Editor

<attribute id="documentation" title="Documentation" description="Documentation" value="" type="RichText"/>
richtext

TreeView

Tree view dialog

<attribute id="form_entry" title="FormRef" type="TreeView" value="" description="Form referenced by Form Task." filter="xfm" optional="false" readonly="true" />
treeview

Date

Date field

<attribute id="duedate" title="Due Date" description="Due Date" value="" type="Date"/>
date

ComplexDate

Date Editor

<attribute id="min-date" type="ComplexDate" value="" readonly="false" path="extraSettings.minDate" export="true" category="edoras" index="105"/>
complexdate

Color

Color field

<attribute id="bgcolor" title="BackgroundColor" type="Color" value="#ffffcc" description="" ref-to-view="fill_el" fill="true" stroke="false" optional="false"/>
color

Complex

Complex dialog

<attribute id="in" title="In" type="Complex" description="Execution element for data input." value="">
    <complex-items>
        <complex-item id="source" name="Source" type="SimpleText" value="" width="150" />
        <complex-item id="target" name="Target" type="SimpleText" value="" width="150" />
    </complex-items>
</attribute>
complex

ComplexKeyValue

Complex dialog

<attribute id="in" title="In" type="ComplexKeyValue" description="Property for Complex Key Value editor." value="">
    <complex-items>
        <complex-item id="key" name="Key" type="SimpleText" value="" width="150" />
        <complex-item id="value" name="Value" type="SimpleText" value="" width="150" />
    </complex-items>
</attribute>

In the ComplexKeyValue type the first column is always taken as the key and the second column is always taken as value and any further columns are ignored even if present.

complexkeyvalue

ComplexForm

Form dialog

<attribute id="email" title="Email Properties" type="ComplexForm" description="Email properties" value="">
    <complex-items>
        <complex-item id="from" name="From" type="SimpleText" value="" width="250" vtype="expressionOrEmail" optional="false" />
        <complex-item id="to" name="To" type="SimpleText" value="" width="250" vtype="expressionOrEmailList" optional="false" />
        <complex-item id="cc" name="Cc" type="SimpleText" value="" width="250" vtype="expressionOrEmailList" />
        <complex-item id="bcc" name="Bcc" type="SimpleText" value="" width="250" vtype="expressionOrEmailList" />
        <complex-item id="subject" name="Subject" type="SimpleText" value="" width="250" />
        <complex-item id="html" name="Html" type="RichText" value="" width="250" />
    </complex-items>
</attribute>
complexform

Check Special Attribute complex-items for more details.

Link

Link field

<attribute id="link" title="SimpleLink" type="Link" value="http://www.google.com" />
link

ComplexTrigger

Complex Timer dialog

<attribute id="ComplexTrigger" type="ComplexTrigger" title="Complex Trigger" value="" optional="true" readonly="false" category="edoras" />
complextrigger

RestComplex

Complex dialog

<attribute id="RestComplex" readonly-editor="false" type="RestComplex" title="RestComplex" value="" url="../rest/one-groups" readonly="false" optional="true" category="edoras">
        <complex-items>
            <complex-item id="id" type="SimpleText" value="" name="ID" optional="false" />
            <complex-item id="title" type="SimpleText" value="" name="Title" optional="true" />
            <complex-item id="value" type="SimpleText" value="" name="Value" />
        </complex-items>
</attribute>
complex
Defining custom widget presentation in a custom palette

edoras vis supports defining the SVG and Image for a widget.

Table 101. Attributes supported by the widget-presentations element
Name Mandatory Description

base-palette-icon-path

true

Base folder path where all related images are present.

base-editor-view-path

true

Base folder path where all related SVG file are present.

Table 102. Attributes supported by the widget-presentation element
Name Mandatory Description

id

true

Id of the widget presentation.

palette-icon-path

false

Path of image file used in presentation.

editor-view-path

false

Path of SVG file used in presentation.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component-presentations base-palette-icon-path="icons" base-editor-view-path="view">
    <component-presentation id="presentation.number" palette-icon-path="number.png" editor-view-path="number.svg"/>
    <component-presentation id="presentation.password" palette-icon-path="password.png" editor-view-path="password.svg"/>
</component-presentations>

For detailed explanation on oryx related elements and attributes in SVG view check here SVG view features

Defining rules in a custom palette

edoras vis supports defining the rules for a widget behaviour.

Table 103. Rules supported by an edoras vis custom palette widgets
Name Mandatory Description

containment-rules

This rule can be applied to widgets to specify containment rules based on roles.

<containment-rules>
    <containment-rule role="base_container" contains="standard_container,core_form_controls"/>
    <containment-rule role="standard_container" contains="core_form_controls"/>
</containment-rules>

morphing-rules

This rule can be applied to widgets to specify morphing rules (Changing from one type to another) based on roles.

<morphing-rules>
    <morphing-rule role="controls_morph" base-morphs="Input"/>
</morphing-rules>

connection-rules

This rule can be applied to widgets to specify connection rules between widgets based on roles (Used Only in Process Custom Palettes).

<connection-rules>
    <connection-rule role="SequenceFlow">
        <connects from="sequence_start" to="sequence_end"/>
    </connection-rule>
    <connection-rule role="MessageFlow">
        <connects from="messageflow_start" to="messageflow_end"/>
    </connection-rule>
</connection-rules>
  1. SequenceFlow widgets can be used to connect between widgets having roles "sequence_start" and "sequence_end"

  2. MessageFlow widgets can be used to connect between widgets having roles "messageflow_start" and "messageflow_end"

cardinality-rules

This rule can be applied to widgets to specify number of incoming and outgoing connector rules based on roles (Used Only in Process Custom Palettes).

<cardinality-rules>
     <cardinality-rule role="Startevents_all">
        <incoming role="SequenceFlow" maximum="0"/>
    </cardinality-rule>
    <cardinality-rule role="Endevents_all">
        <outgoing role="SequenceFlow" maximum="0"/>
    </cardinality-rule>
</cardinality-rules>
  1. Widgets having "Startevents_all" as role cannot have incoming sequence flows.

  2. Widgets having "Endevents_all" as role cannot have outgoing sequence flows.

Defining attribute groups in a custom palette

edoras vis supports defining custom attribute groups, which can be used to assign a set of attributes to multiple widgets. .Attributes supported by an attribute-group element

Name

Mandatory

Description

name

true

Unique name of the attribute group

An attribute-groups element can contain one or more attribute-group elements. Similarly an attribute-group element can contain one or more attribute elements, as shown in the sample below.

<attribute-groups>
    <attribute-group id="commonAttributes">
        <attribute id="id" title="Id" value=""/>
        <attribute id="nameKey" title="NameKey" description="NameKey" type="SimpleText" value="" />
    </attribute-group>
    <attribute-group id="formControlAttributes">
        <attribute id="label" runtime="false" multilanguage="false" category="common"/>
        <attribute id="description" title="Description" type="SimpleText" visible="false"/>
    </attribute-group>
</attribute-groups>

if an attribute-group with same id present across multiple palettes, it will extend those attributes as well. If the attribute-group with same id contains repeated attribute(i.e with same id) across multiple custom palettes, it will show warning. Similarly if repeated attributes differs in default value, it will show warning.

Defining custom attributes in custom palette

edoras vis supports defining custom attributes.

Table 104. Attributes supported by the custom-attributes-group element
Name Mandatory Description

id

true

Id of the custom-attributes-group.

ref

false

Id of the widget to which the custom attributes are applied to. If this attribute is skipped then the attributes are applied to all the widgets.

A custom-attributes element can contain one or more custom-attributes-group elements. Similarly, a custom-attributes-group element can contain one or more attribute elements, as shown in the sample below.

<custom-attributes>
    <custom-attributes-group id="customAttributeGroup1">
        <attribute id="id" title="Id" value=""/>
        <attribute id="nameKey" title="NameKey" description="NameKey" type="SimpleText" value="" />
    </custom-attributes-group>
    <custom-attributes-group id="customAttributeGroup2" ref="Task">
        <attribute id="label" runtime="false" multilanguage="false" category="common"/>
        <attribute id="description" title="Description" type="SimpleText" visible="false"/>
    </custom-attributes-group>
</custom-attributes>
Defining model attributes in a custom palette

edoras vis supports defining model attributes in a custom palette.

To add model attributes a model-attributes element has to be added.

A model-attributes element can contain one or more attribute elements. All attributes which are defined within the model-attributes element will be added to the model. See the sample below.

<model-attributes id="modelAttributes" >
    <attribute id="expressionid" title="Label Expresion" value=""/>
    <attribute id="guid" title="GUID" description="GUID of the model" type="SimpleText" value="" />
</model-attributes>

8.8.3. Special attributes of attribute element in palette

ref-to-view

ref-to-view specifies an id of SVG element in the graphical representation of a widget. If this attribute is set, the property will manipulate the graphical representation at run-time, for example, changing the color or rendering text. Depending on the property’s type you can reference different types of SVG elements as show below.

  • ref-to-view="text_name" (for text)

  • ref-to-view="fill_el" (for color)

<attribute id="name"   value="" category="common"  type="SimpleText" ref-to-view="text_name"/>
filter

The filter attribute is applicable only for TreeView type and is used to filter the nodes displayed in the tree view.

edoras vis supports following filters :

  • mod is used for Processes

  • xfm is used for Forms

<attribute id="form_entry" title="FormRef" type="TreeView" value="" description="Form referenced by Form Task." filter="xfm" optional="false" readonly="true" />
fill

fill is an optional attribute applicable only for Color type. If fill attribute is set to true the background color of a shape can be set.

fill
multilanguage

multilanguage is an optional attribute used to show or hide the language specific attributes for a given attribute in the property window.

multilanguage
runtime and runtime-value

runtime is an optional attribute used to show or hide runtime-value of an attribute in the property window of the editor.

<attribute id ="description" runtime-value="" runtime="true" multilanguage="true"> </attribute>
runtime
wrapLines

wrapLines is an optional attribute used to customize attributes of type String.

If wrapLines is set to false, the text field shown will be of single line.

If wrapLines is set to true, the text field shown will be of multi line.

items

items can be used as a child element of the attribute element of type ComboBox. This is used to define the list of values for the combobox.

<attribute id="behavior" type="ComboBox" category= "edoras"  index="3" title="behavior">
    <items>
        <item id="none" title="none" value="none" />
        <item id="all" title="all" value="all" />
        <item id="one" title="one" value="one" />
        <item id="complex" title="complex" value="complex" />
    </items>
</attribute>
complex-items

complex-items can be used as child element of attribute element if the attribute is of one of the following types:

  • Complex

  • ComplexForm

complex-items element can contain one or more complex-item elements.

Table 105. Attributes supported by the complex-item element
Name Mandatory Description

id

true

Id of the complex-item

name

false

Title of the complex-item

value

false

Value of the complex-item

type

false

Type of the complex-item, It can only support following types:

  • SimpleText

  • TextArea

  • ComboBox

  • RestComboBox

  • Boolean

  • Integer

  • Float

  • Date

  • ComplexDate

  • Color

  • Link

  • TextEditor

  • RichText

  • TreeView

vtype

false

A validation type for validating values, the supported validation types are:

  • singleEmail

  • emailList

  • expressionOrEmail

  • expressionOrEmailList

width

false

Width of the complex-item

optional

false

Used to make the complex-item optional or otherwise

<attribute id="email" title="Email Properties" type="ComplexForm" description="Email properties" value="">
    <complex-items>
        <complex-item id="from" name="From" type="SimpleText" value="" width="250" vtype="expressionOrEmail" optional="false" />
        <complex-item id="to" name="To" type="SimpleText" value="" width="250" vtype="expressionOrEmailList" optional="false" />
        <complex-item id="cc" name="Cc" type="SimpleText" value="" width="250" vtype="expressionOrEmailList" />
        <complex-item id="bcc" name="Bcc" type="SimpleText" value="" width="250" vtype="expressionOrEmailList" />
        <complex-item id="subject" name="Subject" type="SimpleText" value="" width="250" />
        <complex-item id="html" name="Html" type="RichText" value="" width="250" />
    </complex-items>
</attribute>
dependency

dependency can be used as a child element of the attribute element. This is used to make attribute visible/hide based on another attribute value.

<attribute id="thumbnail-max-height" type="SimpleText" title="Thumbnail Maximum Height" value="" >
    <dependency ref="preview" value="thumbnail" />
</attribute>

8.8.4. Configuring named validations in palette

edoras vis supports named validations which can be used to implement customized attribute validations at design time.

A typical named validation palette configuration would look like below:

<component id="prime-number" ref="base-text" title="Prime number">
    <attribute id="value" type="SimpleText">
        <validation-rules>
            <rule name="isPrimeNumber">
                <param name="value" value="[[value]]"/>
            </rule>
        </validation-rules>
    </attribute>
    <attribute id="label"/>
</component>

For the above isPrimeNumber named validation rule configuration in the palette, vis editor will try to execute a java-script function by name isPrimeNumber by passing the value of the value attribute as a parameter.

function isPrimeNumber(num){
    if(num && !isNaN(num)){
        var N = parseInt(num);
        for(var i = 2; i <= (N/2); i++){
            if(N % i == 0){
                return false;
            }
        }
        return true;
    }
    return "Invalid value";
}

If such a function is defined and it returns one of true, false or an error message, as shown in the above sample, the validation is successful only when the return value is true and fails when the return value is either false or any other value. A warning message is shown against the attribute when the validation fails. In cases where a error message is returning the error message is shown as part of the warning message against the attribute.

This java-script function can also invoke a REST end-point (synchronously) in cases where validation needs to be done on the server.

Such a function can be added to the custom.js file already made available in the edoras-one-client module.

It is also possible to directly provide a REST end-point URL in a named validation configuration as shown in the below sample:

<component id="zip-code" ref="base-text">
    <attribute id="country" type="ComboBox" value="CH" category="common" index="2">
        <items>
            <item id="US" value="US" title="United States"/>
            <item id="CH" value="CH" title="Switzerland"/>
            <item id="DE" value="DE" title="Germany"/>
            <item id="FR" value="FR" title="France"/>
            <item id="ES" value="ES" title="Spain"/>
            <item id="IN" value="IN" title="India"/>
        </items>
    </attribute>
    <attribute id="value" type="SimpleText">
        <validation-rules>
            <rule name="validate-zip-code" url="../rest/validate-zip">
                <param name="zip" value="[[value]]"/>
                <param name="countryCode" value="[[country]]"/>
            </rule>
        </validation-rules>
    </attribute>
    <attribute id="label"/>
</component>

Even in this case the vis editor will try to execute a java-script function by name validateZipCode by passing the values of the value and country attributes as parameters.

Only if such a function is not defined, the REST URL is invoked with the specified parameters.

The REST end-point is expected to return a String value as shown in the below sample.

@ResponseBody
@RequestMapping(value = "/validate-zip", method = GET)
public String validateZipCode(@RequestParam String zip, @RequestParam(required = false) String countryCode) {

    if (countryCode != null && zip != null) {
        if (zip.length() > 3) {
            switch (countryCode) {
                case "US":
                    return String.valueOf(zip.matches("^[0-9]{5}(?:-[0-9]{4})?$"));
                case "CH":
                    return String.valueOf(zip.matches("^[0-9]{4}"));
                case "ES":
                case "FR":
                case "DE":
                    return String.valueOf(zip.matches("^[0-9]{5}"));
                case "IN":
                    return String.valueOf(zip.matches("^[0-9]{6}"));
                default:
                    return "true";
            }
        } else {
            return "Zip code too short.";
        }
    }

    return "Invalid input.";
}

The validation is successful if the REST end-point returns true and fails if it either returns false or any string other than true. A warning message is shown against the attribute when the validation fails. In cases where a error message is returned the error message is shown as part of the warning message displayed against the attribute.

8.8.5. SVG view features

oryx:magnet

With oryx:magnet you can define special points on a node where you can dock other nodes or edges to connect them.

You can connect a docker to any point on a node, but magnets help the user creating nicer looking models. If you do not define a magnet for a node, it will a have default magnet in the center. Magnets are specified with 'magnet' elements, for example:

<oryx:magnets>
    <oryx:magnet oryx:cx="1" oryx:cy="20" oryx:anchors="left" />
    <oryx:magnet oryx:cx="1" oryx:cy="40" oryx:anchors="left" />
    <oryx:magnet oryx:cx="1" oryx:cy="60" oryx:anchors="left" />

    <oryx:magnet oryx:cx="25" oryx:cy="79" oryx:anchors="bottom" />
    <oryx:magnet oryx:cx="50" oryx:cy="79" oryx:anchors="bottom" />
    <oryx:magnet oryx:cx="75" oryx:cy="79" oryx:anchors="bottom" />

    <oryx:magnet oryx:cx="99" oryx:cy="20" oryx:anchors="right" />
    <oryx:magnet oryx:cx="99" oryx:cy="40" oryx:anchors="right" />
    <oryx:magnet oryx:cx="99" oryx:cy="60" oryx:anchors="right" />

    <oryx:magnet oryx:cx="25" oryx:cy="1" oryx:anchors="top" />
    <oryx:magnet oryx:cx="50" oryx:cy="1" oryx:anchors="top" />
    <oryx:magnet oryx:cx="75" oryx:cy="1" oryx:anchors="top" />

    <oryx:magnet oryx:cx="50" oryx:cy="40" oryx:default="yes" />
  </oryx:magnets>

The oryx:magnets element is a direct child of the svg element.

magnet

The magnets are shown as small light red circles light magnet

oryx:docker

dockers are the other part of the dockers-magnets concept. A docker is a control object to connect an edge to a node or in this case to connect two nodes. A node can have at most one docker that can be defined by using a docker element:

<oryx:docker oryx:cx="16" oryx:cy="16" />
docker

A docker is shown as a small green circle green docker

A docker element needs only position information. Docking nodes on nodes can be used as a shortcut for connecting two nodes with an edge. In this figure, the rectangular shape is the source and the circular shape is the target.

Text

Text is rendered with SVG text elements.

<text
       font-size="12"
       id="text_name"
       x="50"
       y="40"
       oryx:align="middle center"
       oryx:fittoelem="text_frame"
       stroke="black">
</text>
text

Oryx extends these element with attributes for the alignment and the rotation of the text. The alignment uses the specified coordinates (attributes x and y) as the reference point. A value of middle center means that the horizontal center and vertical middle point of the text will be positioned on the reference point.

If you want to set the text element’s value using a property, you have to set the id of the text element by using ref-to-view attribute in custom palette.
<attribute id="name"   value="" category="common"  type="RichText" ref-to-view="text_name"/>
oryx:minimumSize
  • Value: float float

  • Initial: 1 1

  • Optional: yes

  • Applies to: SVG elements

minimumSize defines the minimum size the node can be resized to, if the node is resizable. The first value defines the minimum width, the second the minimum height.

<g pointer-events="fill" oryx:minimumSize="200 80" >
oryx:maximumSize
  • Value: float float

  • Initial: -

  • Optional: yes

  • Applies to: SVG elements

maximumSize defines the maximum size the node can be resized to, if the node is resizable. The first value defines the maximum width, the second the maximum height.

<g pointer-events="fill" oryx:minimumSize="80 60" oryx:maximumSize="200 160" >

8.8.6. Removing widgets from the main palette using fragment/patch palettes

edoras vis supports defining model attributes in a custom palette.

This feature can be used in cases where some of the default widgets provided in the default palettes should not been shown (since similar custom widgets have been added). To remove certain widgets, add the widget IDs as a comma separated list to the stencil-ids attribute of the <remove-stencils> element in the patch/fragment palette as shown in the below sample:

    <remove-stencils
            stencil-ids="cloud-attachment,cloud-upload"/>

Note this only works for elements contained in the main palette to which the patch palette is applied to.

8.8.7. Sample custom palette

A sample custom palette is given below:

<?xml version="1.0" encoding="UTF-8"?>
<palette id="custom-process-palette"
     xmlns="http://www.edorasware.com/schema/vis/palette"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.edorasware.com/schema/vis/palette http://www.edorasware.com/schema/vis/edoras-vis-process-palette-2.0.57.xsd"
     resource-bundle="translation">

    <attribute-groups>
        <attribute-group id="baseAttributes">
            <attribute id="id" value="" title="" />
            <attribute id="name" value="" title="Name"
                       multilanguage="false" category="common" ref-to-view="text_name"/>
            <attribute id="documentation" value="" title="Documentation"
                       multilanguage="false" category="common"/>
        </attribute-group>

        <attribute-group id="usertask">
            <attribute id="notesShort" title="" value="" />
            <attribute id="notesShortKey" title="" value="" />
            <attribute id="candidateusers" title="CandidateUsers" value=""
                       category="edoras" type="RestComboBox" url="/rest/modeler-users"/>
            <attribute id="candidategroups" title="CandidateGroups" value=""
                       category="edoras" type="RestComboBox" url="/rest/modeler-groups"/>
            <attribute id="support" title="Support Link" type="Link"
                       value="http://www.edorasware.com/support" />
        </attribute-group>
    </attribute-groups>

    <model-attributes id="modelAttributes">
        <attribute id="guid" value="" title="" />
        <attribute id="labelExpression" value="" title="" />
        <attribute id="version" value="" title="" />
        <attribute id="author" value="" title="" />
        <attribute id="language" value="" title="" visible="false"/>
        <attribute id="namespaces" value="" title="" visible="false"/>
    </model-attributes>

    <group title="Custom Tasks" id="custom-shapes">
        <component id="CustomFormTask" extends="FormTask"
                   attribute-groups="baseAttributes,usertask"/>
        <component id="CustomManualTask" extends="ManualTask"
                   attribute-groups="baseAttributes,usertask"/>
        <component id="CustomEndNoneEvent" extends="EndNoneEvent"
                   attribute-groups="baseAttributes"/>
        <component id="CustomSequenceFlow" extends="SequenceFlow"
                   attribute-groups="baseAttributes"/>
        <component id="CustomTextAnnotation" extends="TextAnnotation"
                   attribute-groups="baseAttributes"/>
        <component id="CustomAssociationUndirected" extends="Association_Undirected"
                   attribute-groups="baseAttributes"/>
        <component id="CustomExclusiveDatabasedGateway" extends="Exclusive_Databased_Gateway"
                   attribute-groups="baseAttributes"/>
        <component id="CustomParallelGateway" extends="ParallelGateway"
                   attribute-groups="baseAttributes"/>
    </group>

    <group title="Activities" id="activities">
        <component ref="Task" id="RefTask"/>
        <component ref="Subprocess" id="RefSubprocess"/>
        <component id="RefFormTask" extends="FormTask">
            <attribute id="formInit" value="" title="Init Form Ref"
                   type="TreeView" filter="xfm" category="common" export="true"/>
            <attribute id="guid-ref" value="" title="Init Form Ref (ID)"
                   type="SimpleText" category="common" export="true" visible="false"/>
        </component>
        <component ref="CollapsedSubprocess" id="RefCollapsedSubprocess"/>
        <component ref="ExpandedSubProcess" id="RefExpandedSubProcess"/>
        <component ref="CallActivity" id="RefCallActivity"/>
    </group>

    <group title="Gateways" id="gateways">
        <component ref="Exclusive_Databased_Gateway" id="RefExclusive_Databased_Gateway"/>
        <component ref="ParallelGateway" id="RefParallelGateway"/>
    </group>

    <group title="Events" id="events">
        <component ref="StartNoneEvent" id="StartNoneEvent"/>
        <component ref="EndNoneEvent" id="EndNoneEvent"/>
    </group>

    <group title="Connectors" id="connectors">
        <component ref="SequenceFlow" id="RefSequenceFlow"/>
        <component ref="Association_Undirected" id="RefAssociation_Undirected"/>
        <component ref="Association_Unidirectional" id="RefAssociation_Unidirectional"/>
        <component ref="MessageFlow" id="RefMessageFlow"/>
        <component ref="Association_Bidirectional" id="RefAssociation_Bidirectional"/>
    </group>

</palette>

8.9. Defining App development workflows

8.9.1. App development overview

edoras one supports configurable app development workflows, allowing automatic or semi-automatic exchange of Apps between different edoras one installations and tenants.

To transfer an App out of an edoras one tenant, the App content is written to the local filesystem using an outgoing channel adapter. The adapter can then send a message to a Spring Integration channel to trigger additional processing (e.g. to copy the App to another system).

Spring Integration can also be used to receive incoming Apps and send them to the Incoming App Service. This documentation will describe the interface between edoras one and Spring Integration. For details of how to configure Spring Integration to implement a given App distribution workflow please refer to the {spring-int-page}.

Here is a high level overview of the App workflow processing:

AppWorkflow

8.9.2. Outgoing adapter configuration

An outgoing adapter can be declared as a Spring bean which implements the interface:

com.edorasware.cloud.core.transfer.OutgoingAppChannelAdapter

Beans declared with this interface will automatically be detected by the edoras one Spring configuration - no additional registration is required. edoras one provides the following standard channel adapter implementations:

com.edorasware.cloud.core.transfer.internal.LocalDirectoryOutgoingAppChannelAdapter

writes the App to the local filesystem as a file tree within a root directory.

com.edorasware.cloud.core.transfer.internal.LocalZipFileOutgoingAppChannelAdapter

writes the App to the local filesystem as a ZIP file.

In all channel adapter implementations by default the App will be written using an ID that is constant across all systems where the App is installed. But you are able to configure this with the exportedAppNameExpression property on the channel adapters. The given expression is evaluated with the App Model as context, meaning that an expression like name will evaluate to the App Model name. Expression prefix and suffix like #{, } is added automatically to the expression string.

As an example, a typical outgoing channel adapter configuration for deployed Apps could look like the following:

  @Bean
  public OutgoingAppChannelAdapter localZipFileOutgoingAppChannelAdapter(
          WorkObjectService workObjectService,
          CurrentTenantService currentTenantService,
          TenantLookupService tenantLookupService,
          TimeProvider timeProvider,
          GearExpressionResolver gearExpressionResolver,
          AppExporter appExporter,
          AppWriterFactory writerFactory,
          MessageChannel loggingChannel,
          @Value("${transfer.outgoing.location}") Path basePath)
  {
      return new LocalZipFileOutgoingAppChannelAdapter(
              workObjectService,
              currentTenantService,
              tenantLookupService,
              timeProvider,
              gearExpressionResolver,
              appExporter,
              writerFactory,
              "Local Directory",
              basePath,
              loggingChannel);
  }

  @Bean
  public MessageChannel loggingChannel() {
      LoggingHandler loggingHandler = new LoggingHandler(LoggingHandler.Level.WARN.name());
      loggingHandler.setShouldLogFullMessage(true);

      DirectChannel directChannel = new DirectChannel();
      directChannel.subscribe(loggingHandler);
      return directChannel;
  }

This configuration will save each deployed App as a Zip file in the given directory, and then send a message to the logging channel (where the full message content will be logged).

8.9.3. Outgoing adapter message format

By setting the messageChannel property outgoing channel adapter implementations can send a message to a Spring Integration channel whenever an App is saved. These messages can be used to trigger the additional processing needed for App distribution, and have the following format:

  • the message payload is a org.springframework.core.io.Resource describing the App location

  • the message has additional headers with information that may be useful in subsequent processing

Table 106. Outgoing Spring Integration message headers
Header Type Description

appName

String

the current App name (this may change over time)

appSourceId

String

the App Global ID (constant across all systems)

comment

String

a comment supplied when the App distribution was triggered

sourceTenantName

String

the name of the originating tenant

8.9.4. Incoming adapter configuration

Spring Integration can be configured to import an App by sending a message to the pre-defined App channel resourceAppChannel. This channel accepts messages with org.springframework.core.io.Resource payloads describing the App location and supports:

  • remote App Zip resources

  • local App Zip files

  • local App file trees

To define incoming App workflows Spring Integration should be enabled by adding the @EnableIntegration annotation to the project configuration class. As part of the example implementation we will also make use of Spring Integration’s Java DSL, so we add the relevant dependency:

  <dependency>
          <groupId>org.springframework.integration</groupId>
          <artifactId>spring-integration-java-dsl</artifactId>
          <version>1.2.2.RELEASE</version>
  </dependency>

An incoming channel adapter configuration to automatically load apps from a given input directory could look like the following. First we start with an App source that generates an array of resources by checking for modified files that match the given pattern:

  @Bean
  public MessageSource customIncomingAppSource() {
      ResourceRetrievingMessageSource source =
              new ResourceRetrievingMessageSource("file:/tmp/INCOMING/*.zip");
      source.setFilter(new ModifiedFilesFilter());
      return source;
  }

We then connect this source via a polling adapter to the customAppArrayChannel which will receive messages containing an array of App resources. The source will be polled once a minute, checking for newly-arrived Apps:

  @Bean
  public DirectChannel customAppArrayChannel() {
      return MessageChannels.direct().datatype().get();
  }

  @Bean
  public SourcePollingChannelAdapterFactoryBean customIncomingAppAdapter() {
      SourcePollingChannelAdapterFactoryBean factoryBean
              = new SourcePollingChannelAdapterFactoryBean();

      PollerMetadata pollerMetadata = Pollers.fixedRate(1, TimeUnit.MINUTES).get();
      factoryBean.setPollerMetadata(pollerMetadata);
      factoryBean.setSource(customIncomingAppSource());
      factoryBean.setOutputChannelName("customAppArrayChannel");
      factoryBean.setAutoStartup(false);

      return factoryBean;
  }

The poller is not auto-started as we need to wait for the rest of the system to be initialized, otherwise the channel adapter may be started before edoras one is ready to receive Apps. The channel bean reference should be registered with edoras one which will start the channel at the appropriate time. To do this we overwrite the IncomingAppChannelAdapterLifecycleBean bean as follows:

  @Bean
  public static IncomingAppChannelAdapterLifecycleBean incomingChannelManager(
          IncomingAppService incomingAppService,
          List<AppDeploymentConfiguration> appDeploymentConfigurations,
          SourcePollingChannelAdapter customIncomingAppAdapter)
  {
      IncomingAppChannelAdapterLifecycleBean lifecycleBean =
              new IncomingAppChannelAdapterLifecycleBean(
                      incomingAppService,
                      appDeploymentConfigurations);

      lifecycleBean.setManagedChannels(Collections.singletonList(customIncomingAppAdapter));
      return lifecycleBean;
  }

As a final step, we create an integration flow to connect the channel for the resource arrays to the resourceAppChannel used by the edoras one server to receive incoming Apps. This splits the resource arrays into individual resource messages, and adds a header to each one to remove the original file once the import has been completed:

  @Bean
  public StandardIntegrationFlow customIncomingAppFlow() {
      return IntegrationFlows.from(customAppArrayChannel())
              .split()
              .enrichHeaders(ImmutableMap.of("removeAfterImport", true))
              .channel("resourceAppChannel")
              .get();
  }

8.9.5. Incoming App service message format

The incoming App service accepts messages from a Spring Integration channel as follows:

  • the message payload is a org.springframework.core.io.Resource describing the App location

  • the message has additional headers with information to control the App import process

Table 107. Incoming Spring Integration message headers
Header Type Default Description

isSystemApp

Boolean

false

Set to true if the incoming app is the system app

isEditableApp

Boolean

true

Set to true if the app should be editable after import

removeAfterImport

Boolean

false

Set to true if the incoming app should be removed after import

forceAppImport

Boolean

false

Set to true if the incoming app should always be installed (no version checking will be performed)

tenantNames

String

<empty>

A comma-separated list of tenant names for the tenants where the app should be installed. If no tenant is specified then the app will be installed on all tenants.

8.9.6. App version checking

When an App is imported into edoras one, a version check will normally be performed. This makes sure that the currently installed version is a direct ancestor of the version that is being imported. If this is not the case then the App being imported is based on a different version of the App than the one that is installed. This means that changes currently installed on the system may be lost.

This version check may be disabled using the incoming message headers, but this should only be done when the scenarios where this may be necessary have been established and the possible consequences of silently ignoring version conflicts have been considered.

8.9.7. Spring Integration extensions

The following implementations are provided by edoras one and can be used in Spring Integration configurations to support some common integration use cases:

com.edorasware.cloud.core.transfer.integration.ModifiedFilesFilter

a CollectionFilter<Resource> implementation that tracks incoming files and accepts files that are either new or have been modified. This is useful for polling an incoming App directory where the Apps aren’t removed after import.

8.10. Deployment

8.10.1. Deploying to Cloud Foundry

This appendix gives step by step instructions on how to deploy your application to a Cloud Foundry server. Cloud Foundry is an open Platform as a Service (PaaS) infrastructure.

Maven support

Cloud Foundry provides a Maven plugin that allows you to deploy applications with Maven goals. This appendix only gives basic instructions, please refer to http://docs.cloudfoundry.org/buildpacks/java/build-tool-int.html to learn more about Maven support for Cloud Foundry.

Install Maven plugin

To install the Cloud Foundry Maven plugin, add the corresponding section to your pom.xml file:

Cloud Foundry plugin installation in pom.xml
  <plugin>
          <groupId>org.cloudfoundry</groupId>
          <artifactId>cf-maven-plugin</artifactId>
          <version>1.0.3</version>
  </plugin>

Cloud Foundry does not have a persistent file system (the file system is cleared before an application restart), therefore it is not possible to persistently store work item and document content data in the file system. In this environment the application uses Cloud Foundry services to persistently store data.

Usually the application loads edorasware license from the file system (e.g. from the user’s home directory). Again, this approach is not possible with Cloud Foundry as there is no persistent file system, so we supply the edorasware license as an environment variable.

Configure Maven plugin

The configuration section of the plugin defines the default values used for the Cloud Foundry goals. It is possible to overwrite the default values with system variables.

server

Used to look up the Cloud Foundry credentials in the Maven settings.xml file. By default the settings.xml file is stored in ~/.m2/settings.xml. See http://maven.apache.org/settings.html#Servers to learn more about the Maven settings.xml file.

target

Defines the URL of your Cloud Foundry infrastructure API.

org

Defines your organization inside the Cloud Foundry infrastructure.

space

Defines the space to be used inside your organization.

env

Defines the environment variables needed by edoras one. The only environment variable we define here is the edorasware license.

services

Defines the Cloud Foundry services needed by edoras one: a relational database named datadb that stores the work items and a mongo DB named contentdb that stores the document content.

Putting all this together, the Cloud Foundry plugin section looks as follows:

Cloud Foundry plugin configuration in pom.xml
  <plugin>
          <groupId>org.cloudfoundry</groupId>
          <artifactId>cf-maven-plugin</artifactId>
          <version>1.0.3</version>
          <configuration>
                  <server>${cloudfoundry.server}</server>
                  <target>${cloudfoundry.target}</target>
                  <org>${cloudfoundry.org}</org>
                  <space>${cloudfoundry.space}</space>
                  <memory>1024</memory>
                  <env>
                          <EDORASWARE_LICENSE>${edorasware.license}</EDORASWARE_LICENSE>
                  </env>
                  <services>
                          <service>
                                  <name>datadb</name>
                                  <label>${cloudfoundry.service.datadb.label}</label>
                                  <plan>${cloudfoundry.service.datadb.plan}</plan>
                          </service>
                          <service>
                                  <name>contentdb</name>
                                  <label>${cloudfoundry.service.contentdb.label}</label>
                                  <plan>${cloudfoundry.service.contentdb.plan}</plan>
                          </service>
                  </services>
          </configuration>
  </plugin>

To ease the handling of the Cloud Foundry plugin configuration in the pom.xml file you can use Maven properties. The property values are then stored in two places: properties that are not security critical are defined inside a properties element at the top of the pom.xml file, security critical properties are defined in the Maven settings.xml file.

Properties in pom.xml
  <!-- Cloud Foundry properties -->
  <cloudfoundry.server>run.pivotal.io</cloudfoundry.server>
  <cloudfoundry.target>http://api.run.pivotal.io</cloudfoundry.target>
  <cloudfoundry.org>edorasware</cloudfoundry.org>
  <cloudfoundry.space>development</cloudfoundry.space>

  <cloudfoundry.service.datadb.label>elephantsql</cloudfoundry.service.datadb.label>
  <cloudfoundry.service.datadb.plan>turtle</cloudfoundry.service.datadb.plan>

  <cloudfoundry.service.contentdb.label>mongolab</cloudfoundry.service.contentdb.label>
  <cloudfoundry.service.contentdb.plan>sandbox</cloudfoundry.service.contentdb.plan>

Make sure that the server id in the Maven settings.xml file matches the server configuration value of Cloud Foundry plugin (run.pivotal.io in our case).

Settings in Maven settings.xml
     <servers>
         <server>
             <id>run.pivotal.io</id>
             <username>user</username>
             <password>pass</password>
         </server>
  </servers>
Use Maven plugin

To access your Cloud Foundry infrastructure, the Cloud Foundry Maven plugin offers different Maven goals. The most important is the one to deploy your application:

mvn cf:push

Congratulations! You have deployed your first edoras one application to a Cloud Foundry infrastructure.

Command line support

The recommended way to work with Cloud Foundry is to use the Maven integration (see above) or the Gradle integration. However for special cases it is possible to use the Cloud Foundry command line tool. One such special case is when your Cloud Foundry infrastructure does not support recent versions of the Maven / Gradle integration plugins.

It is not possible to define environment variables that contain line feeds with the Cloud Foundry command line tool. Therefore you cannot use an environment variable to supply the edorasware license to the Cloud Foundry infrastructure.

In this case you have to place the edorasware license file inside your application and access it from there, e.g. in the WEB-INF folder.

First make sure to install the correct version of the Cloud Foundry command line tool that matches your Cloud Foundry infrastructure. Then open a command line and invoke the Cloud Foundry commands as required. The following batch file lists the commands needed to deploy an edoras one application:

Batch file
  REM stop application
  cf stop edoras-one-bootstrap

  REM deploy application without start
  cf push edoras-one-bootstrap ^
     -d beta.swisscloud.io ^
     -m 1G ^
     -p target\edoras-one-bootstrap.war ^
     -t 150 ^
     --no-start

  REM create and bind relational database service
  cf create-service mariadb 512mb datadb
  cf bind-service edoras-one-bootstrap datadb

  REM create and bind document database service
  cf create-service mongodb default contentdb
  cf bind-service edoras-one-bootstrap contentdb

  REM start application
  cf start edoras-one-bootstrap

See http://docs.cloudfoundry.org/devguide/#cf to learn more about the Cloud Foundry command line tool.

8.10.2. How to integrate edoras one in your own html

It’s possible to use edoras one in your own html inside a div.

First of all, you should know some limitations:

  • edoras one app must be the unique angularJS app in your html.

  • The div which contains edoras one requires a defined height, that is, not auto, with percentage or pixels.

  • The minimum size supported in edoras one is 1024x768. That means that the div which contains edoras one must fit this measure.

The following html code must be inserted in your page:

<div ng-app="oneModule" class="edoras-one" >
    <script type="text/javascript" src="./forms/css/resources.css"></script>
    <script type="text/javascript" src="./one/css/resources.css"></script>
    <script type="text/javascript" src="./one/app/one.files.js"></script>
    <link type="text/css" media="all" href="./one/less/main.less" rel="stylesheet/less"/>
    <link rel="stylesheet" href="./forms/libs/upload/css/external/bootstrap-image-gallery.min.css" />
    <link rel="stylesheet" href="./forms/libs/upload/css/jquery.fileupload-ui.css" />
    <script type="text/javascript" src="./one/libs/moved/less/less-1.7.5.min.js"></script>
    <link rel="stylesheet" type="text/css" href="widgets.css"/>
    <script type="text/javascript" src="widgets.js"></script>
    <script type="text/javascript" src="widgets-module.js"></script>
    <link rel="stylesheet" type="text/css" href="custom.css"/>
    <script type="text/javascript" src="custom.js"></script>
    <div e-application-loader>
        <div id="mainDiv">
            <div e-menu></div>
            <div e-header></div>
            <div class="viewContainer">
                <div class="ng-view"></div>
                <div e-actions-pane></div>
            </div>
            <div e-version ></div>
        </div>
        <div e-notification-bar></div>
        <div e-select-dashboard-pane ></div>
        <div e-global-message></div>
    </div>
</div>

You must have the production files in the correct directory structure with "./one" and "./forms" directories and the backend endpoints.

If you want and you are able to do, you can define these css and scripts tags in your head element instead of the body, in order to be loaded synchronously before the page is rendered.

Customizing edoras one elements

You can avoid showing some elements like the menu, the header or the actions pane by simply deleting it from the html above. These elements are:

<div e-menu></div>
<div e-header></div>
<div e-actions-pane></div>
Placing our html in a different place than the resources

In the html we can set the BACK_END_BASE_URL and the FRONT_END_BASE_URL variables to specify where the server (back end) and resources (front end) are.

For example if we have our frontend resources in http://domain.com/resources but our html is in http://domain.com/web, we can set the FRONT_END_BASE_URL to "../resources/":

<script>window.FRONT_END_BASE_URL = '../resources/';</script>

If we have our backend resources in http://domain.com/rest but our html is in http://domain.com/, we can set the BACK_END_BASE_URL to "rest/":

<script>window.BACK_END_BASE_URL = 'rest/';</script>

This script tag must be placed before the one.files.js script tag:

<script>window.BACK_END_BASE_URL = '../resources/';</script>
<script type="text/javascript" src="./forms/app/one.files-1.5.0.S70.js"></script>

We can set the BACK_END_BASE_URL and FRONT_END_BASE_URL with relative or absolute values:

<script>window.BACK_END_BASE_URL = '../resources/';</script>
<script>window.BACK_END_BASE_URL = '/resources/';</script>
<script>window.BACK_END_BASE_URL = 'http://domain.com/resources';</script>
If you want to set an external domain as your context, then you need to follow the instructions in the next section about CORS. Note that currently you can only move the HTML to another context/domain and the front end resources still need to be served from the back end server. The complete separation will be done in a later release with the goal of having the front end resources together such that you have the possibility to serve these on a web server and have the back end as a pure REST server.
CORS configuration

To configure the back end to send the correct CORS headers you can define the following system properties:

Table 108. CORS configuration
System property Default Description

security.cors.path

/**

A path into the application that should handle CORS requests. Exact path mapping URIs (such as /admin) are supported as well as Ant-stype path patterns (such as /admin/**).

security.cors.allowed-methods

*

Comma-separated list of HTTP methods to allow, e.g. GET, POST. The special value * allows all method.

security.cors.allowed-headers

*

Comma-separated list of headers that a pre-flight request can list as allowed for use during an actual request. The special value of * allows actual requests to send any header.

security.cors.allowed-origins

*

Comma-separated list of origins to allow, e.g. http://domain1.com, http://domain2.com. The special value * allows all domains.

security.cors.allow-credentials

true

Whether user credentials are supported.

security.cors.exposed-headers

<empty>

Comma-separated list of response headers other than simple headers (i.e. Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma) that an actual response might have and can be exposed.

security.cors.max-age

1800

How long, in seconds, the response from a pre-flight request can be cached by clients.

8.10.3. Application logging

An edoras one project should log correctly using application-specified logging without changes.

For JBoss application servers, an additional deployment configuration file is required to prevent logging-related classes from the application container being added to the application classpath and interfering with the application-specific logging:

JBoss deployment configuration WEB-INF/jboss-deployment-structure.xml
  <?xml version="1.0" encoding="UTF-8"?>
  <jboss-deployment-structure>
      <deployment>
      <exclusions>
            <module name="org.apache.log4j"/>
            <module name="org.slf4j"/>
            <module name="org.jboss.logging"/>
            <module name="commons-logging"/>
            <module name="org.apache.commons.logging"/>
            <module name="org.jboss.logging.jul-to-slf4j-stub"/>
      </exclusions>
      </deployment>
  </jboss-deployment-structure>

Application logging is configured as described in the section Logging configuration.

8.10.4. Container logging

A common logging configuration uses log4j and a local logging configuration within the deployed WAR file. The resulting logs will typically be written to an application-specific log file, separate from any log files that may be used by the container in which the application is deployed.

An alternative logging approach is to delegate the logging to the container, allowing the logs from both the container and the application to be written to a single log file and controlled using a single logging configuration. The following sections describe the required configuration for this setup using some common application containers.

Tomcat container logging

The Tomcat application server uses a custom logging implementation for server logging that is not supported by an slf4j adapter. For this reason we cannot simply delegate the logging to the container in the default configuration. To use container logging, the server must be reconfigured to use log4j as described on the following web page:

When the server has been reconfigured in this way, you just need to remove the log4j library from the project by excluding it explicitly when the slf4j-to-log4j adapter is included. The slf4j-to-log4j adapter will then find the log4j implementation from the Tomcat lib directory and use it for all edoras one logging. You will also need to remove the project log4j.properties file, and transfer any required edoras one logging configuration to the container log4j.properties file.

If you have unit tests in your project then you will also need to add a testing runtime dependency for the log4j library, as the unit tests will not have access to the log4j library in the Tomcat container.

Maven dependency configuration
Tomcat container logging configuration in the Maven pom.xml
  <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>${org.slf4j.version}</version>
          <scope>runtime</scope>
          <exclusions>
                  <exclusion>
                          <groupId>log4j</groupId>
                          <artifactId>log4j</artifactId>
                  </exclusion>
          </exclusions>
  </dependency>

  <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
          <scope>test</scope>
  </dependency>
Gradle dependency configuration
Tomcat container logging configuration in the Gradle build.gradle
  // Route the logs to log4j ...
  runtime("org.slf4j:slf4j-log4j12:$slf4jVersion") {
    // ... where log4j itself is supplied by the Tomcat container
    exclude group: 'log4j', module: 'log4j'
  }

  // we still need a local log4j library for testing
  testRuntime "log4j:log4j:1.2.17"
JBoss container logging

The JBoss application server supports all of the logging frameworks used in edoras one, so to use JBoss container logging it is only necessary to do the following:

  • remove the logging dependencies

  • remove the julReroute bean definition from the application’s Spring configuration

  • remove the logging configuration file log4j.properties (or move it to the test source tree if it is still needed for unit testing)

  • remove the file WEB-INF/jboss-deployment-structure.xml

If the project contains unit tests, however, the logging dependencies will need to be retained and moved to the test scope as shown below.

Maven dependency configuration
JBoss container logging configuration in the Maven pom.xml
  <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>jul-to-slf4j</artifactId>
          <version>${org.slf4j.version}</version>
          <scope>test</scope>
  </dependency>
  <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>jcl-over-slf4j</artifactId>
          <version>${org.slf4j.version}</version>
          <scope>test</scope>
  </dependency>
  <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>${org.slf4j.version}</version>
          <scope>test</scope>
  </dependency>
Gradle dependency configuration
JBoss container logging configuration in the Gradle build.gradle
  // Retain test dependencies for unit testing ...
  testRuntime "org.slf4j:jul-to-slf4j:$slf4jVersion"
  testRuntime "org.slf4j:jcl-over-slf4j:$slf4jVersion"
  testRuntime "org.slf4j:slf4j-log4j12:$slf4jVersion"

9. CMMN Documentation

9.1. Design & Implementation Notes

9.1.1. CMMN Specification Issues (and interpretations) 

During the course of implementing a working CMMN engine based on CMMN specification version 1.0, a number of specification issues were identified. This section lists the issues that popped up and explains how the current implementation of the edoras one CMMN engine deals with it.

ManualActivationRule

The item control is called ManualActivationRule. The symbol is modeled after a tape recorder play button. Having the symbol on a model element means that there is a manual activation rule configured for the element. By naming (and table 5.40 in the spec), a rule evaluating to 'true' means manual activation. Not specifying a rule should, according to the specification (figure 5.12) also evaluate to a value of 'true'. This leads to the situation where both of the following tasks have manual activation. This looks like a contradiction and is confusing for modelers as they, in order to configure automatic activation, must define a manual activation rule that resolves to false.

manualActivation

We decided to handle this differently. In the current implementation, a missing manual activation rule defaults to false, meaning automatic activation. Thus, the task on the left auto starts. Another advantage of this is that all missing plan item controls (manual activation, repetition, required) default to false in the case of a missing rule.

In addition, Automatic activation by default is, in our experience, the better choice for the case plan model itself (no symbol) and a better default (because more common) for stages, process tasks and case tasks.

Sentry Evaluation

The order and logic related to the evaluation of sentries of a CMMN model is not specified in CMMN specification version 1.0. Because of this, the runtime-evaluation of CMMN models in our implementation is likely to differ from other vendors. edoras one CMMN works as follows:

Triggering plan items

A plan item transitions from AVAILABLE to ACTIVE (or ENABLED) based on its entry sentry configuration and the transitions the sentry’s on-part items undergo (if any).

Plan items are created and made AVAILABLE as their parent container (Case Plan Model or Stage) starts. From that point on, a plan item will listen to a trigger event. Possible trigger events (conditions) are:

  • the plan item has no entry sentry. In this case it will immediately trigger (as part of the same event processing cycle that created it).

  • the plan item has at least one entry sentry that triggers (logical OR among multiple sentries).

An individual sentry triggers under the following conditions:

  • it has no condition (expression) and no on-parts.

  • it has a condition (expression) and no on-parts, and the condition evaluates to true.

  • it has one or more on-parts, the on-parts fire, and there is either no condition or a condition evaluating to true.

A sentry’s on-parts (one or more) fire under the following conditions:

  • if there is one on-part, it fires if the on-part item it listens to undergoes the desired transition as part of the current event processing cycle.

  • if there are more than one on-parts, the sentry fires if at least one of the on-parts fire and all other on-part items' last transition (possibly from an earlier event processing cycle) equal the one the on-part is configured for.

    In other words, multiple on-parts of a single sentry form a logical AND. In order for the sentry to trigger, at least one of the on-parts must trigger as part of the current event processing cycle and all (!) other on-part items must have undergone the desired transition as their last transition (but not necessarily during the same event processing cycle).

Current implementation

Our current CMMN engine implementation behaves according the rules described above, with the following exception:

  • The first instance of a plan item with one or more on-parts may trigger merely based on a sentry condition turning to true, provided the on-parts are satisfied. This is the default behaviour of sentries in edoras one CMMN. This type of trigger mode is called "Event deferred".

The behaviour can be described has having a memory effect. For example: We have a plan item with a sentry holding a condition and an on-part. The condition is false. At some point, the on-part item undergoes the desired transition. Now, during some later event processing cycle, the condition switches to true. The plan item triggers.

Starting with edoras one S104, a second type of trigger mode is available. It is called "On event" and does not exhibit the memory effect described above. The trigger mode can be selected on sentry elements in the VIS modeler.

A third trigger mode called "Deferred repetition" is under discussion. The idea is to record on-part transitions that happen as the sentry condition is false. Then, as the sentry condition turns to true, the recorded transitions would be played back in the order they occurred, potentially triggering multiple instances of the sentry’s plan item.

Deferred sentry evaluation (i.e. considering element transitions in sentry on-parts that were observed in a previous model evaluation cycle) are not only relevant in combination with sentry conditions but also in situations where the model element owning the sentry is created at a later point in time. Consider the following situation:

triggerMode

The bottom task will exit as either one of the top two tasks completes. The sentry referring to the top-right task uses trigger mode "Event deferred". If we start the case, complete the top-right task and then start the stage, the bottom task (the one in the stage) will immediately terminate due to the memory effect described above.

By choosing trigger mode "On event", this wont happen. The bottom task can only be exited via the top-left task’s completion if it exists at the point in time the top left task completes.

There is also a forum topic on sentry evaluation https://forum.edorasware.com/t/cmmn-sentry-evaluation-semantics/89

Implementing the RepetitionRule

The specification is not clear on how to handle the repetition rule in combination with sentry AND-conditions (multiple on-parts creating an AND condition an a sentry). The edoras one CMMN implementation is based on an algorithm that distinguishes between current and past event transitions.

On-Parts and Repetition (Multiplicity)

The specification is not clear on how to handle plan item or case file item on-parts that refer to potentially multiple runtime instances. Our implementation is based on an "at least one" approach.

Triggering repeatable plan items - current implementation

The first instance of a plan item triggers according to the rules defined under Sentry Evaluation, above. Subsequent instances only trigger if one or more on-parts trigger.

There is an extension in place for repeatable plan items that are configured for manual activation and don’t have a sentry with on-parts. If such a plan item completes, it will create and trigger a new instance of itself.

A plan item can trigger itself, directly or indirectly via some plan item on-part configuration like an on-part connection onto itself. Potential infinite loops must be caught via a suitable sentry condition.

The CMMN engine enforces a configurable maximum recursion limit as a safety precaution. This limit can be configured by setting custom property triggerLimit on the Case plan model to the desired maximum number. Without explicitly setting this property, the limit is set to 1. This means that during a given model evaluation cycle, a maximum number of 1 new instances can be triggered for a given model plan item and parent stage instance.

The sentryRef Dilemma

The following is a legal diagram fragment:

exitSentries

The modeler’s intention in this example is: The ExitSentry of Task 2 has a PlanItemOnPart referring to Task 1 having a sentryRef pointing to the ExitSentry of Task 1. The meaning: Task 1 exiting via the one ExitSentry triggers the exit of Task 2. The problem: just by looking at the diagram, it is not clear which ExitSentry holds the PlanItemOnPart. There should be an arrow or some other symbol indicating the direction of the connector (the PlanItemOnPart).

Parent Termination of Event Listeners and Milestones

The CMMN 1.0 XSD doesn’t include a PARENT_TERMINATE transition as depicted in table 7.9 of CMMN specification 1.0. The edoras one CMMN engine uses the EXIT transition instead.

Transitions on plan items within terminal stages

According to CMMN 1.0 specification, completing a stage (unlike terminating it) doesn’t propagate the completion to any child plan items. This means that, as a stage completes, child plan items remain in their current state. This leads to questions regarding child plan items that are in a non-terminal state like AVAILABLE or ENABLED. What should happen if a legal transition on such a plan item is attempted once the parent stage has been completed?

In the current implementation of the edoras one CMMN engine, the transition PARENT_COMPLETE is introduced and used to terminate child plan items in state AVAILABLE or ENABLED. This new transition is used internally. The transition can not be captured by a plan item on-part in the model. The resulting state of a PARENT_COMPLETE transition on a plan item is state EXPIRED.

Discretionary Items and Sentries

5.4.9.2 of the specification mentions entry and exit criteria with respect to discretionary items as supported. Figure 5.12 states that DiscretionaryItems are not associated with Sentries. Entry and exit criteria references are modeled in the XML (XSD) only on PlanItems. Not on DiscretionaryItems. The current implementation of the CMMN engine does not support sentries on Discretionary Items.

Non-Blocking Tasks and Exit Sentries

Tables 5.18 and 5.29 in the CMMN 1.0 specification rule out the use of exit sentries for plan items that are non-blocking. In the current edoras one implementation, however, we allow such exit sentries. There are use-cases where it makes perfect sense to exit a plan item in a not yet started state like AVAILABLE or ENABLED, at which point the setting of the plan item’s Blocking property is not relevant (and thus should not disallow it).

9.1.2. CMMN Extensions 

Custom Attributes

An arbitrary map of custom String/String properties can be edited during design time and stored on select CMMN elements:

The map is serialized to JSON and stored under attribute customAttributes in the XML. The purpose of these properties is to configure certain CMMN extensions like repeatable user event listeners. Customer implementation extensions can also make use of these properties to implement custom logic based on arbitrary design-time properties.

The elements for which custom attributes are supported are:

  • Case (case plan model)

  • Stage

  • Process task

  • Service task

  • Human task

  • Case task

  • Milestone

  • User event listener

  • Event listener (external events)

  • Case file item (stored in 'caseFileItemDefinition' XML element)

Except for the case file item, the customAttribute is stored as part of the item’s PlanItemDefinition.

Automatic repetition

The CMMN repetition rule allows to create multiple instances of a given model plan item. The triggering of a plan item (START, ENABLE or OCCUR) is controlled by sentries. Only a Sentry with on-parts that fire may lead to the creation and triggering of an additional instance of the plan item.

By introducing the Automatic repetition extension, it is possible to automatically trigger the creation of a new instance of a plan item as it completes. For this to work, a plan item must be configured as follows:

  • The manual activation rule must resolve to true

  • The repetition rule must resolve to true

  • The plan item must not have any on-parts. (If there are on-parts, the on-parts will be responsible for the creation of new plan item instances.)

If this is the case, a plan item can repeatedly be created by means of an action button under Available Actions in the case HTML template. The action button becomes available as the previous plan item instance completes.

repetition

In the picture above, the two Human task configurations are identical (the on-part event of the Human task on the right hand side is 'complete'). Automatic repetition is simply a modelling short-cut for the pattern on the right hand side with event 'complete'. If you want to be able to create multiple task instances at the same time, consider using the pattern on the right with event 'manualStart'.

The CMMN specification 1.0 states, that a plan item’s repetition expression is evaluated at the point of the plan item’s creation (transition to AVAILABLE) and maintained throughout the life cycle of the plan item. The current implementation handles this differently: The engine evaluates the rule on demand, i.e. each time a new plan item instance may potentially be created, the rule is evaluated.

Please note that automatic repetition may have an impact on stage auto-completion. Manually starting a plan item with automatic repetition leads to the activation of the plan item. As the plan item completes a new plan item instance is created and put into state 'enabled' in order to accept an additional click (i.e. MANUAL_START). This means that, with automatic repetition, by default, there is always an enabled instance of the repeatable plan item in the run-time model. With auto-completion off, this will prevent the parent stage from completing.

Automatic repetition as described above can be disabled on the level of the whole model by setting the following custom property on the case plan model:

repetition = standardCmmn
Plan Items and Stage Completion

In the edoras one CMMN implementation, plan items can be configured to be "completion neutral". If checked, the plan item will not prevent a stage from completing, meaning that such a plan item is neutral with respect to stage completion evaluation. The rationale to introduce this option is as follows:

Following the specification, a stage with a plan item in state Available does not complete unless we set the stage’s auto-complete flag to true. In many modeling situations, this forces us to set a stage to auto-completion as soon as we use a plan item which potentially may remain AVAILABLE. By treating such plan items as neutral, as now possible by setting the Completion Neutral option, we gain modeling flexibility in the sense that we can still use the auto-completion flag to model some other condition of a stage, for example, the handling of plan items in state ENABLED.

Manual Stage Auto-Completion

A special type of user event listener named Stage Auto Completion is available in CMMN models. This user event listener can be placed in any Stage. It can not be connected to any other item. It is typically placed into a stage which has Auto Complete set to off.

During run-time, this new event listener appears as an action button in the Case GUI if the stage it is part of would complete had it its Auto Completion property set to true. In other words, this new event listener will become available as soon as the stage can be completed in a normal way (in general as soon as there are no more active plan items). Clicking the action button for this user event listener will then complete the stage.

Repetition of User Events and External Events (User event listener, Event listener)

User events and external events support a custom property manualRepetition (simply named Repetition in the VIS properties editor). The value can be any back-end condition. If the condition evaluates to true, a new user event instance is created upon occurrence of the preceding one. This allows the modeler to create a user event button in the GUI which remains visible and can be invoked multiple times. For external event listeners this means that there is always an instance of the event listener available to receive an OCCUR transition.

Rule Evaluation

All edoras one CMMN rules and back-end expressions (like the required, repetition and manual activation rules) are evaluated on demand. There is no default logic in place to evaluate such a rule at the point in time a stage is activated (as the specification defines, for example, for the required rule). By evaluating such expressions on demand, the edoras one CMMN engine adds a great deal of modeling flexibility. For example, it is now easily possible to model plan items that repeat N times. The original evaluation logic can explicitly be modeled by a service task (or some other means) that executes at stage activation time and stores the result of a particular expression on the Case Work Item. By using such a stored variable as a rule expression, the original evaluation semantic is then effectively in place.

Cross-Stage Plan Item On-Parts

According to the specification (description of sourceRef in table 5.22 of CMMN Specification 1.0), plan item on-parts referring to plan items outside the sentry’s stage are not supported. In contrast to the specification, the current implementation of the edoras one CMMN engine allows such connections.

For example, the following diagram shows a valid edoras one CMMN model containing cross-stage on-parts. We have a down-hierarchy connection from task 3 to task 1 (task 3 listens to an event of a task residing in a sub-stage) and an up-hierarchy connection from task 2 to task 4 (task 2 listens to an event of a task residing in a parent stage):

crossStagePlanItemOnParts

Please refer to section CMMN Connectors ("on-parts") for more examples on cross-hierarchy connections and explanations on how they are resolved at run-time.

9.2. Developer Documentation

9.2.1. Integrating Custom Extension Code 

There are two ways to call custom extension code from a running CMMN case:

  1. Invoke custom code by means of a service task (by evaluating a runtime expression).

  2. Configure a custom CmmnActionListener implementation via your project Spring configuration

  3. Provide low-level custom implementations for plan item transitions.

The following sections describe the options in more detail:

Execute custom code by means of a Service Task

Service tasks are available in the palette and can be placed into the model like any task. By means of a runtime expression configured on the service task, arbitrary code can be executed as the runtime representation of the task starts. The result of the expression evaluation is stored in the case scope under the variable name provided by the modeler. Service tasks are non-blocking, meaning, as soon as they trigger, they evaluate the expression, store the result and complete.

Provide a custom CmmnActionListener implementation

The CMMN Spring context allows to specify one optional CmmnActionListener implementation as part of the DefaultCmmnEngine bean configuration. The CmmnActionListener exposes the two methods

void actionWillBePerformed(CmmnActionEvent cmmnActionEvent);

and

void actionPerformed(CmmnActionEvent cmmnActionEvent);

The methods will be called just before and just after the execution of a CMMN action. The types of actions for which the listeners are invoked are:

  • CASE_CREATION_EVENT

  • PLAN_ITEM_TRANSITION_EVENT

  • CASEFILE_ITEM_TRANSITION_EVENT

  • DISCRETIONARY_ITEM_PLANNING_ACTION_EVENT

  • MODEL_REEVALUATION_EVENT

The event types supported by the CmmnActionListener interface are high-level events. They allow to hook into top-level events of the CMMN engine - top-level events meaning external events imposed on the CMMN engine typically resulting from a user interaction or CMMN service call.

Please note that once such a top-level event is being processed, no additional top-level events will be generated as a result of the internal CMMN state update handling. This explains why there is a CASE_CREATION_EVENT but no event representing the completion (or closing) of a case. The closing of a case typically results as a consequence of a particular high-level event (like PLAN_ITEM_TRANSITION_EVENT). If you need to capture the completion (or termination) of your CMMN case, you will have to provide a custom transition handler for the COMPLETE and/or TERMINATE transitions of the CasePlanModel (see next section). Note: An alternative way to capture Case creation and completion events would be to re-configure the CmmnCaseProvider via Spring.

Provide custom implementations for plan item transitions

This is a very flexible and powerful yet low-level way of integrating custom Java code into a case model. Using this approach, the complete edoras one implementation of the CMMN engine can be replaced with custom implementation code. Replacing, extending or hooking into a select sub-set of the existing implementation classes is possible too. In order to introduce a custom transition handler for a given plan item, the following steps are necessary:

  1. Define a bean with name cmmnExtensions implementing interface CmmnExtensions or extending DefaultCmmnExtensions.

  2. In your CmmnExtensions class, implement the method of you choice to return your handler implementation. E.g. implement method getOccurExtension(..) to return your implementation of an OccurHandler.

  3. Your implementation of the handler must extend the appropriate abstract handler (e.g. the OccurHandler) and implement the generic handler method

public abstract Object handleTransition(PlanItem planItem, TransitionData transitionData,
                                        EngineListeners engineListeners,
                                        PersistenceListeners persistenceListeners);

It is possible to selectively return handlers. The methods in interface CmmnExtensions all have the same signature: they receive

  • the type of plan item for which to return the custom handler

  • an arbitrary string. The string is called extensionType and can be provided in your model as a custom property with name extensionType. (E.g. define the custom attribute (key/value pair) extensionType=MyExtension on your model element)

Based on these parameters you can decide which custom handler implementation (if any) you want to return. By returning null, the default edoras one handler implementation will be used.

If you decide to return a custom handler, you have the option to completely replace the default implementation or to invoke your handler code before or after the default implementation code. Check out method getExtensionPoint() in class BaseHandler. If you don’t override getExtensionPoint(), your code will replace the default implementation code.

Please refer to the table on page Standard CMMN State Transition Implementations in order to get an overview of the available default edoras one implementation handlers and their purpose.

9.2.2. Storing custom plan item state

Plan item run-time instances feature a map of key/value pairs of type string that can be used by modelers and extension code writers to persist custom run-time information. Custom plan item state can be stored on a plan item instance as soon as the instance is created (i.e. in state AVAILABLE). The state is kept throughout the life-cycle of the plan item. It is persisted as part of the CMMN engine run-time state.

State can be written in extension code via method setCustomState(String key, String value) on the passed plan item instance. State values can be read via getter getCustomState(String key).

By using the prefix _customState_ in variable names, custom key/values can be stored via target variable references (e.g. by service tasks or output parameter maps).

This feature is not optimized to store significant amounts of data. Please restrict its use to the storing of small strings like IDs.

9.2.3. Standard CMMN State Transition Implementations 

The edoras one CMMN engine implementation is split into two parts:

  • A generic CMMN engine implmenentation

  • Edoras one integration code

The edoras one integration code is implemented per PlanItem type and CMMN transition type. The following table outlines which particular integration methods are provided for the various plan item types and transitions. The table also shows the purpose of the available edoras one implementations.

The main goal of the table is to support edoras one customer code developers in the task of implementing CMMN extensions. The table shows which standard implementations are available. Based on the table, developers of extensions can decide which hooks they want to extend or override.

Empty cells in the table mean that there is no edoras one implementation needed. There is code executed for the cell (transition and plan item type) within the CMMN state model, however, there is no need to take an action on edoras one Work Items.

CasePlanModel Stage HumanTask ProcessTask (BPMN) ProcessTask (Service task) CaseTask Milestone UserEventListener

create

Creates and starts a Case Work Item for the CMMN case represented by the CasePlanModel.

Updates the clientRef field of the task plan item.

enable

manualStart

Starts the HumanTask (see 'start').

Starts the BPMN process (see 'start').

Executes the service task (see 'start')

Starts the CaseTask (see 'start').

start

Creates and starts the Task Work Item referenced by the HumanTask. The Task is based on an AdHoc Task Definition. AdHoc Task Definitions for HumanTasks are created during deployment of the CMMN Case model.

Creates and starts a Process Work Item.

Executes the service task

Creates and starts a new CMMN StateModel for the Case referenced by the CaseTask. This leads to 'create' of the CaseTask’s CasePlanModel.

occur

complete

Completes the Case Work Item (archives the case).

Collects output parameters from the completed task and stores them on the case.

Collects output parameters from the completed process and stores them on the case.

Collects output parameters from the completed case task and stores them on the case.

exit

Sets the sub-state of the HumanTask work object to INTERRUPTED.

Cancels the process.

Terminates the case represented by the CaseTask.

disable

re-enable

fault

reactivate

terminate

Completes the Case Work Item (archives the case).

Same as for 'exit'

Same as for 'exit'

Same as for 'exit'

Case auto-completion handling

After having applied an external event to a StateModel (like after applying a state transition), a StateModel’s auto-completion is evaluated. If a StateModel completes due to auto-completion (or otherwise is considered exited/terminated), and if the StateModel represents a CaseTask, then a suitable transition (complete, exit or terminate) is triggered in the parent Case for the CaseTask that was just completed/exited/terminated.

9.2.4. CMMN Service API

The standard edoras one Spring configuration contains a bean named cmmnService. The bean exposes methods that allow client projects to invoke actions on CMMN case instances.

Calls invoking state change
Re-evaluate a case state model
void handleStateUpdate(WorkObjectId caseId, TransitionData transitionData);

This method re-evaluates the model, evaluating all relevant sentries and other expressions. Any necessary state changes resulting from expressions are applied to the model. See parameter section for details on method parameters.

Invoke a plan item transition on a CMMN case instance
void handlePlanItemTransition(WorkObjectId caseId, String planItemId, PlanItemTransition planItemTransition, TransitionData transitionData);

This method applies the passed plan item transition to the selected plan item and re-evaluates the model. See Common CMMN service call parameters for details on method parameters.

Invoke a case file item transition on a CMMN case instance
void handleCaseFileItemTransition(WorkObjectId caseId, String caseFileItemId, CaseFileItemTransition caseFileItemTransition, TransitionData transitionData);

This method applies the passed case file item transition to the selected case file item item and re-evaluates the model. See Common CMMN service call parameters for details on method parameters.

Invoke a discretionary item planning action on a CMMN case instance
void handleDiscretionaryItemPlanning(WorkObjectId caseId, String discretionaryItemId, TransitionData transitionData);

This method 'plans' the selected discretionary item and re-evaluates the model. See Common CMMN service call parameters for details on method parameters.

Query CMMN run-time state

These are high-level query methods to get information about a particular running CMMN case. All of these methods return simple Java types or CMMN implementation interfaces

Get a particular plan item instance by Id
PlanItemView getPlanItem(WorkObjectId caseId, String planItemId, TransitionData transitionData);

The method returns a view object on the selected plan item. The returned PlanItemView exposes the same properties as the ones documented for _planItem in the section CMMN Expressions. See Common CMMN service call parameters for details on method parameters.

Get a list of plan items of a given type
List<PlanItemView> getPlanItems(WorkObjectId caseId, Class<? extends PlanItem> planItemType, TransitionData transitionData);

The method returns a list of PlanItemViews. Each PlanItemView exposes the same properties as the ones documented for _planItem in the section CMMN Expressions. See Common CMMN service call parameters for details on method parameters.

Note: This method is identical to the next one passing singleInstanceMode=false.

Get a list of plan items of a given type (optional "single instance mode" parameter)
List<PlanItemView> getPlanItems(WorkObjectId caseId, Class<? extends PlanItem> planItemType, boolean singleInstanceMode, TransitionData transitionData);

The method returns a list of PlanItemViews. Each PlanItemView exposes the same properties as the ones documented for _planItem in the section CMMN Expressions. See Common CMMN service call parameters for details on method parameters.

Query the CMMN run-time model of a case and return information on a particular plan item instance.
Map<String, Object> getPlanItemProperties(WorkObjectId caseId, planItemId, String[] properties, TransitionData transitionData);

Returns a map containing information on the selected plan item. The map contains the property name/value entries as defined by the properties parameter. See Common CMMN service call parameters for details on method parameters.

Query the CMMN run-time model of a case and return information on plan item instances.
List<Map<String, Object>> getPlanItemProperties(WorkObjectId caseId,
Class<? extends PlanItem> planItemType, boolean singleInstanceMode, String[] properties,
TransitionData transitionData);

The method returns the list of matching plan item instances. Each plan item instance in the returned list is represented by a map. Each map contains the property name/value entries as defined by the properties parameter. See Common CMMN service call parameters for details on method parameters.

Get the list of current states (milestones and stages) for a CMMN case instance
List<CurrentState> getCurrentStates(WorkObjectId caseId, TransitionData transitionData);

The method returns the list of current states of the case (states of stages and milestones). See Common CMMN service call parameters for details on method parameters.

Get the list of available actions for a CMMN case instance
List<AvailableAction> getAvailableActions(WorkObjectId caseId, TransitionData transitionData);

The method returns the list of available actions for the case. See Common CMMN service call parameters for details on method parameters.

Query CMMN run-time state (low-level methods)

These are low-level query methods to get information about a particular running CMMN case. These methods return actual implementation objects. Whenever possible, use one of the higher-level methods above.

Get a particular plan item instance by Id
PlanItem getPlanItemInstance(WorkObjectId caseId, String planItemId, TransitionData transitionData);

The method returns the selected PlanItem. All public properties of the PlanItem class are accessible. See Common CMMN service call parameters for details on method parameters.

Get the plan item representing the Case Plan Model of a case
CasePlanModel getCasePlanModel(WorkObjectId caseId, TransitionData transitionData);

The method returns the selected CasePlanModel. All public properties of the CasePlanModel class are accessible. See Common CMMN service call parameters for details on method parameters.

Get a list of plan item instances of a given type
List<PlanItem> getPlanItemInstances(WorkObjectId caseId, Class<? extends PlanItem> planItemType, TransitionData transitionData);

The method returns a list of PlanItems. All public properties of the PlanItem class are accessible. See Common CMMN service call parameters for details on method parameters.

Note: This method is identical to the next one passing singleInstanceMode=false.

Get a list of plan item instances of a given type (optional "single instance mode" parameter)
List<PlanItem> getPlanItemInstances(WorkObjectId caseId, Class<? extends PlanItem> planItemType, boolean singleInstanceMode, TransitionData transitionData);

The method returns a list of PlanItems. All public properties of the PlanItem class are accessible. See Common CMMN service call parameters for details on method parameters.

Get a list of case file item instances of a given definition type
List<CaseFileItem> getCaseFileItemInstances(WorkObjectId caseId, String definitionType, TransitionData transitionData);

The method returns a list of CaseFileItem instances. All public properties of the CaseFileItem class are accessible. See Common CMMN service call parameters for details on method parameters.

Utility methods
Create a TransitionData object with one or more parameters

This call allows to create a TransitionData object containing one or more parameter key/value pairs. The method can be used to construct a TransitionData object that is then passed to any of the service call methods above accepting a TransitionData object.

TransitionData parameters(String key, Object value, ...);
Create a TransitionData object with one or more form data items

This call allows to create a TransitionData object containing one or more form data key/value pairs. The method can be used to construct a TransitionData object that is then passed to any of the service call methods above accepting a TransitionData object.

Note: to pass both, parameters and form data to a service method, use this helper to construct a TransitionData object. Prepend keys with the prefix _param_ to mark them as parameters.

TransitionData formData(String key, Object value, ...);
Resolve a work object Id

Best effort work object Id resolution. Typed work object Ids may get converted to a string during a front-end round-trip. This method returns the input parameter unchanged if it is of type WorkObjectId. Otherwise, if it is of type String, it tries to convert it into a WorkObjectId and returns it. Otherwise returns null.

WorkObjectId resolveId(Object workObjectId)
Resolve an external work object Id

Similar to `resolveId(Object)' with the difference that the Id passed in the input parameter is expected to be an external work object Id. The Id returned is the external Id’s internal Id.

WorkObjectId resolveExternalId(Object workObjectId)
Common CMMN service call parameters
Parameter caseId

Case IDs in the API calls below are expected to be Case Work Object Ids. Should you only have access to an external case Id, use method resolveExternalId(Object) to convert an external Id to the internal Id expected in the CMMN service call. For example:

cmmnService.handlePlanItemTransition(cmmnService.resolveExternalId(<my-external-id>), ...
Parameter planItemId

The planItemId parameter in the methods below is used to identify a plan item instance. You can pass any one of the following IDs (they will match in the order given):

  • id (the plan item model Id). For example: onehumantask1. When passing a model Id in a context where an instance Id is expected, the model Id will always map to the most recent (i.e. highest instance index) instance of the plan item.

  • instanceId (the plan item instance id, i.e. the model Id with the instance suffix). For example: onehumantask1~3

  • clientId (the plan item’s client Id, where applicable; for example a Human task’s work object Id)

  • clientRef (the plan item’s client reference, where applicable; for example the process reference of a Process task)

In case of ambiguities (e.g. when passing an id or clientRef to a model with multiple instances of the respective plan item), the most recent plan item instance (the one with the highest instance suffix) is selected. If the plan item is available in multiple parent stage instances, the highest plan item instance from the highest stage instance is selected.

Parameter caseFileItemId

The caseFileItemId parameter in the methods below is used to identify case file item instances. Pass either a case file item Id or a case file item instance Id. When passing a case file item Id, it will match the most recent (highest index) instance available.

Parameter transitionData

The optional TransitionData parameter in the method calls below can be used to pass form data or parameters along with the call. Simply construct a new TransitionData object (using either the empty constructor or a constructor with a parameter map) and pass it along with your call. The parameter is optional. It can be omitted or passed as null.

Use one of the service methods parameters(…​) or formData(…​) to construct a TransitionData object to be used in a call to one of the service methods accepting TransitionData.

Parameter singleInstanceMode

This can be used to limit the number of instances per plan item model element to 1. If true, zero or one instance is returned per model plan item (zero for plan items that have not been created yet, i.e. for plan items that are part of a stage that has never been started). The particular instance that is returned if there are multiple instances available for a repeatable plan item is the one with the highest instanceIntId (or index), i.e. the most recent one.

Parameter planItemType

This parameter is used to filter the types of plan items. Passing null maps to PlanItem which is the base class for all plan item types and thus includes all types of plan items. You can specify any of the following classes:

planItemTypes

Parameter properties

This parameter contains the comma-separated list of properties you’re interested in. Each property will be returned as a map entry (property name/value). The properties that are available are the same ones that are available in back-end expressions for the _planItem key word. See CMMN Expressions.

9.2.5. edoras one CMMN configuration properties

This section describes the System properties that are supported by the CMMN engine. They are typically added to the one.properties file.

Property cmmn.planitem.exposed-model-types

This property allows to expose CMMN plan item model elements by model Id on the deployed Case definition. It takes the form:

cmmn.planitem.exposed-model-types = <comma-separated list of model plan item types; see below>

The property receives a comma-separated list of plan item types. The possible plan item types are:

planItemTypes

The types honor hierarchy, so by setting a property value of PlanItem, all plan item model Ids in the CMMN model will be exposed.

The model Ids will be written to a Case definition Work Object variable named cmmnModelIds_<plan-item-type-from-property-value>. As many work object variables will be created as there are comma-separated elements in the property value.

Note: the stage representing the CasePlanModel will never be output. This is due to the structure of the CMMN XML where the CasePlanModel stage does not have a corresponding plan item element.

For example, by specifying property

cmmn.planitem.exposed-model-types = UserEvent, ExternalEvent

The following work object variables will be created and stored on the Case Definition Work Object:

cmmnModelIds_UserEvent
cmmnModelIds_ExternalEvent

The variables will list the model Ids of the named types that are modeled in the CMMN model.

Note: by making use of the plan item type hierarchy, you can expose the same model Ids in one result variable. To do so just specify a property value of EventListener.

Property cmmn.planitem.exposed-types

This property, in combination with property cmmn.expose.planItemStates, allows to expose CMMN run-time plan item states as Case Work Object variables. The property is defined like:

cmmn.planitem.exposed-types = <comma-separated list of model plan item types>

The property takes a comma-separated list of plan item types (similar to property cmmn.planitem.exposed-model-types). For more information, see the description for the next property.

Property cmmn.expose.exposed-states

This property, in combination with property cmmn.planitem.exposed-types, allows to expose CMMN run-time plan item states in Case Work Object variables. The property is defined like:

cmmn.planitem.exposed-states = <comma-separated list of CMMN plan item states>

The property takes a comma-separated list of plan item states. Possible states are: AVAILABLE, ENABLED, DISABLED, ACTIVE, FAILED, SUSPENDED, TERMINATED, COMPLETED, CLOSED, EXPIRED (EXPIRED is a non-standard CMMN state used to mark plan items that were in states {AVAILABLE, ENABLED}, as their parent stage completed). The key word ALL is supported to expose all of the above states.

The result of defining properties cmmn.planitem.exposed-types and cmmn.expose.planItemStates are Case Work Object variables named after the naming scheme described below, each containing a comma-separated list of zero or more CMMN run-time plan item instance Ids.

The generated Case Work Object variables are named according to the following pattern: _cmmn_states_<plan-item-type-from-property-value>_<plan-item-state-from-property-value>. Each variable lists the plan item instance Id(s) for the respective combination of plan item type and CMMN state.

For example, by specifying properties

cmmn.planitem.exposed-types = ExternalEvent
cmmn.planitem.exposed-states = AVAILABLE, ENABLED

The following work object variables will be created and stored on the Case Work Object:

_cmmn_states_ExternalEvent_AVAILABLE
_cmmn_states_ExternalEvent_ENABLED

The variables will list the plan item instance Ids of all plan items of type ExternalEvent that are in the respective state (AVAILABLE or ENABLED). If there are no states for a particular type and state combination, the value stored under the respective case variable will be the empty string.

Adapting to configuration changes

Any state case variables maintained via these configuration properties that have become obsolete (their configuration changed such that their type/state combination is no longer exposed) are set to a value of null. This is in contrast to a value of an empty string, indicating, that the variable is maintained but the case doesn’t currently hold any plan items for the respective type/state combination.

9.3. User Documentation

9.3.1. Current Feature Overview 

This page describes the scope of the initial edoras one CMMN engine implementation.

Important: When running CMMN cases, make sure the case template is selected (make sure your URL starts with /case.html#…​). If not, simply edit it in the browser’s address bar and reload the page.

Plan Items and Case File Items
Stages

A case can be structured by using stages. Stages can be nested. As of sprint 85, stages can be visuaized in the case template. See CMMN Stage and Milestone Visualization.

Plan fragments

Plan fragments can be put into a model. They allow to group individual plan items. Plan fragments do now have a run-time representation and no associated functionality other than to provide a means to enclose a bunch of plan items.

Process tasks

edoras one process tasks can be placed in a model and wired up using connectors and sentries. Input/output is handled via input and output parameter maps that can be modeled on the Process task element.

Service tasks

Service tasks can be placed into a model like any other task. When triggered, a service task evaluates a back-end expression and stores the evaluation result in the scope of the case under a variable name provided by the modeler. Service tasks are non-blocking. They immediately complete once the result is stored in the result variable.

Send mail task

A Send mail task is a special type of Service task which allows to send out e-mail notifications.

Create document task

A Create document task is a special type of Service task which creates a document instance from a document model and associates it with the case by setting the case as pareent.

Initialize variables task

An Initialize variables task is a special type of Service task which allows to initialize a set of variables on the Case Work Item (or arbitrary target Work Items).

Add comment task

An Add comment task is a special type of Service task which creates a Work Item text comment on an arbitrary target Work Item (the Case by default).

Dmn rule task

A Dmn rule task is a special type of Service task which evaluates Dmn rule and sets the outputs as a variables to the case scope.

Human tasks

Ad-hoc human tasks can be placed in a model and wired up using connectors and sentries. Input/output is handled via input and output parameter maps that can be modeled on the Human task element.

Human tasks have an init form and a work form. The work form is the main form. Where applicable, the init form is used (e.g. when starting a human task with manual activation from the case actions menu).

Case tasks

Case tasks can be placed in a model and wired up using connectors and sentries. Input/output is handled via input and output parameter maps that can be modeled on the Case task element.

Case file items

Case file items can be placed in a model. Currently only one Case file item type is supported:

DefinitionType: edorasCaseVariable. By using this case file item type, a case file item can be modeled which refers to a variable of the Case Work Object. As the variable changes, corresponding Create/Update/Delete events are triggered on the case file item.

The following features/restrictions apply: 1) Multiplicity is not supported. Please leave the corresponding field empty in the model. 2) Only top-level variables can be addressed (i.e. a simple variable name with no dots). If the variable holds an array or map, updates to the array or map will result in an update event of the modeled variable (Add Child/Remove Child events are currently not supported). 3) The Delete event is triggered in situations where the variable is set to null. An initial create of the variable (or re-set after a Delete event) will trigger a Create event. Any other update to the variable will trigger an Update event.

Milestones

Milestones can be placed in a model and configured via sentries. Reached milestones are visible in the case template. As of sprint 85, additional options for milestone visibility is available. See CMMN Stage and Milestone Visualization.

User events

Support for User events. As of sprint 84, user event listeners can be configured to be invoked more than once. See See CMMN Extensions (Repetition of User Events).

Timer events

Timer events can be modeled via the Timer event listener model element. Absolute times, relative times (durations) and repeating timers are supported by the model element. The CMMN timerStart property is currently not supported. However, it can easily be modeled by placing the Timer event listener into a stage and thus controlling the timer starting point via the stage’s life-cycle.

Generic events

External system events can be modeled by means of a generic event listener symbol. Such events can be triggered using the CMMN service.

HTML template

The existing case.html template is supported. In particular the areas:

Active Work Items - For active human tasks and active work items from process tasks and case tasks.

Case File Items - For created case file items

Case Actions - For the starting of tasks with manual activation and for the creation of case file items (according to their multiplicity property)

Sentries and Events

Sentry If-conditions are supported (evaluated in the context of the case).

Connectors to tasks and stages are supported (plan item on-parts). Supported transitions:

  • CREATE

  • ENABLE

  • MANUAL_START

  • START

  • COMPLETE

  • EXIT

  • TERMINATE

Transitions SUSPEND, RESUME, PARENT-SUSPEND, PARENT-RESUME are not yet supported. CLOSE (on the level of the case) is not supported. Instead, once a case reaches COMPLETED or TERMINATED, it is archived (edoras one ARCHIVED state).

The events

  • DISABLE

  • REENABLE

  • FAULT

  • REACTIVATE,

are supported by the CMMN service and custom transition implementations (extension code) for plan items (except the case itself). There is currently no GUI support available to trigger these events and limited support for their visualization (visualization is only supported for DISABLE - disabled stages don’t appear in the currentStates list, and disabled tasks and stages do not generate an action entry in the availableActions list).

The transition

  • OCCUR

is supported for Milestones and Event listeners. The resulting state is COMPLETED.

Connectors to case file items are also supported (case file item on-parts). Supported transitions:

  • CREATE

  • UPDATE

  • DELETE

Roles

Support for the formal modelling of CMMN roles is not implemented. However, support for access control based on the concept of edoras one "candidate users" and "candidate groups" is provided for Human tasks and the control of the visibility of action buttons (available actions).

Discretionary Items and planning

Discretionary items planning has been partially implemented. However, support in the modeler and the Case Template (case.html) has been removed due to the limited value of the current implementation. The whole planning aspect will be re-addressed at a future point in time.

Simple optional tasks can be modeled on the basis of normal plan items, by setting the Manual start attribute and possibly using a run-time expression for the Required attribute.

PlanItem properties

Repetition - the Repetition property is supported, including the dynamic evaluation of an expression to determine the property value. If repetition == true, new plan item instances are created depending on entry sentry evaluation.

Manual activation - the ManualActivation property is supported, including the dynamic evaluation of an expression to determine the property value. For manual activation items, menu entries are made available in the Case Actions menu for the starting of these items.

Required - the Required property is supported, including the dynamic evaluation of an expression to determine the property value. The Required property is relevant for the determination of a Stage’s completion status (AutoComplete flag on the Stage).

Blocking - By default, tasks are blocking, meaning their transition to COMPLETE is triggered by an event outside of the case engine (i.e. by a case worker explicitly completing a HumanTask). By modeling a task as non-blocking, the engine immediately completes the task after START (or MANUAL_START).

Autocomplete - the Autocomplete property is supported for stages.

Custom PlanItem attributes

Custom plan item model attributes (name/value pairs, both simple strings) are supported for plan items and case file items.

Custom attributes are needed to extend or qualify the execution semantics in the context of client integration projects.

Custom PlanItem state

Custom plan item run-time state (name/value pairs), both simple strings) are supported for plan items. Custom state properties allow to store small bits of information on a plan item run-time instance.

Please refer to Storing custom plan item state for more information.

CMMN Case migration

The run-time state of a running CMMN case can be migrated from its current model XML to a more recent model XML. This feature is able to automatically adapt the persisted state of the running case to the new model structure. The feature currently only supports structural model changes. It does not cater for changes of variable names or other changes related to the way the modeler chooses to store data on work objects.

Please refer to CMMN run-time Case migration for more information.

9.3.2. CMMN Stage Completion

To know and understand the circumstances under which a CMMN stage completes or terminates is an essential prerequisite for the successful modeling of CMMN cases. This section explains the logic behind stage completion and describes the modeling options that are available to configure and control the completion of a particular stage of a running model. 

The following illustration summarizes stage completion logic. Detailed descriptions are presented in the sections below the picture.

stage completion
Relevant plan item states for stage completion

The states of the plan items contained in a stage at run-time determine stage completion ("plan item" is the general term for modelling elements like stages, tasks, milestones and event listeners). The following states are important in this context:

  • AVAILABLE - a plan item which has been created but has not yet triggered. A plan item is created when its parent stage is started. Note: A plan item is said to have triggered when its entry sentry has fired (or if it doesn’t have an entry sentry).

  • ENABLED - the state indicating that the plan item had triggered but was not automatically started (due to its "Manual Activation" property evaluating to "true").

  • ACTIVE - a state indicating that the plan item has been started (which is the default reaction upon triggering)

  • An INACTIVE state like COMPLETED, TERMINATED, DISABLED. Inactive is not an official CMMN state (in CMMN lingo it would be "terminal" or "semi-terminal) - but let’s call it like that the for the sake of this discussion.

Stage completion rules

Stages like to complete (unless something prevents them from doing so). In particular:

  • A stage with no plan item or with all plan items in an INACTIVE state will automatically complete.

Two simple conditions that stop a stage from completing:

  • The stage contains one or more ACTIVE plan items.

  • The stage contains one or more "required" plan items in state AVAILABLE or ENABLED.

Plan items in state AVAILABLE or ENABLED (that are not required) may also prevent a stage from completing. Here, however, we have to look at the Auto Completion property of the stage. Provided the above rules are met, a stage with any plan item in state AVAILABLE or ENABLED will complete under the following conditions:

  • The stage has its Auto Completion property set to "true" (black square), or else

  • The stage has default completion (no black square) and there are no ENABLED plan items and all AVAILABLE plan items are Completion Neutral (see below)

Modeling properties that control Stage completion

The following modeling properties have an impact on stage completion:

  • The state of the Auto Complete property of a stage (see discussion above)

  • The Required property of a plan item (this has an impact on the interpretation of AVAILABLE and ENABLED with respect to Auto Completion of a stage)

  • The Completion Neutral property of a plan item. This has an impact on the interpretation of the AVAILABLE state. A plan item with Completion Neutral "true" will not prevent a stage from completing (regardless of the stage’s Auto Completion property)

9.3.3. CMMN Connectors ("on-parts")

Connection types

The edoras one CMMN implementation allows modelers to freely connect plan items with each other via sentries and plan item on-parts (or case file item on-parts when referring to a case file item).

The following types of connections are supported:

  • Same stage connections: a plan item connects via a plan item on-part with another plan item, both plan items being siblings of each other (i.e. immediate children of the same stage).

  • Up-hierarchy connections: a plan item connects to an element in a parent stage (one or possibly more levels up).

  • Down-hierarchy connections: a plan item connects to an element residing in a sub-stage (one or possibly more levels down).

  • Cross-hierarchy connections: a plan item connects to an element residing in a different branch of the stage hierarchy of the CMMN model (note cross-hierarchy connections are supported starting with edoras one 1.5.0.S101).

The following section explains how various types of on-part connections are resolved by the CMMN engine at run-time.

On-part resolution

On-part standard events (like Complete) are resolved according to the following policies:

For entry sentries:

  • Any to one, common run-time hierarchy policy : any instance of a repeatable plan item will trigger zero or one new instance of the target plan item (per target plan item parent stage instance) within the common run-time branch of the stage instance tree.

For exit sentries:

  • Any to all, common run-time hierarchy policy : any instance of a repeatable plan item will terminate all instances of the target plan item within the common run-time branch of the stage instance tree.

Please refer to section Stage Hierarchy - model structure vs run-time structure for an explanation what "common run-time hierarchy" means.

The following figure is provided to illustrate the on-part resolution logic for a few types of plan item connections:

on parts

Note: For the sake of this example, all sentries listen to standard event Complete. However, the type of event is not relevant with respect to the resolution logic described here.

In order to explain how these connections are being handled in a running case model, we have to consider it with respect to a particular run-time state. Let’s assume the following run-time structure (the integer suffix denotes the run-time instance of the model element):

parent stage #1
    dependent task #1
    dependent task #2
    sub-stage #1
        task #1
    sub-stage #2
        task #2
    dependent sub-stage #1
        dependent sub-task #1
parent stage #2
    dependent task #3
    sub-stage #3
    dependent sub-stage #2

The connections marked in the diagram behave as described below:

  1. An up-hierarchy on-part from task to dependent task. Completing task #1 or task #2 will trigger a new instance of dependent task within parent stage #1.

  2. An up-hierarchy on-part from task to dependent task via an exit sentry. Completing task #1 or task #2 will terminate all instances of dependent task within parent stage #1 (but not parent stage #2 as that stage represents a different branch of the run-time hierarchy). See also note below on the order of sentry evaluation.

  3. An up-hierarchy on-part from task to sub-stage. Completing task #1 or task #2 will trigger a new instance of sub-stage within parent stage #1.

  4. An up-hierarchy on-part from task to sub-stage via an exit sentry. Completing task #1 will terminate sub-stage #1 (but not sub-stage #2 as that stage represents a different branch of the run-time hierarchy). Note, by completing task, its parent (sub-stage) auto-completes. However, termination via the modeled exit sentry happens first and thus determines the final state of sub-stage #1.

  5. A cross-hierarchy on-part from task to dependent sub-stage. Completing task #1 or task #2 will trigger a new instance of dependent sub-stage within parent stage #1.

  6. A cross-hierarchy on-part from task to dependent sub-task. Completing task #1 or task #2 will trigger any available instance of dependent sub-task in all active instances of dependent sub-stage of parent stage #1. Note: the event has a memory effect. Subsequently starting an instance of dependent sub-stage within parent stage #1 will automatically start the dependent sub-task instance of the new stage (see section Sentry Evaluation). Note, this type of cross-hierarchy connection is described in more detail in section Stage Hierarchy - model structure vs run-time structure, below.

  7. A cross-hierarchy on-part from task to dependent sub-stage via an exit sentry. Completing task #1 or task #2 will terminate all instances of dependent sub-stage within parent stage #1.

Sentry order: CMMN Specification version 1.0 doesn’t define the order in which entry and exit sentries are being evaluated. The behavior of the edoras one CMMN engine is such that entry sentries are evaluated first. Given an entry sentry and an exit sentry on the same plan item listening to the same condition, as the condition occurs, a new instance of the plan item is triggered and then immediately terminated.
Stage Hierarchy - model structure vs run-time structure

Plan item on-parts are evaluated with respect to their run-time stage hierarchy. As soon as we are using repeatable stages, the run-time hierarchy of a particular running CMMN model may contain multiple stage instances and thus may contain multiple parallel hierarchy branches. Consider the following model:

stages 1
Figure 48. Modeling a cross-hierarchy on-part

The model structure looks like this:

Case plan model
    parent stage
        sub-stage one
            task
        sub-stage two
            dependent task

The on-part connector connects task with dependent task. The tasks live in different model hierarchy branches. If we run this case and invoke the User event listener "Start parent stage" once, we get the following run-time hierarchy.

Case plan model #1
    parent stage #1
        sub-stage one #1
            task #1
        sub-stage two #1
            dependent task #1

In this scenario, associating the on-part event with its corresponding sentry is unambiguous - we only have one instance of dependent task. Completing task will trigger dependent task (assuming the sentry listens to event Complete).

If we invoke the User event listener "Start parent stage" a second time, we get the following run-time hierarchy:

Case plan model #1
    parent stage #1
        sub-stage one #1
            task #1
        sub-stage two #1
            dependent task #1
    parent stage #2
        sub-stage one #2
            task #2
        sub-stage two #2
            dependent task #2

We now have two instances of dependent task. The engine must now ensure that the correct instance of dependent task is triggered. edoras one CMMN does this by evaluating plan item on-parts within their common run-time hierarchy. Completing task #1 will trigger dependent task #1 but not dependent task #2.

The way the CMMN engine evaluates the Complete event in the model depicted above can be explicitly modeled by introducing an intermediate element in the common model hierarchy of the two connected plan items. This might look like the following:

stages 2
Figure 49. Resolving a cross-hierarchy on-part

By introducing the milestone, we explicitly resolve the cross-hierarchy on-part to an up-hierarchy on-part (from task to milestone) and a down-hierarchy on-part from milestone to dependent task. (This can be viewed as resolving an N-to-M relation between the two tasks to an N-to-1 relation to the milestone and then a 1-to-M relation from the milestone to th dependent task.) The run-time structure looks like this:

Case plan model #1
    parent stage #1
        milestone #1
        sub-stage one #1
            task #1
        sub-stage two #1
            dependent task #1
    parent stage #2
        milestone #2
        sub-stage one #2
            task #2
        sub-stage two #2
            dependent task #2

In most modeling scenarios, using the milestone is not necessary, since the CMMN engine always resolves the on-part with respect to the run-time hierarchy at hand. However, by introducing a common element like the milestone, you can change the behaviour of your plan item on-part connectors.

For example, in the following model, the milestone was put in the top-most level of the diagram (the Case plan model). The effect is now such that completing any instance of task will trigger all instances of dependent task, regardless of the run-time branch dependent task resides in.

stages 3
Figure 50. Controlling on-part resolution by means of a milestone

The model above effectively "broadcasts" a Complete event of task to all run-time instances of dependent task, regardless of the run-time hierarchy branch dependent task resides in.

9.3.4. CMMN Parameters

Overview

The following picture provides a graphical summary of the CMMN parameter support as described in this section. The diagram represents the course of action as a simple model is evaluated (as visible on the left hand side of the diagram, the model consists of an Event listener triggering a Human task with manual start property).

parameters

Parameters in edoras one CMMN are key/value pairs which are available for evaluation in CMMN back-end expressions. By default, these parameters are not persisted. They are maintained in memory and are available during a model evaluation cycle. Task parameter maps or service tasks can be used to selectively persist such parameters to the Case Work Item or to pass them on to Human task, Process task or Case task Work Items.

There are two types of parameters:

  • Explicit parameters - parameters explicitly modeled in the CMMN model or parameters passed into the evaluation cycle (e.g. as CMMN service call parameters)

  • Implicit parameters - parameters automatically set up by the CMMN engine for the duration of the current evaluation cycle.

There are two "time-to-live" scopes for parameters:

  • Form scope - form scope parameters are available during the initial plan item transition addressed by a CMMN service call

  • 'Param' scope - param scope parameters are available during the whole evaluation cycle (CMMN service call)

Some background: The starting point for a CMMN model evaluation cycle is a CMMN service method invocation. The call wraps a model evaluation cycle. Within an evaluation cycle, multiple plan item transition may take place. For example, a CMMN service call can apply a specific transition to a specific plan item instance. This transition will be processed and will trigger a re-evaluation of the CMMN run-time model, possibly triggering more plan item transitions as part of the same evaluation cycle. The form scope parameters will only be available for the initial plan item transition, the param parameters for all transitions within the same cycle.

Passing parameters to a state model

By default, edoras one init form data (e.g. when manually starting a Human task via an init form) are passed into the evaluation cycle with form scope. Form scope parameters are automatically persisted on the first Work Item started as part of the evaluation cycle.

Param scope parameters can be passed into the evaluation cycle in the following ways:

  • by passing them as query parameters in GET REST calls (with or without _param_ prefix)

  • by passing them as query parameters in PUT REST calls (with _param_ prefix)

  • by providing them as init form variables using _param_ as prefix in the form variable name

  • via the TransitionData object in the case of CMMN service calls.

Unlike form scope parameters, param parameters are not automatically persisted. They can be persisted, however, by explicitly mapping them in the parameter maps of Human tasks, Process tasks or Case tasks. Or by using a service task for that purpose.

Passing parameters within a state model (using parameter maps)

Within a state model, input and output parameter maps of Human tasks, Case tasks and Process tasks can be used to pass parameters between the Case Work Item and the respective edoras one Work Item representing the CMMN task. In the VIS modeler, the input map is called "In", the output map is called "Out". They are available in the properties panel of Human tasks, Case tasks and Process tasks.

The input parameter map is used to map parameters to the edoras one Work Item representing the task (Task Work Item for a Human task, Case Work Item for a Case Task, Process Work Item for a Process task). The mapping takes place as the task is started (START or MANUAL_START transition). Mapped input parameters are persisted on the target Work Item. The evaluation context for the parameter expressions are: Case Work Item, form scope parameters and param scope parameters.

The output parameter map is used to map parameters from the Work Item representing the task to the Case Work Item. The mapping takes place as the task work item completes (COMPLETE transition). Mapped output parameters are persisted on the Case Work Item (except for _param_ prefixed parameters, which are stored in memory with param scope). The evaluation context for the parameter expressions are: the edoras one Work Item representing the CMMN task, form scope parameters and param scope parameters.

Accessing parameters

Parameters can be accessed by name in CMMN back-end expressions. Form scope and param scope parameters are mapped into the same namespace, with param type parameters taking precedence in case of name clashes. Typical scenarios are:

  • referring to a parameter in a sentry expression

  • in a service task expression

  • in a parameter map expression (Human tasks, Process tasks, Case tasks)

Parameters can also be accessed by CMMN extension code via the transitionData object, which exposes getter methods for the form data and parameter data maps (for form and param scope parameters, respectively).

Writing parameter values

Parameter values can be written/updated in any of the following ways:

  • by naming the parameter in a service task result variable. Prepend the target variable name of the service task with _param_ in order to store the result of the service task in the parameter map of the current evaluation cycle. (Without the prefix, the result of a service task is persisted on the target Work Item, which is the Case Work Item by default.)

  • by using the _param_ prefix in target variable names of input or output parameter maps of Human task, Process tasks or Case tasks.

  • in CMMN extension code by writing to the parameter map of the transitionData object.

Implicit parameters

The following parameters are automatically provided by the CMMN engine for resolution in back-end expressions:

  • _planItem

  • _planItems

  • _triggerItems

  • _triggerItem

See section Expression variables with special meanings for more information.

Store and forward of parameters and trigger items

There are two evaluation cycles (and thus param scopes) involved in the starting of plan items with manual start property. First there is an ENABLE transition and then, at a later point in time a potential MANUAL_START transition. Often, the state of parameters and trigger items as present at ENABLE time is required during the evaluation cycle of MANUAL_START. To cater for this, the edoras one CMMN engine takes a snapshot of the parameters and trigger items at the point of ENABLE and makes it available during the MANUAL_START cycle. Parameters explicitly passed into the MANUAL_START cycle will overwrite any pre-existing values from an earlier ENABLE cycle.

Examples: Recursive CaseTask invocation

The following two examples are provided to illustrate some of the concepts and features presented above.

Example 1: Euclid’s algorithm to calculate the GCD of two integer values

The goal of the first case is to calculate the greatest common divisor of two integer values. To do so, the CMMN case model described below implements the recursive version of Euclid’s algorithm.

The case plan model looks as follows:

euclid case

The case takes two input parameters (the integer values for which to calculate the GCD). They are passed into the case as form scope parameters a and b. If b equals zero, a is returned immediately (i.e. set as result on the case). If b is not zero, the case invokes itself recursively with parameters a := b and b := a modulo b.

The case init form looks like this:

euclid input

The case work form, presenting the calculated result at the end, looks like this:

euclid result

The input parameter map of the case task in the model is configured like this:

euclid in

And the output parameter map like this:

euclid out

Example 2: Recursive calculation of the Fibonacci number

In the second example, the Fibonacci number is calculated for some integer input N. Unlike the previous example, in this case the _triggerItems parameter is used to access the result of two recursive case invocations. The model looks like this:

fibonacci case

The service task expression for "add results" looks like this:

#{_triggerItems['onecasetask1'].workItem.result + _triggerItems['onecasetask2'].workItem.result}

('onecasetask1' and 'onecasetask2' are the model IDs of the two case tasks in the 'sum of' stage.)

9.3.5. CMMN Expressions

Overview

edoras one CMMN models support back-end expressions at various locations. These include:

  • Entry sentry expressions

  • Exit sentry expressions

  • Expressions in task input and output parameter maps

  • The expression evaluated as part of a Service task

  • Expressions that determine the applicability of the Required, Repetition and Manual activation properties on plan items

  • Various properties in the Attributes pane of a CMMN model, like plan item name properties (to set the name as a result of an expression evaluation) or the 'show state' property for stages and milestones.

All of the above expressions are evaluated in the context of a given Work Item. By default, this Work Item is the Case. Where applicable, however, a more specific Work Item is set up as the evaluation context for a particular expression. The exact Work Item is determined based on the type of expression. For example, the Work Item context for the evaluation of a Process task’s output parameter map is set up to be the current Process Work Item.

With respect to back-end expressions there is also the concept of the current plan item. The current plan item can be referred to by name _planItem. Here again, the engine will provide the most specific plan item under that variable name when referring to it in an expression. For example, when evaluating the Show state property of a stage, the plan item accessible via _planItem will be the stage for which the expression is being evaluated.

To enable server-side debug output for expression resolution, including execution times in milliseconds, set the following log4j property: log4j.logger.com.edorasware.cmmn.one.implementation.OneEngineListeners = DEBUG
Expression variables with special meanings

The following special variables (or "implicit parameters", as referred to in the CMMN Parameters section) are available for expression resolution:

  • _planItem - the current plan item.

  • _planItems - a map of all plan item instances of the running model. The map is keyed by plan item instance Id.

  • _triggerItems - a map of the plan item instances being responsible for the triggering of the current plan item. This map is keyed by plan item model Id (not instance Id). The value obtained from looking up a _triggerItems element is a generic object of type EventSource, wrapping either a plan item or a case file item (depending on the exact circumstances for the triggering of the plan item).

  • _triggerItem the trigger item if there is exactly one element in _triggerItems.

  • parametersMap - the map of transition data parameters. For example, use an expression like parametersMap.containsKey('foo') to test for the existence of a 'foo' parameter.

  • formDataMap - the map of form data items (form scope parameters).

  • variablesMap - this is an expression variable which, in the context of an edoras one Work Item, returns the work item’s variables map. This again can be used to test for the existence of a work item variable (e.g. myWorkItemReference.variablesMap.containsKey('foo')).

Variables of the current Work Item (if applicable), of form scope and param scope (see section CMMN Parameters) can simply be referred to by name. They do not require a special prefix.
_planItem

Use this variable to refer to the current plan item. As mentioned above, this is the most specific plan item with respect to the expression being evaluated. Expressions evaluated in the context of the case will receive the Case Plan Model as current plan item.

The result returned is a view on the requested plan item, exposing the following properties:

Properties exposed by plan items

General properties

  • blocking - the value of the Blocking property.

  • casePlanModel - the plan item representing the current case plan model.

  • clientId - the client Id as a string; may be null (see workItem).

  • completionNeutral - the value of the Completion neutral property.

  • customState - a map (key/value pairs both of type String) of custom run-time state. See Storing custom plan item state

  • id - the static model Id.

  • index - the instance number, an integer >= 1; no gaps; the bigger the number the younger the plan item (synonym for instanceIntId).

  • instanceId - the instance Id (see Instance Ids).

  • instanceIntId - the instance number (synonym for index).

  • lastTransition - the last CMMN transition applied to the plan item (e.g. "COMPLETE").

  • manualActivation - the value of the Manual activation rule, evaluated at the moment the property is accessed.

  • name - the name of the plan item.

  • parent - the parent plan item. Returns null for the case plan model.

  • repetition - the value of the Repetition rule, evaluated at the moment the property is accessed.

  • required - the value of the Required rule, evaluated at the moment the property is accessed.

  • state - the CMMN state as a string (e.g. "ACTIVE").

  • workItem (or workObject) - a typed edoras one work object ID for the string stored under clientId; may be null.

For example, the following expression returns true if the plan item for which it is evaluated is in state ACTIVE:

#{_planItem.state == 'ACTIVE'}

Properties related to Cases started as Case tasks

  • ownerCasePlanModel - the Case plan model of the Case that started the current Case. Applies to all types of Case tasks (root or sub-case). Returns null for top level Cases (i.e. cases not started as a Case task).

  • parentCasePlanModel - the Case plan model of the parent Case. This only applies to Cases started as Case tasks of type sub-case. Returns null for any other type of Case.

  • topMostCasePlanModel - the Case plan model of the top most CMMN Case in the current Case hierarchy. When called for a root Case task or a top-level CMMN Case, will return its own Case plan model.

  • caseTask - returns true if the current Case was created from a Case task. Returns false otherwise.

  • subCaseTask - returns true if the current Case was created from a Case task and is of type sub-case. Returns false otherwise.

  • rootCaseTask - returns true if the current Case was created from a Case task and is of type root-case. Returns false otherwise.

For example, the following expression will return the value of variable myVariable of the top-most Case in the current plan item’s CMMN Case hierarchy. Note: When called within a top-level Case or a CMMN Case task of type root case, the expression shown below is equivalent to expression: #{myVariable == 'some value'}

#{_planItem.topMostCasePlanModel.workObject.myVariable == 'some value'}

Properties exposed by plan items of type Case task

  • targetCasePlanModel - the Case plan model of the Case started by the Case task. Returns null for Case tasks that have not yet been started or for plan items that are not of type Case task.

  • planItems - returns the Case task’s target Case plan model’s plan items. Returns null for Case tasks that have not yet been started or for plan items that are not of type Case task.

For example, assuming that the current plan item is of type Case task, the following expression will return true, if the state of the plan item with model Id 'modelid' within the plan item’s target Case is 'ACTIVE'. The expression will return false if the target Case doesn’t exist or if the 'modelid' plan item in the target Case is not in state 'ACTIVE'.

#{_planItem.planItems['modelid'].state == 'ACTIVE'}

Properties exposed by plan items of type Stage

These properties only make sense when called for stages (i.e. _planItem is of type Stage). These properties count child instances that are in a given state (or in any stage, in the case of childInstanceCount).

  • autoComplete - the boolean value of the auto-complete flag (or expression) of this stage.

  • availableChildrenCount - the number of available children of this stage plan item. Returns 0 when called for a non stage plan item.

  • activeChildrenCount - the number of active children of this stage plan item. Returns 0 when called for a non stage plan item.

  • childInstanceCount - the number of child instances of this stage plan item. Returns 0 when called for a non stage plan item.

  • completedChildrenCount - the number of completed children of this stage plan item. Returns 0 when called for a non stage plan item.

  • disabledChildrenCount - the number of disabled children of this stage plan item. Returns 0 when called for a non stage plan item.

  • enabledChildrenCount - the number of enabled children of this stage plan item. Returns 0 when called for a non stage plan item.

  • terminatedChildrenCount - the number of terminated children of this stage plan item. Returns 0 when called for a non stage plan item.

  • triggeredChildrenCount - the number of triggered children of this stage plan item (after transitions {ENABLE, START, OCCUR}. Returns 0 when called for a non stage plan item.

For example, given the stage plan item _planItem the following expression will tell you the number of child plan item instances the stage has:

#{_planItem.childInstanceCount}

Properties related to stage completion

  • waitingOnChildren - determines whether the stage is waiting on any child plan items for its completion. This property considers the current state of the stage’s autoComplete property. Returns false for non stage plan items.

  • waitingOnChildren(autoComplete) - determines whether the stage is waiting on any child plan items for its completion. The boolean result value is determined under the scenario of the boolean autoComplete value passed in the method call. Returns false for non stage plan items.

For example, assuming _planItem is a stage with autoCompletion set to false, the following expression will tell you whether the stage would complete under the scenario that autoCompletion was true:

#{not _planItem.waitingOnChildren(true)}

Properties related to sentries

The following properties are related to sentries and sentry evaluation. armed in these methods means that the plan item is ready to respond to an event, deferred means that that a suitable event has already occurred and the plan item is 'waiting' on a condition.

  • armed - returns true if the underlying plan item is armed. For an event listener, this means that invoking the OCCUR transition on the event listener has an effect, i.e. it triggers a transition on one or more connected plan items. For a plan item with entry sentries, armed means that the plan item is in state AVAILABLE and one or more of the plan item’s entry sentries are armed (See armedEntrySentries, below).

  • armedEntrySentries - the set of entry sentries (model IDs) whose condition is either missing or true. Returns an empty set for a plan item that has already been fired.

  • armedExitSentries - the set of exit sentries (model IDs) whose condition is either missing or true. Returns an empty set for a plan item that has not yet been created or is terminal.

  • deferredEntrySentries - the set of entry sentries (model IDs) whose on-parts have triggered. Returns an empty set for a plan item that has already been fired. Never includes sentries with no on-parts or trigger mode 'On event'.

  • deferredExitSentries - the set of exit sentries (model IDs) whose on-parts have triggered. Returns an empty set for a plan item that has not yet been created or is terminal. Never includes sentries with no on-parts or trigger mode 'On event'.

For example, an expression to test whether the condition of a specific sentry for a specific plan item is true might look like this:

#{_planItems['onehumantask1'].armedEntrySentries.contains('oneentrycriterion1')}

Count properties across the whole Case

These properties always return the total number, irrespective of the particular stage instance the current plan item is a child of.

  • availableCount - the number of instances of this plan item that are available.

  • activeCount - the number of instances of this plan item that are active.

  • completedCount - the number of instances of this plan item that have been completed.

  • disabledCount - the number of instances of this plan item that are disabled.

  • enabledCount - the number of instances of this plan item that are enabled.

  • instanceCount - the number of instances of this plan item.

  • terminatedCount - the number of instances of this plan item that have been terminated.

  • triggeredCount - the number of instances of this plan item that have been triggered (transitioned from AVAILABLE to either ACTIVE, ENABLED or OCCURRED).

For example, the following expression returns the number of plan item instances of the plan item type represented by _planItem that have been terminated:

#{_planItem.terminatedCount}

Count properties related to the parent stage instance

These properties are evaluated with respect to the stage instance the current plan item is a child of.

  • availableCountInStage - the number of instances of this plan item that are available with respect to the plan item’s parent stage instance.

  • activeCountInStage - the number of instances of this plan item that are active with respect to the plan item’s parent stage instance.

  • completedCountInStage - the number of instances of this plan item that have been completed as part of the plan item’s parent stage instance.

  • disabledCountInStage - the number of instances of this plan item that are disabled with respect to the plan item’s parent stage instance.

  • enabledCountInStage - the number of instances of this plan item that are enabled with respect to the plan item’s parent stage instance.

  • indexInStage - the instance number within the plan item’s parent stage instance, an integer >= 1; no gaps; the bigger the number the younger the plan item.

  • instanceCountInStage - the number of instances of this plan item with respect to the plan item’s parent stage instance.

  • terminatedCountInStage - the number of instances of this plan item that have been terminated with respect to the plan item’s parent stage instance.

  • triggeredCountInStage - the number of instances of this plan item that have been triggered (transitioned from AVAILABLE to either ACTIVE, ENABLED or OCCURRED) with respect to the plan item’s parent stage instance.

For example, the following expression returns true if _planItem is the first instance of its model element within its parent stage:

#{_planItem.indexInStage == 1}

This expression returns true if _planItem is the last instance of its type within its parent stage:

#{_planItem.indexInStage == _planItem.instanceCountInStage}

In addition to the above properties, the property planItemInternal can be used to access the underlying plan item implementation instance. This is internal API, however, and may break without notice.

_planItems

Use this map to refer to any existing plan item instance in your CMMN run-time model. Pass an instance Id as key into the map (see Instance Ids, below). For example, to refer to the third instance of a model element "humantask", use the following expression:

#{_planItems['humantask~3']}

Note: Passing a model Id (no instance suffix) will always refer to the most recent instance (highest instance suffix) available.

_triggerItems

Every plan item which can be modeled with an entry sentry automatically receives a standardized input parameter map named _triggerItems bound to the model evaluation cycle during which the plan item is triggered. The map contains key/value pairs of type String/EventSource with entries representing the plan item(s) that triggered the current plan item:

Example:

humanTasks

As task B-ID is triggered (started or enabled), it will receive the following input trigger items map:

"_triggerItems" : {
  "<A-ID>" -> "<A's trigger item (an instance of an EventSource object)>"
}
_triggerItem

The single value element of _triggerItems if _triggerItems contains exactly one element. If there are no trigger items or more than one in the _triggerItems map, this parameter is not set.

Properties exposed by trigger items

A trigger item (as returned for example by an expression like #{_triggerItems['my-human-task-model-id']}) exposes the following properties:

  • id - the static model Id

  • instanceId - the instance Id (see Instance Ids)

  • instanceIntId - the instance number, an integer >= 1

  • clientId - the client Id as a string; may be null (see workItem)

  • workItem (or workObject) - a typed work object ID for the string stored under clientId; may be null

  • state - the CMMN state as a string (e.g. "ACTIVE")

  • lastTransition - the last CMMN transition applied to the trigger item (e.g. "COMPLETE")

  • caseFileItem - a boolean value resolving to true if the trigger item represents a case file item

  • planItem - the plan item represented by this trigger item (if not a case file item). This planItem object exposes more properties. See Properties exposed by plan items

In addition to the above properties, the property caseFileItemInternal can be used to access the underlying case file item implementation instance (for case file item events). This is internal API, however, and may break without notice.

Please note the following when referring to trigger items:

  • Only the trigger items leading to the start/enable/occur of the target plan item are included in the _triggerItems map. If we have a sentry with multiple on-parts, only the on-parts whose transition triggers the enable/enable/occur event on the target plan item are included.

  • Trigger items are transient. They are only available as part of the current evaluation cycle (i.e. for evaluation during the model evaluation cycle during which they triggered). For task plan items: if the trigger items are needed at a later point in time, use an input parameter mapping to persist them to a desired work item.

  • Please also note a possible ambiguity with respect to multiple sentries: Multiple sentries represent a logical OR. If multiple such OR-ed sentries trigger simultaneously, the exact sentry passed in _triggerItems is not defined.

Instance Ids

An instance Id is a Model Id suffixed with a tilde and the plan item’s instance number. For example, given a Human task element with Model Id 'onehumantask', once the first instance of the Task plan item has become available in the run-time model, the plan item can be referred to as _planItems['onehumantask~1'] in an RT expression.

To refer to the most recent instance of a plan item, the instance Id suffix can be skipped (i.e. the model Id can be used).
Referring to Work Objects in expressions

Work Object IDs (aka Work Item IDs) used in back-end expressions automatically resolve to their underlying object. This means you can refer to Work Item properties by means of some ID reference you hold to that Work Item. The workItem property of _planItem is such an ID reference. Consider for example the following situation:

processTask

Here we have Process task with an exit sentry. The BPMN process referred to by the task in our example maintains a boolean property as a work object variable named 'exitMe'. This variable can be tested by the sentry condition in the CMMN process task like this:

#{_planItem.workItem.exitMe}
Special care must be taken when referring to ID variables which are involved in Front-end round trips. Form variables or case variables are typically involved in front-end/back-end server round-trips and may loose their 'ID' behavior as described above (because their type may get converted to a string). For those cases, wrap your ID expression by a call to cmmnBean.resolveId(..). For the example shown above, this would result in the following expression:
#{cmmnBean.resolveId(_planItem.workItem).exitMe}
Referring to Work Object variables in expressions

Work Object variables can simply be referred to by name. For example, the following sentry expression

#{myVariable}

will evaluate the Case variable myVariable in a boolean context (the Work Object context for entry sentries is always the Case Work Item).

Work Object variables may not always be initialized. Referring to a non-existing variable will result in an expression evaluation exception. There is a remedy for this though: If you want a Work Object variable reference for a non-existing variable to silently resolve to null, access the variable via the Work Object’s variablesMap. For example: #{variablesMap.myVariable}.

9.3.6. CMMN Stage and Milestone Visualization 

Intro

CMMN has a concept for stages and milestones. They somewhat overlap but don’t have exactly the same lifecycle. This secion describes how they can be visualized within the case template at runtime and how they can be configured/modeled within a CMMN case model.

Visualization options for stages and milestones

A stage can have the following visualization options (they might change over the lifecycle of the case):

  • Available, active or completed, but hidden in the case template (e.g. the CMMN model contains the stage, but it is not showed in the case template)

  • Available and shown in the case template, but not active at the moment

  • Active and shown in the case template

  • Completed and shown in the case template (completed means, the stage has been active and has been completed)

A milestone can have the following visualization options (they might change over the lifecycle of the case):

  • Available or reached but hidden in the case template

  • Available but not yet reached and shown in the case template

  • Reached and shown in the case template

In addition to whether a state and milestone is rendered within the case template or not, there is a certain order on how they will be rendered. As the case model does not provide a flow-kind of modeling but is rather event and condition driven, the order of stages and milestones must explicitly be modeled within the CMMN case model.

Visualized states

The current implementation of the case templates only knows a concept named availableStates, where milestones and stages are both rendered as states. States have three different options; available, active and completed managed with two boolean flags named isCurrentState and isCompleted.

First step implementation

As a first implementation due to simplicity and also to learn about the real-world requirements, the following new attributes are supported within an edoras vis CMMN case model.

New milestone attributes:

  • Show state → boolean, default is true

  • Show state (RT) → optional expression to define the availability of the milestone dynamically

  • Display order → integer

If the show state flag is true or the expression resolves to true, the milestone is rendered as an available state. As soon as the milestone has been reached, it is rendered as a reached state

New stage attributes:

  • Show state → boolean, default is true

  • Show state (RT) → optional expression to define the availability of the stage dynamically

  • Display order → integer

If the show state flag is true or the expression resolves to true, the stage is rendered as an available state. As soon as the stage is active, it is rendered as active. Once it completes, it is rendered as complete.

The default order among stages and milestones with the same user-configured display order is by age (instance creation time). The younger a stage, the more to the right it will appear. Milestones are also ordered by age but grouped and displayed next to their parent stage.

9.3.7. CMMN Execution Modes (Non-Blocking vs Ansynchronous)

This section describes how the CMMN property isBlocking is interpreted and how it relates to synchronous (or asynchronous) execution.

In the current implementation, service tasks are carried out non-blocking. They start, carry out some task and complete, all as part of the same evaluation cycle. They don’t remain in state active.

In addition, service tasks are executed synchronously. An asynchronous mode for service tasks may become available in a future implementation.

The following table puts the meaning of the various options in relation to each other:

Service tasks
Synchronous Asynchronous

Blocking

n/a

starts, starts an asynchronous thread of execution, remains (blocks) in state active, completes upon receiving the completion event from the asynchronous execution

Non-blocking

starts, executes, completes (DEFAULT)

starts, executes (fire and forget of an asynchronous thread of execution to carry out the task), completes

Other tasks (e.g. Human tasks)

Non-service tasks (like Human tasks, which are asynchronous by nature) are implemented in the following way.

Synchronous Asynchronous

Blocking

n/a

starts, starts the task, remains (blocks) in state active, completes upon recreceiving external task completion event (DEFAULT)

Non-blocking

n/a

starts, starts the task (fire and forget), completes

9.3.8. CMMN run-time Case migration

This is currently an experimental feature. It is not enabled by default. To turn it on, set configuration property experimental.enable-cmmn-case-migration to true.

There may be situations where you want to alter a case’s underlying CMMN model as it is executing. This is typically the case if you have long running cases and you need to adapt to changes in business or regulatory requirements not only for new cases but also for the cases currently being executed.

The edoras one CMMN engine supports automatic migrations of running cases from an old CMMN Case model (the one a particular case is based on) to a more recent model version. Please note, that the current implementation only supports automatic migration of structural model changes. It does not cater for changes of variable names or other changes related to the way the modeler chooses to store data on work objects.

The feature is triggered via the Migrate button that is available for Case models in the edoras one Modeler Dashboard. Clicking this button will migrate all running (i.e. not archived) Cases of that model type from their current model version to the latest model version.

The Migrate function is a powerful feature which should be employed with great care. As noted above, only structural model changes are supported. An overview of supported and un-supported types of model changes follows below:

Supported types of model changes
  • adding new plan items, like adding a new Human task to a stage.

  • adding new stages. This includes the introduction of new parent stages to existing stages.

  • moving plan items, including stages.

  • deleting plan items.

  • renaming of model IDs: in most cases, the migration algorithm will successfully detect renamed model elements (including renamed model IDs) and will be able to re-map old run-time state to the new model element.

Types of model changes not supported
  • any logic in the model that deals with the storing and accessing of case data. This includes the naming of variables and how variables are being referenced in sentry expressions and other expressions.

  • expressions referring to model elements whose model ID has been renamed

In order to fully migrate running cases that need to adopt these types of changes, you’ll have to run custom migration code that takes all relevant model changes into consideration and alters any relevant persisted state accordingly. This obviously is easier said than done. Complex migrations of running business cases will have to be planned, executed and tested involving business analysts, modelers, developers and testers.

Examples of supported model changes

This section illustrates a number of basic model changes and explains how the automatic migration algorithm deals with them.

Any number of such supported model changes can be applied in a single migration. As a result, complex model transformations can be performed in a single migration step as long as you keep in mind the rules and limitations described here.

Adding a plan item
addedTask

In this example, the modeler introduced a new task that is started upon the completion of an existing task. After the migration of running cases to this new model, the following two scenarios are of interest:

  • if Existing task has not been completed, completing the task will trigger the New task as modelled in the new model version.

  • if however, the Existing task had already been completed, the outcome will depend on the sentry option of New task’s entry sentry:

    • If it is of type Event deferred, the new task will automatically be started by the migration. This is due to the fact that during migration, the last plan item transition of all existing plan items is re-evaluated against the newly introduced model elements.

    • If it is of type On event, the New task will not be started and, for this particular model, will never be started.

Removing a plan item
removedTask

In this example, the modeler will remove the Delete task and connect Existing task via a Complete event directly with Remaining task. Just picture the new model without the Delete task and a direct connection from Existing task to Remaining task.

When migrating cases to this new model, the following happens:

  • if Delete task is active, it will be terminated by applying the EXIT transition to it. Based on the fact that Delete task was active in this scenario, we must have had a COMPLETE transition on Existing task and as a result will have Remaining task in state ACTIVE (provided the sentry mode is Event deferred - see example above).

  • if Delete task has not yet been completed, completing it will simply trigger Remaining task.

Introducing new stages and moving existing stages

In this example, we will migrate a running case from this model:

existingStage

to this model:

insertedStage

Let’s consider the migration of a running case with an active Existing stage and an active Existing task. Since the modeler decided to introduce a new parent stage for Existing stage, the migration of the running case to the new model will yield the following result, depending on the value of the new stage’s entry sentry:

  • if the sentry evaluates to true during case migration, the New parent stage will be active and the existing stage and task from the old run-time state will be properly moved to the new stage, carrying over their existing state (active stage, active task).

  • if however, the sentry evaluates to false, the New parent stage will not be started after migration. Consequently, the Existing stage and Existing task from the old run-time state can not yet exist. As a result, Existing stage and Existing task will be terminated as part of the migration step (by means of applying the EXIT transition to it). Once New parent stage triggers, a new instance of Existing stage and Existing task will be started.

9.4. CMMN Palette

This section describes the elements available in the CMMN modelling palette of edoras one. Each modeling element and their corresponding attributes are described in detail below.

These are the common attributes available for all model elements of an edoras one CMMN diagram.

Table 109. Common attributes
Attribute Name Description

Name

The name of the element. This is the name displayed in the diagram. If no RT-Name is specified, this name is also used in the running case.

Name (RT)

The name of the element in a running case. If left empty, Name is used. The name can be localized. The value provided here may be a run-time expression (or it can be a static string containing one or more run-time expressions). Use the #{..} syntax for expressions. Evaluation context is the Case Work Item.

Description

The description for the element. The description is not displayed in the diagram but is exported as part of the generated CMMN XML. The description can be localized.

Custom Properties

Any properties as key/value pairs (string/string). These properties are exported as part of the CMMN XML and can be accessed at runtime. Keys are case insensitive.

Background Color

The background color of the element in the diagram.

Border Color

The border color of the element in the diagram.

Custom Properties are not available for Sentry and Connector elements. Background Color is not available for the Connector element.

There are several attributes that allow to customize the font format diagram elements. If the attributes are set at the level of the Case Plan Model, all the elements of the case will contain these attributes by default:

Table 110. Text format attributes
Attribute Name Description

Font size

The font size of the element in the diagram.

Font weight

The font weight of the element in the diagram.

Font style

The font style of the element in the diagram.

Font Color

The font color of the element in the diagram.

These attributes can also be modified by the shortcut with a "T" icon placed in the left-bottom corner of the components. Clicking on this brings up a text format dialog where the formatting can be changed as required. The dialog includes a button to remove the style format and goes back to the default format.

9.4.1. Case plan model

The Case plan model represents the case itself. It is the top-most parent stage for all model elements of the case.

Table 111. Specific attributes for the Case plan model
Attribute Name Description

Auto complete

See Auto complete attribute of Stage

Table 112. Supported custom attributes for the Case plan model
Key Value

repetition

standardCmmn - set this custom attribute on the Case plan model if you want to disable the automatic repetition feature (see Automatic repetition).

triggerLimit

Some integer value >= 1. This value determines how many new instances of a model element can be triggered per parent stage and model evaluation cycle. This is used for recursion detection/prevention. If this value is missing, a default value of 1 is assumed.

Background: In certain modeling scenarios you may decide to create and trigger multiple new instances of a particular model element. If your model contains such recursions, you can raise the limit here to a higher value, taking into account the maximum number of expected recursions for your case. The value provided here represents a hard limit. Reaching it will cause a run-time exception. You will have to make sure to stay below this limit by means of suitable sentry expressions.

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.2. Human task

A Human task represents a form based data collection / data maintenance activity performed by a Case worker. When started, a Human task will create an edoras one Task Work Item which will act as the default container for any task data and which can be assigned to other users, and marked with a due date, priority and other attributes, just like any edoras one Task Work Item.

Table 113. Specific attributes for Human tasks
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Required

Select this option to mark the element as required (exclamation mark decorator). Required plan items must reach one of the states {Completed, Terminated, Disabled} in order for their parent stage to complete.

Required (RT)

An optional run-time expression (#{..} syntax) for the Required property. If empty, the setting of the Required flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Required flag.

The expression is evaluated once at the point of creation of the plan item instance (i.e at the start of the parent stage or at repetition time). Evaluation context is the Case Work Item.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Manual activation

Select this option to mark the element to have manual activation (right arrow 'play' decorator). Plan items with Manual activation move from state Available to state Enabled once they trigger. A plan item in state Enabled exposes an action button that allows the user to manually start the plan item.

Manual activation (RT)

An optional run-time expression (#{..} syntax) for the Manual activation property. If empty, the setting of the Manual activation flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Manual activation flag.

The value is evaluated on demand, i.e. at the point in time a plan item is triggered (moving out of state Available). Evaluation context is the Case Work Item.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Blocking

Set this property to mark the task as blocking. Blocking is the default behaviour where a task plan item remains active until it is moved out of its active state as work on the case progresses. An example of a typical flow of action would be: the Work Item is started and remains active until the case worker completes it or until it is completed due to some external condition.

By marking a plan item as non-blocking, the plan item is started and immediately completes from the point of view of the case model. The plan item’s Work Object (e.g. the Task Work Object for a Human task), however, may remain active until a case worker decides to complete it. By setting the non-blocking property, you can effectively detach the life-cycle of a plan item and its corresponding Work Object. See [blockingModes] for more information on how the blocking property is interpreted in a running CMMN case.

Initialize form reference

The form reference referring to an edoras one form to be used as the task’s init form. The init form is only relevant for tasks with Manual activation. The init form is shown at the point the user decides to manually start the task. Form fields of the init form will be passed to the new Work Item as parameters with 'form scope'.

By default, the init form fields will be persisted on the new Work Object. By using the prefix _param_ in form field variable names, form fields can be passed on in memory without being persisted on the target Work Item (see section CMMN Parameters for details on edoras one CMMN parameters).

Work form reference

The form reference referring to an edoras one form to be used as the task’s work form.

In

An optional input parameter map. Allows to map parameters and variables onto the Human task’s Work Item as it is started. See section CMMN Parameters.

Out

An optional output parameter map. Allows to map parameters and variables onto the original Case Work Item as the Human task’s Work Item completes. See section CMMN Parameters.

Task id

The name of the variable under which to store the new Task Work Item Id on the original Case Work Item (i.e. to let the owning Case know the Id of the started task). The name is optional and, if provided, can be a back-end expression (#{..} syntax) resolving to the name of the variable (evaluation context is the Case Work Item).

If your Human task is repeatable, append the variable name with a pair of brackets ('[]'). This will store the Task Work Object Ids in a map keyed by Human task instance Ids.

Owner

Set the owner of the task by selecting an existing user statically.

Owner (RT)

Use a backend expression to evaluate the owner dynamically at runtime.

Assignee

Set the assignee of the task by selecting an existing user statically.

Assignee (RT)

Use a backend expression to evaluate the assignee dynamically at runtime.

Candidate Users

Set the candidate users of the task by selecting existing users statically.

Candidate Users (RT)

Use a backend expression to evaluate the candidate users dynamically at runtime.

Candidate Groups

Set the candidate users of the task by selecting existing groups statically.

Candidate Groups (RT)

Use a backend expression to evaluate the candidate groups dynamically at runtime.

Priority

The priority to be set on the new Task Work Item. Defaults to priority 50 if left empty.

Due date

An optional task due date.

Allowed actions

The set of allowed actions that can be performed on the Task Work Item.

Table 114. Supported custom attributes for Human tasks
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.3. Case task

A Case task represents an edoras one Case. Use this element to start a CMMN case that is available in the current edoras one App.

Table 115. Specific attributes for Case tasks
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Required

Select this option to mark the element as required (exclamation mark decorator). Required plan items must reach one of the states {Completed, Terminated, Disabled} in order for their parent stage to complete.

Required (RT)

An optional run-time expression (#{..} syntax) for the Required property. If empty, the setting of the Required flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Required flag.

The expression is evaluated once at the point of creation of the plan item instance (i.e at the start of the parent stage or at repetition time). Evaluation context is the Case Work Item.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Manual activation

Select this option to mark the element to have manual activation (right arrow 'play' decorator). Plan items with Manual activation move from state Available to state Enabled once they trigger. A plan item in state Enabled exposes an action button that allows the user to manually start the plan item.

Manual activation (RT)

An optional run-time expression (#{..} syntax) for the Manual activation property. If empty, the setting of the Manual activation flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Manual activation flag.

The value is evaluated on demand, i.e. at the point in time a plan item is triggered (moving out of state Available). Evaluation context is the Case Work Item.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Blocking

Set this property to mark the task as blocking. Blocking is the default behaviour where a task plan item remains active until it is moved out of its active state as work on the case progresses. An example of a typical flow of action would be: the Work Item is started and remains active until the case worker completes it or until it is completed due to some external condition.

By marking a plan item as non-blocking, the plan item is started and immediately completes from the point of view of the case model. The plan item’s Work Object (e.g. the Task Work Object for a Human task), however, may remain active until a case worker decides to complete it. By setting the non-blocking property, you can effectively detach the life-cycle of a plan item and its corresponding Work Object. See [blockingModes] for more information on how the blocking property is interpreted in a running CMMN case.

Case reference

The Case model reference referring to the CMMN Case that is to start as this Case task moves to state Active.

Case reference (RT)

An optional run-time expression (#{..} syntax) that resolves to a Case reference at the time the Case task is started.

Case name

An optional RT expression for the name of the started Case Work Item. If left empty, defaults to the value of the Name attribute under Common Attributes.

Scope

Defines the hierarchy of the started Case.

Sub case - the started Case will be a child of the current Case. Its tasks, actions and states will be visually integrated in the GUI of the current case.

Root case - the started Case will be a top-level Case. You will have to select the started Case in the User Dashboard to work with it.

In

An optional input parameter map. Allows to map parameters and variables onto the Case task’s Work Item as it is started. See section CMMN Parameters.

Out

An optional output parameter map. Allows to map parameters and variables onto the original Case Work Item as the Case task’s Work Item completes. See section CMMN Parameters.

Case id

The name of the variable under which to store the new Case Work Item Id on the original Case Work Item (i.e. to let the owner Case know the Id of the started Case). The name is optional and, if provided, can be a back-end expression (#{..} syntax) resolving to the name of the variable (evaluation context is the original Case Work Item).

If your Case task is repeatable, append the variable name with a pair of brackets ('[]'). This will store the Case Work Object Ids in a map keyed by Case task instance Ids.

Table 116. Supported custom attributes for Case tasks
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.4. Process task

A Process task represents an edoras one BPMN process. Use this element to start a BPMN process that is available in the current edoras one App.

Table 117. Specific attributes for Process tasks
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Required

Select this option to mark the element as required (exclamation mark decorator). Required plan items must reach one of the states {Completed, Terminated, Disabled} in order for their parent stage to complete.

Required (RT)

An optional run-time expression (#{..} syntax) for the Required property. If empty, the setting of the Required flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Required flag.

The expression is evaluated once at the point of creation of the plan item instance (i.e at the start of the parent stage or at repetition time). Evaluation context is the Case Work Item.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Manual activation

Select this option to mark the element to have manual activation (right arrow 'play' decorator). Plan items with Manual activation move from state Available to state Enabled once they trigger. A plan item in state Enabled exposes an action button that allows the user to manually start the plan item.

Manual activation (RT)

An optional run-time expression (#{..} syntax) for the Manual activation property. If empty, the setting of the Manual activation flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Manual activation flag.

The value is evaluated on demand, i.e. at the point in time a plan item is triggered (moving out of state Available). Evaluation context is the Case Work Item.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Blocking

Set this property to mark the task as blocking. Blocking is the default behaviour where a task plan item remains active until it is moved out of its active state as work on the case progresses. An example of a typical flow of action would be: the Work Item is started and remains active until the case worker completes it or until it is completed due to some external condition.

By marking a plan item as non-blocking, the plan item is started and immediately completes from the point of view of the case model. The plan item’s Work Object (e.g. the Task Work Object for a Human task), however, may remain active until a case worker decides to complete it. By setting the non-blocking property, you can effectively detach the life-cycle of a plan item and its corresponding Work Object. See [blockingModes] for more information on how the blocking property is interpreted in a running CMMN case.

Process reference

The process model reference referring to the BPMN process that is to start as this Process task moves to state Active.

Process reference (RT)

An optional run-time expression (#{..} syntax) that resolves to a process reference at the time the process task is started.

Process name

An optional RT expression for the name of the started Process Work Item. If left empty, defaults to the value of the Name attribute under Common Attributes.

In

An optional input parameter map. Allows to map parameters and variables onto the Process Work Item as it is started. See section CMMN Parameters.

Out

An optional output parameter map. Allows to map parameters and variables onto the Case Work Item as the Process Work Item completes. See section CMMN Parameters.

Process id

The name of the variable under which to store the process Work Object Id on the Case Work Item (i.e. to let the Case know the Id of the started process). The name is optional and, if provided, can be a back-end expression (#{..} syntax} resolving to the name of the variable (evaluation context is the Case Work Item).

If your Process task is repeatable, append the variable name with a pair of brackets ('[]'). This will store the process Work Object Ids in a map keyed by Process task instance Ids.

Table 118. Supported custom attributes for Process tasks
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.5. Service task

A Service task is a special type of task which, as it moves to state Active, evaluates a back-end expression and optionally stores its result (if any) on a Work Item.

Table 119. Specific attributes for Service tasks
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Required

Select this option to mark the element as required (exclamation mark decorator). Required plan items must reach one of the states {Completed, Terminated, Disabled} in order for their parent stage to complete.

Required (RT)

An optional run-time expression (#{..} syntax) for the Required property. If empty, the setting of the Required flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Required flag.

The expression is evaluated once at the point of creation of the plan item instance (i.e at the start of the parent stage or at repetition time). Evaluation context is the Case Work Item.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Manual activation

Select this option to mark the element to have manual activation (right arrow 'play' decorator). Plan items with Manual activation move from state Available to state Enabled once they trigger. A plan item in state Enabled exposes an action button that allows the user to manually start the plan item.

Manual activation (RT)

An optional run-time expression (#{..} syntax) for the Manual activation property. If empty, the setting of the Manual activation flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Manual activation flag.

The value is evaluated on demand, i.e. at the point in time a plan item is triggered (moving out of state Available). Evaluation context is the Case Work Item.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Expression

A back-end expression (#{..} syntax) or static text mixed with any number of embedded back-end expressions. The expression is evaluated as the Service task becomes Active. Evaluation context is the Case Work Item.

Result variable

The name of the variable under which to store the result of the expression evaluation. The name can be a back-end expression (resolving to the name of the variable).

By default, the variable is stored on the Case Work Item. Use the _param_ prefix in the variable name to store the result in memory for the duration of the current model evaluation cycle (see sections CMMN Parameters and CMMN Expressions).

Table 120. Supported custom attributes for Service tasks
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.6. Send mail task

A Send mail task is a special type of service task which allows to send out e-mail notifications.

Table 121. Specific attributes for Send mail tasks
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Required

Select this option to mark the element as required (exclamation mark decorator). Required plan items must reach one of the states {Completed, Terminated, Disabled} in order for their parent stage to complete.

Required (RT)

An optional run-time expression (#{..} syntax) for the Required property. If empty, the setting of the Required flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Required flag.

The expression is evaluated once at the point of creation of the plan item instance (i.e at the start of the parent stage or at repetition time). Evaluation context is the Case Work Item.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Manual activation

Select this option to mark the element to have manual activation (right arrow 'play' decorator). Plan items with Manual activation move from state Available to state Enabled once they trigger. A plan item in state Enabled exposes an action button that allows the user to manually start the plan item.

Manual activation (RT)

An optional run-time expression (#{..} syntax) for the Manual activation property. If empty, the setting of the Manual activation flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Manual activation flag.

The value is evaluated on demand, i.e. at the point in time a plan item is triggered (moving out of state Available). Evaluation context is the Case Work Item.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Mail Model

This mail model defines rich-text templates for the mail subject and body. Backend expressions in the mail model templates will be replaced when the mail is sent.

The mail model is a required runtime back end expression (the Mail Model RT attribute) or a literal (the Mail Model attribute) that defines the mail model key or its model id. In the literal case, you are able to select the mail model based on a select box which is populated with the mail models of the current app. In this case, the version of the mail model taken is the one that will be deployed next which on subsequent changes to the mail model will not be the latest mail model definition deployed.

If you specify a back end expression, then this should resolve to either an email model id or email definition key (that is, a specific version of an email model). In the first case, the latest deployed version (definition) of the email model is used as template. In the latter case, the specified definition will be used, similar to selecting the literal case mentioned above.

Mail Recipient

The mail recipient is a required expression or literal that defines the email recipient (or multiple recipients). The first mail recipient can be accessed in the mail template by ${recipient} expression.

Mail Reply-To

The mail reply-to is an optional expression that specify an explicit reply address. If no reply address is defined then the global system default will be used (which will vary from installation to installation)

Mail CC

Specify one or multiple CC recipients using literals or backend expressions. This attribute is optional

Mail Bcc

Specify one or multiple BCC recipients using literals or backend expressions. This attribute is optional

Mail Priority

An optional expression or literal that specifies the mail priority (usually an integer in the range 1 - 5)

Mail Headers

Specify additional mail headers. They will be applied before the message is sent

Attachments ids

The list of documents sent by the email. The documents can be referenced by its id or a backend expression.

Table 122. Supported custom attributes for Send mail tasks
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.7. Create document task

A Create document task is a special type of Service task which creates a document instance from a document model and associates it with the case by setting the case as parent.

Table 123. Specific attributes for Create document tasks
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Required

Select this option to mark the element as required (exclamation mark decorator). Required plan items must reach one of the states {Completed, Terminated, Disabled} in order for their parent stage to complete.

Required (RT)

An optional run-time expression (#{..} syntax) for the Required property. If empty, the setting of the Required flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Required flag.

The expression is evaluated once at the point of creation of the plan item instance (i.e at the start of the parent stage or at repetition time). Evaluation context is the Case Work Item.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Manual activation

Select this option to mark the element to have manual activation (right arrow 'play' decorator). Plan items with Manual activation move from state Available to state Enabled once they trigger. A plan item in state Enabled exposes an action button that allows the user to manually start the plan item.

Manual activation (RT)

An optional run-time expression (#{..} syntax) for the Manual activation property. If empty, the setting of the Manual activation flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Manual activation flag.

The value is evaluated on demand, i.e. at the point in time a plan item is triggered (moving out of state Available). Evaluation context is the Case Work Item.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Document Model

Select a document model for the new document to be created.

Document Model (RT)

An optional run-time expression (#{..} syntax) that resolves to a document model key.

Document Id variable name

Specify an optional variable name under which the Id of the newly created document instance will be stored on the case.

Document name

The name of the document to be created within the case. The name may contain expressions.

Table 124. Supported custom attributes for Create document tasks
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.8. Initialize variables task

An Initialize variables task is a special type of Service task which allows to initialize a set of variables on the Case Work Item (or arbitrary target Work Items).

This task is modeled after the Initialize variables task for BPMN process models and works the same way except that the default target Work Object is not the Process but the current CMMN Case. The CMMN specific variable naming features (the _param_ and _customState_ prefixes and the [] suffix) are not supported at this time. Please use a basic Service task to update such values.

Table 125. Specific attributes for Initialize variables tasks
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Required

Select this option to mark the element as required (exclamation mark decorator). Required plan items must reach one of the states {Completed, Terminated, Disabled} in order for their parent stage to complete.

Required (RT)

An optional run-time expression (#{..} syntax) for the Required property. If empty, the setting of the Required flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Required flag.

The expression is evaluated once at the point of creation of the plan item instance (i.e at the start of the parent stage or at repetition time). Evaluation context is the Case Work Item.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Manual activation

Select this option to mark the element to have manual activation (right arrow 'play' decorator). Plan items with Manual activation move from state Available to state Enabled once they trigger. A plan item in state Enabled exposes an action button that allows the user to manually start the plan item.

Manual activation (RT)

An optional run-time expression (#{..} syntax) for the Manual activation property. If empty, the setting of the Manual activation flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Manual activation flag.

The value is evaluated on demand, i.e. at the point in time a plan item is triggered (moving out of state Available). Evaluation context is the Case Work Item.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Init variables

Define the list of variable initializations here. Each line in this property editor will initialize one variable. The Target column can be empty (in which case the target is the current Case Work Item; the constants root, parent are supported in addition to any target expressed by means of a back-end expression). The columns Variable name and Initial value define the variable’s name and value respectively. Expressions (using the #{..} syntax) are supported in all three columns.

Overwrite if existing

If set to true, the values of already defined variables will be overwritten. Otherwise, already initialized variables are skipped.

Table 126. Supported custom attributes for Initialize variables tasks
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.9. Add comment task

An Add comment task is a special type of Service task which creates a Work Item text comment on an arbitrary target Work Item (the Case by default).

Table 127. Specific attributes for Add comment tasks
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Required

Select this option to mark the element as required (exclamation mark decorator). Required plan items must reach one of the states {Completed, Terminated, Disabled} in order for their parent stage to complete.

Required (RT)

An optional run-time expression (#{..} syntax) for the Required property. If empty, the setting of the Required flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Required flag.

The expression is evaluated once at the point of creation of the plan item instance (i.e at the start of the parent stage or at repetition time). Evaluation context is the Case Work Item.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Manual activation

Select this option to mark the element to have manual activation (right arrow 'play' decorator). Plan items with Manual activation move from state Available to state Enabled once they trigger. A plan item in state Enabled exposes an action button that allows the user to manually start the plan item.

Manual activation (RT)

An optional run-time expression (#{..} syntax) for the Manual activation property. If empty, the setting of the Manual activation flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Manual activation flag.

The value is evaluated on demand, i.e. at the point in time a plan item is triggered (moving out of state Available). Evaluation context is the Case Work Item.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Comment Target Object

A back-end expression that resolves to the Work Item to which the new comment should be added.

History variable name

Stores the last comment added in the given variable name. If empty the comment is added to the comment-stream.

Comment User

Allows to specify the user in whose name the comment is created. The provided value may be a back-end expression (#{..} syntax).

Comment Template

The text template for the comment. The template supports embedded back-end expressions (#{..} syntax).

Table 128. Supported custom attributes for Add comment tasks
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.10. Dmn rule task

A Dmn rule task is a special type of Service task which evaluates Dmn rule.

Table 129. Specific attributes for Dmn rule tasks
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Required

Select this option to mark the element as required (exclamation mark decorator). Required plan items must reach one of the states {Completed, Terminated, Disabled} in order for their parent stage to complete.

Required (RT)

An optional run-time expression (#{..} syntax) for the Required property. If empty, the setting of the Required flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Required flag.

The expression is evaluated once at the point of creation of the plan item instance (i.e at the start of the parent stage or at repetition time). Evaluation context is the Case Work Item.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Manual activation

Select this option to mark the element to have manual activation (right arrow 'play' decorator). Plan items with Manual activation move from state Available to state Enabled once they trigger. A plan item in state Enabled exposes an action button that allows the user to manually start the plan item.

Manual activation (RT)

An optional run-time expression (#{..} syntax) for the Manual activation property. If empty, the setting of the Manual activation flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Manual activation flag.

The value is evaluated on demand, i.e. at the point in time a plan item is triggered (moving out of state Available). Evaluation context is the Case Work Item.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Comment Target Object

A back-end expression that resolves to the Work Item to which the new comment should be added.

History variable name

Stores the last comment added in the given variable name. If empty the comment is added to the comment-stream.

Comment User

Allows to specify the user in whose name the comment is created. The provided value may be a back-end expression (#{..} syntax).

Comment Template

The text template for the comment. The template supports embedded back-end expressions (#{..} syntax).

Table 130. Supported custom attributes for Add comment tasks
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.11. Milestone

This element represents the CMMN Milestone plan item.

Table 131. Specific attributes for Milestones
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Required

Select this option to mark the element as required (exclamation mark decorator). Required plan items must reach one of the states {Completed, Terminated, Disabled} in order for their parent stage to complete.

Required (RT)

An optional run-time expression (#{..} syntax) for the Required property. If empty, the setting of the Required flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Required flag.

The expression is evaluated once at the point of creation of the plan item instance (i.e at the start of the parent stage or at repetition time). Evaluation context is the Case Work Item.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Show state

A flag indicating whether the state of this Milestone is displayed at run-time. The standard Case template includes a status bar showing the states of Stages and Milestones. When set to true, the Milestone will be displayed in the status bar with colors reflecting its state: light gray for Available/Enabled/Terminated, dark gray for Completed (i.e. 'reached').

Show state (RT)

A back-end expression (#{..} syntax) determining the state of this flag at run-time. It overrides the value of the Show state on/off flag. Evaluation context is the Case Work Item.

Display order

An integer value (negative, zero or positive) denoting the display order of the Milestone’s state indicator relative to other elements in the status bar (see attribute Show state). The smaller the number, the more to the left.

Table 132. Supported custom attributes for Milestones
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.12. Case file item

Case file items are used to model references to external data. The following types of Case file items are supported (attribute Definition type):

  • edoras case variable - this type of Case file item allows to define a reference to a variable of the Case Work Item. As the Case variable is created/updated/deleted, corresponding Case file item transitions will be triggered on the Case file item.

Table 133. Specific attributes for both Case file item types
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Multiplicity

Case file item multiplicity values as defined in the CMMN specification.

Definition type

Defines the type and behaviour of this Case file item.

Table 134. Specific attributes for Case file items of type edoras case variable
Attribute Name Description

Variable name

The name of the Case variable for which to receive Create, Update and Delete events. Currently only top-level variable names can be mentioned here. Monitoring the state of a particular sub element (e.g. of a map or array type variable) is currently not supported.

9.4.13. Stage

This element represents the CMMN Stage plan item. Stages are used to structure your case into stages and sub-stages.

Table 135. Specific attributes for Stages
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Required

Select this option to mark the element as required (exclamation mark decorator). Required plan items must reach one of the states {Completed, Terminated, Disabled} in order for their parent stage to complete.

Required (RT)

An optional run-time expression (#{..} syntax) for the Required property. If empty, the setting of the Required flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Required flag.

The expression is evaluated once at the point of creation of the plan item instance (i.e at the start of the parent stage or at repetition time). Evaluation context is the Case Work Item.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Manual activation

Select this option to mark the element to have manual activation (right arrow 'play' decorator). Plan items with Manual activation move from state Available to state Enabled once they trigger. A plan item in state Enabled exposes an action button that allows the user to manually start the plan item.

Manual activation (RT)

An optional run-time expression (#{..} syntax) for the Manual activation property. If empty, the setting of the Manual activation flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Manual activation flag.

The value is evaluated on demand, i.e. at the point in time a plan item is triggered (moving out of state Available). Evaluation context is the Case Work Item.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Auto complete

A Stage with this option set to true will complete more eagerly, i.e. even if there are pending non-required children in states Available or Enabled.

In other words: With the option set to true, a Stage will complete even if it has children in states Available or Enabled (unless they are Required).

With this option set to false, a Stage will only complete if all child elements are in states {Completed, Terminated, Disabled}.

Show state

A flag indicating whether the state of this Stage is displayed at run-time. The standard Case template includes a status bar showing the states of Stages and Milestones.

When set to true, the Stage will be displayed in the status bar with colors reflecting its state: light gray for Available/Enabled/Terminated, red for active, dark gray for Completed.

Show state (RT)

A back-end expression (#{..} syntax) determining the state of this flag at run-time. It overrides the value of the Show state on/off flag. Evaluation context is the Case Work Item.

Display order

An integer value (negative, zero or positive) denoting the display order of the Stage’s state indicator relative to other elements in the status bar (see attribute Show state). The smaller the number, the more to the left.

Table 136. Supported custom attributes for Stages
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.14. Plan fragment

Plan fragments can be used to group model elements. Plan fragments don’t have a run-time representation or life-cycle. They don’t have any specific attributes other than Model ID.

9.4.15. Entry criterion

Use this element to place a CMMN entry sentry on a suitable model element (Case plan model, Stage, Tasks).

Table 137. Specific attributes for Entry sentries
Attribute Name Description [#triggerMode]

Trigger mode

Defines the sentry’s trigger semantics. The setting here is only relevant for sentries that are connected to other model elements (i.e sentries with one or more "on-parts"). Please refer to section Sentry Evaluation for more information on sentry evaluation logic

On event - the sentry will only 'fire' if one or more of the on-part elements undergo the desired transition as part of the current model evaluation cycle. If the sentry has a condition, and the condition evaluates to false, the sentry won’t trigger and any transition event will be lost.

Event deferred - the sentry is evaluated against any on-part element’s last transition. If there is a transition and a false sentry condition, the sentry does not trigger. If the condition turns to true at a later point in time, the sentry will fire based on the state of any relevant on-part element’s last transition. Note Event deferred is not supported for events created by Timer event listeners.

Condition

A back-end expression (#{..} syntax) resolving to a boolean value or the constants true or false. A missing expression resolves to true. Evaluation context is the Case Work Item.

9.4.16. Exit criterion

Use this element to place a CMMN exit sentry on a suitable model element (Case plan model, Stage, Tasks).

Table 138. Specific attributes for Exit sentries
Attribute Name Description [#triggerMode]

Trigger mode

Defines the sentry’s trigger semantics. The setting here is only relevant for sentries that are connected to other model elements (i.e sentries with one or more "on-parts"). Please refer to section Sentry Evaluation for more information on sentry evaluation logic

On event - the sentry will only 'fire' if one or more of the on-part elements undergo the desired transition as part of the current model evaluation cycle. If the sentry has a condition, and the condition evaluates to false, the sentry won’t trigger and any transition event will be lost.

Event deferred - the sentry is evaluated against any on-part element’s last transition. If there is a transition and a false sentry condition, the sentry does not trigger. If the condition turns to true at a later point in time, the sentry will fire based on the state of any relevant on-part element’s last transition. Note Event deferred is not supported for events created by Timer event listeners.

Condition

A back-end expression (#{..} syntax) resolving to a boolean value, or the constants true or false. A missing expression resolves to true. Evaluation context is the Work Item most closely related to the sentry’s plan item (e.g. the Task Work Item for a Human task). Evaluation context for Stages and the Case plan model is the Case Work Item.

9.4.17. Timer event listener

This model element represents the source of a timer event. A Timer event listener in state Available will respond to a timer event as configured via the model element’s properties panel. At the point in time a Timer event listener is created (it transitions to state Available), it will start a timer in the background with a time configuration as specified by the modeler via the Timer properties dialog. Once the timer running in the background fires, the corresponding Timer event listener will trigger (it will transition to Completed).

The point in time the Timer event listener transitions to Available marks the reference point for relative timer configurations (like a duration of, for example, one month). Once a background timer triggers, its Timer event listener must be in state Availble in order to respond to the timer signal. As a consequence, by putting a Timer event listener into a Stage, you can

  • control the start reference point of the timer via the stage’s entry sentry configuration (the timer is initialized as the stage starts) and

  • cancel a timer by completing (or exiting) the stage.

Please note that trigger mode Event deferred is not supported for timer events (see [triggerMode]. If a timer fires on a sentry whose condition is false, the sentry will not trigger and the event will be lost.

Table 139. Specific attributes for Timer event listeners
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Table 140. Supported custom attributes for Timer event listeners
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.18. User event listener

This model element represents the source of a user interaction. A User event listener in state Available is rendered as an action button in the CMMN case template (under Case actions). Clicking the action button triggers an Occur transition on the even listener. There is a set of properties allowing to configure the behaviour of the action button representing the User event listener in the GUI. Please refer to section [activationAttributes].

User event listeners are smart in the sense that their GUI representation (i.e. action button) is only visible if clicking it actually has an effect in the run-time model (i.e. a sentry connected with the user event listener actually triggers the plan item it is connected with). To deactivate this smart behavior, see property visbility in the custom attributes table, below.

Table 141. Specific attributes for User event listeners
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Table 142. Supported custom attributes for User event listeners
Key Value

visibility

force - set this custom attribute on the User event listener in order to disable the smart visibility behavior mentioned above. No or any other value enables the smart behavior.

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.19. Stage auto completion

A special type of user event listener to manually complete a stage. This element can be placed in any stage or the case plan model. It works in combination with stages that have their Auto complete property set to false. This user event listener effectively turns the stage’s Auto complete property on upon user request (by the user clicking the action button). The button is only shown if clicking it actually has the effect of completing the stage (i.e. only if the stage would complete had it its Auto complete property set to true).

Table 143. Specific attributes for Stage auto completion
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Table 144. Supported custom attributes for User event listeners
Key Value

visibility

force - set this custom attribute on the element in order to disable the smart visibility behavior mentioned above. No or any other value enables the smart behavior.

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.20. Event listener

The Event listener model element represents the source for an external event. Event listeners usually receive an Occur plan item transition sent by a CMMN service bean call.

Table 145. Specific attributes for Event listeners
Attribute Name Description

Model ID

A unique ID for the element. The ID is used to refer to a model element from outside of the diagram (e.g. from a CMMN Action button in a form). For convenience, this ID can be edited.

Repetition

Select this option to mark the element as repeatable (fence-mark decorator). Repeatable plan items may exist more than once at run-time, each having their own life-cycle.

The combination of this property, Manual activation and no entry sentry has a special meaning called Automatic repetition: As a previous instance of the plan item completes, a new instance is automatically created and set into state Enabled. Repeatable event listeners can be triggered (i.e. occur) multiple times.

Repetition (RT)

An optional run-time expression (#{..} syntax) for the Repetition property. If empty, the setting of the Repetition flag is used. When provided, the value of this expression is evaluated at run-time and will determine the value of the Repetition flag.

The value is evaluated on demand, i.e. at the point in time a plan item’s sentry fires (leading to the creation of a new instance if evaluated to true). Evaluation context is the Work Item associated with the task, or the Case Work Item if no more specific Work Item is available.

[#repetitionSyntax] [NOTE] A special variable naming syntax exists to store the result of a repeatable plan item (to prevent one plan item instance from overwriting the result of an earlier plan item instance). This works as follows: if you add the suffix '[]' to a variable name (e.g. to the result variable of a Service Task or to an output parameter variable of a Human task), the parameter will be stored on the target Work Object in a map keyed by the plan item’s instance Id (the name of the map being the string before the '[]' suffix).

Completion neutral

Select this option to mark the element to be 'completion neutral'. The flag can be used to influence the way the plan item’s parent stage completes.

Background: plan items in state Available may prevent the parent Stage (or Case) from automatically completing. By checking this property, the plan item will behave neutral with respect to the completion of the parent container.

Table 146. Supported custom attributes for Event listeners
Key Value

extensionType

Optional extension type. See Provide custom implementations for plan item transitions.

9.4.21. Connector

A connector represents a plan item or case file item on-part.

Table 147. Specific attributes for Connectors
Attribute Name Description

Standard event

When connected to a sentry, a connector exposes this property allowing to set the standard event (CMMN transition) the sentry listens for.

9.4.22. Activation attributes

The Activation attributes section is available to all model element types which will result in the rendering of an action button at run-time. This includes:

  • Tasks with Manual activation resolving to true.

  • Stages with Manual activation resolving to true.

  • User event listeners

Apart from the activation attributes listed below, the custom property availableActionHidden can be set on these model elements. If set to true, no action button will be generated in the Case Actions section for the model element. CMMN action buttons placed in forms, however, will still be shown.

Table 148. Activation attributes
Attribute Name Description

Name

The name displayed in the action button. If empty, fall-back to attribute Name under Common attributes.

Name (RT)

The name displayed in the action button. It can be a mixed expression consisting of static text and run-time expressions like "My name is #{bunny-name}". It takes precedence over the Name property at run-time. Evaluation context is the Case Work Item.

Description

The description for the action button. Currently not used in the Case template.

Hide action if

An optional RT expression (#{..} syntax) which, when provided and resolving to true, will hide the action button.

Display order

An integer (negative, zero or positive) denoting the order of the action button relative to other action buttons in the Case actions menu of the standard Case template. Smaller numbers mean higher up in the list.

Candidate users

Allows to restrict the visibility of the action button to users included in the list provided here.

Candidate users (RT)

An expression resolving to a list of candidate users at run-time. See Candidate users, above. Evaluation context is the Case Work Item.

Candidate Groups

Allows to restrict the visibility of the action button to users that are members of the groups listed here.

Candidate groups (RT)

An expression resolving to a list of candidate groups at run-time. See Candidate groups, above. Evaluation context is the Case Work Item.

9.5. Basic CMMN Modeling Patterns

This section presents a number of simple CMMN modeling patterns. Each pattern is presented with its model diagram and a description of the expected behavior when running the model.

Prerequisites: to re-play the examples in this section you’ll have to be familiar with CMMN modeling to the point of creating a case model, placing and connecting plan items and configuring properties and expressions and on the plan items (model elements).

For building and running these models, make sure to have the case template enabled. I.e. make sure your URL refers to the case.html file like /case.html#/dashboard/user. If the case.html is not set, you can simply edit the URL accordingly.

9.5.1. Auto-starting a task

Use-Case

Model a task which automatically starts as its enclosing stage becomes active. In this example, the enclosing stage is the Case Plan Model. As the case is started, the task starts as well.

auto start
Interaction
  • Start the case → this starts the task "Auto-Start"

  • Select the task from the "Active Work Items" list

  • Complete the task → this completes and archives the case

9.5.2. Manual-start of a task

Use-Case

Model a task which can be started by the user clicking an action button. In this example we have a case model containing a single human task. The task is modeled with Manual Activation set to true. As the case starts, the task is set to state ENABLED. Selecting the task from the list of available actions manually starts (activates) the task.

manual start
Interaction
  • Start the case → this set the task "Manual-Start" to state ENABLED.

  • Select the task from the "Case Actions" list.

  • If the task is configured with an init form, you’ll now see the init form and will be prompted to submit the form to start the task.

  • If the task has no init form, it immediately starts and becomes available under "Active Work Items". The case automatically navigates to the started task’s work form.

9.5.3. Sentry condition

Use-Case

Trigger (start) a task based on the result of an expression evaluation. In this example we have a case model containing a single Human Task. The task is started as soon as the user sets the name of the case to "task".

sentry condition
Interaction
  • Start the case → the task is not started (it is in state AVAILABLE).

  • Select the case work form and set the name of the case to "task".

  • This starts the task - it is now available in the "Active Work Items" list.

  • The name of the started task is "true", which is the result of evaluating the task’s name expression.

9.5.4. Sentry on-part

Use-Case

Trigger (start) a task based on an event happening on some other model element. This can be modeled using connector lines ("on-parts") between the involved model elements. In the following example we have a case model containing two human tasks. One task starts upon completion of the first task. The relevant event (state transition) to listen to can be configured on the connector line. In this example it’s the "Complete" event.

sentry on part
Interaction
  • Start the case → task "A" is started.

  • Select task "A" from the "Active Work Items" list.

  • Complete the task → this starts task "B".

9.5.5. Sentry-OR

Use-Case

Like in the previous example, we want to trigger a task based on an event happening on some other model element. However, in this case, more than one preceding plan item event may trigger our task. At least one event must happen to trigger the task (logical OR). In our example, tasks "A" and "B" are started as the case is started. Completing any of the tasks starts task "A or B completes".

sentry or
Interaction
  • Start the case → this starts tasks "A" and "B".

  • Select any of the tasks from the "Active Work Items" list.

  • Complete the task → this starts task "A or B completes".

9.5.6. Sentry-AND

Use-Case

In this example multiple plan item on-parts need to form a logical AND. In order for our target task to trigger, all connected plan items must undergo the desired on-part event. In the example below we have a case model containing three human tasks. Tasks "A" and "B" are started as the case is started. Completing both of the tasks starts task "A and B complete".

Note: the required tasks don’t have to undergo the selected transition simultaneously. The CMMN engine remembers the last transition of a plan item. As soon as the last AND connected task undergoes the desired transition, and all other plan item’s last transition matches the desired one, the follow-up task is started.

sentry and
Interaction
  • Start the case → this starts tasks "A" and "B".

  • Select any of the tasks from the "Active Work Items" list and complete the task.

  • Select the other active task from the "Active Work Items" list and complete the task.

  • By completing the second task, the AND-condition is fulfilled → Task "A and B complete" starts.

9.5.7. Starting multiple task instances by Automatic Repetition

Use-Case

A task must be able to be executed multiple times at the user’s discretion. There are various ways to model repeatability of plan items. The simplest way is via setting both Manual Activation and Repetition on our task model element. The CMMN engine treats this configuration in a special way: as soon as the task completes, a new instance is created and triggered (set to state ENABLED).

Note: With this setup, there is always an ENABLED instance of the task available. This has an impact on stage/case auto-completion (see next example)

repetition
Interaction
  • Start the case → this sets the task "Manual-Repetition" to state ENABLED.

  • Select the task from the "Case Actions" list → this starts the task.

  • As the task is completed, a new instance is created and put in state ENABLED.

  • The new instance can be started at any time by selecting it from the "Active Work Items" list.

9.5.8. Starting multiple task instances using a User Event Listener

Use-Case

The use-case is the same as in the previous example. However, this time a User Event Listener is used to trigger multiple task instances. Apart from the different graphical model, the run-time behaviour is also slightly different: the creation and triggering of the tasks is controlled via the User Event Listener and not indirectly via the completion of the repeatable task as in the previous example.

Multiple instances of the task can be started (made ACTIVE) at the same time by repeatedly clicking the action button. With this setup, the task goes from CREATED straight to ACTIVE. Using 'Completion neutral' on the User Event Listener, the case more easily auto-completes compared to the previous example as there is never a pending task instance in state ENABLED.

Init forms configured on the task are ignored. In this setup, the task is immediately started once the event listener is selected and the user is navigated to the started task’s work form.

repetition event
Interaction
  • Start the case → this set the user event listener "Start task" to state ENABLED.

  • Select the user event listener from the "Case Actions" list → this triggers the user event listeners OCCUR event.

  • The task is started.

  • Due to the fact that the user event listener is repeatable, a new instance of it is created and made available in the "Case Actions" list.

9.5.9. Starting multiple task instances in parallel

Use-Case

This is another variation on the previous use-case. It demonstrates how a plan item on-part to itself can be used to trigger the repetition. In this example, the standard event that is configured on the plan item on-part (the dotted connector line) is Manual start.

repeat on manualstart
Interaction
  • Start the case → this enables the task (due to the fact that it has an empty sentry with no condition).

  • Select the task’s action button from the "Case Actions" menu. This starts the task.

  • The 'Manual start' event from the previous action triggers the on-part of the task to itself and leads to the creation and enabling of a new task instance.

9.5.10. Starting multiple plan item instances simultaneously

Use-Case

Set up more than one instance of a plan item in one step. In this example exactly two instances of the same repeatable stage are activated as the case starts. This is achieved using a plan item on-part to itself listening to the 'Start' event.

The on-part introduces a recursion which we have to end by means of a condition. In our example, the sentry condition is _planItem.instanceCount < 2.

Note: To protect against infinite looping, by default, the CMMN engine limits the creation/triggering of plan item instances (within the same parent stage) to 1. This limit can be raised setting custom property triggerLimit on the Case Plan Model.

multi stage
Interaction
  • Start the case.

  • Exactly two instances of the stage are active.

9.5.11. Require a task N times

Use-Case

A user must complete a particular task exactly N times. This can be modeled in various ways. One possible way is depicted in the following diagram:

require n times
Interaction
  • Start the case → the Human Task is available for manual activation.

  • Start and complete the task → a second instance of the task is available for manual activation.

  • Start and complete the second instance → the case completes.

9.5.12. Case File Item - respond to case variable updates

Use-Case

Respond to a Case variable update by means of a Case File Item. In this example we have a case model containing a Case File Item of type "edoras case variable" (the case variable to be monitored is set to "myvar"). We also have a task listening to the UPDATE event of the Case File Item. Each time case variable "myvar" changes, a new instance of the task is started.

repeat on update
Interaction
  • Start the case.

  • Select the "Edit Entity" screen (pencil icon).

  • Create a new case variable named "myvar".

  • Edit variable "myvar", setting it to a new value → task "Repeat on update" is started.

  • Edit variable "myvar", setting it to another value → a new instance of task "Repeat on update" is started.

9.5.13. Repeat plan items based on a sentry condition

Use-Case

Trigger a plan item each time a particular expression turns to true. This is not possible with a simple sentry. In CMMN, repeatable plan items are only triggered based on a plan item "on-part" (a connector to another plan item). Merely triggering on a condition is not possible (except for the first instance).

However, by using a Case File Item of type "edoras case variable", we can achieve this type of behavior. Bind the Case File Item to a case variable of your choice and trigger the evaluation of the plan item’s sentry by updating the variable. In the sentry expression, an arbitrary condition can be evaluated determining whether to actually trigger the task or not.

repeat on condition
Interaction
  • Start the case, naming it anything but "repeat".

  • Rename the case to "repeat" → this triggers the task.

  • Rename the case to some other value.

  • Rename the case again to "repeat" → this triggers a second instance of the task.

  • …​and so on.

9.5.14. Task planning

Use-Case

Enable a task (and make it required) based on some business condition (or planning step). Allow to "undo" this based on changing business conditions.

The task "Send Christmas card" in this example will show up as enabled (with an action button) and will be required to complete if the name of the case equals 'vip'. As soon as the name of the case changes, the task is not required anymore and its action button is hidden. Toggling between the two states can happen as often as necessary.

The expression for the Required Rule is case.name == 'vip'. The expression for the Hide-if expression (under Activation attributes) is not _planItem.required (which is the same as case.name != 'vip' but without duplicating the expression logic of the Required Rule for better maintainability).

toggle required
Interaction
  • Start the case, naming it anything but "vip".

  • The case can be completed by clicking the "Complete case" button.

  • Rename the case to 'vip'.

  • The "Complete case" button disappears as we now have the required task (and action button) "Send Christmas card".

  • Rename the case to something other than "vip".

  • The case can again be completed by the "Complete case" button.

9.5.15. Milestones

Use-Case

Visualize reached (and pending) milestones in the states bar of the case template. In this example we have a case model containing a task and a milestone. As the case is started, the milestone is displayed as pending. As the task completes, the milestone is reached and changes its color to COMPLETED.

milestone
Interaction
  • Start the case. This starts the task. It also sets the milestone to AVAILABLE.

  • The AVAILABLE milestone is shown in the header area of the case view (case template).

  • Select the task from the "Active Work Items" list. This selects the task’s work form.

  • Complete the task. This triggers the OCCUR transition on the milestone.

  • The milestone is considered reached (COMPLETED). Its visual representation changes accordingly.

9.5.16. Stages and Plan Fragments

Use-Case

Structure your case using Stages and Plan Fragments. Use Stages to structure the run-time behavior of your case. Use Plan Fragments to graphically group related elements in your model. While Stages have a life-cycle and a GUI representation (AVAILABLE/ACTIVE/COMPLETED), Plan Fragments are merely a means to group model elements.

Stages and Plan Fragements can be nested to any level. Stages can be fitted with entry and exit sentries and connected via on-parts (connector lines).

nesting
Interaction
  • Start the case. This starts stage 1 which starts stage 1.1 which starts task "A".

  • Stage 2 has an entry sentry listening to the completion of stage 1. At this point, stage 2 is in state AVAILABLE.

  • Complete task "A".

  • This results in the completion of stage 1.1 which results in the completion of stage 1.

  • The completion of stage 1 in turn triggers stage 2’s entry sentry which starts stage 2.

  • This starts task "B".

  • Completing task "B" now completes stage 2 and completes (and archives) the case.

9.5.17. Stage with exit sentry

Use-Case

Stages can be exited via exit sentries. In this example, we have a case model containing a stage which can be prematurely terminated by means of a user event listener and exit sentry. This model pattern should be used with care. Only use it to support and model business scenarios where a stage is pre-maturely aborted. Normal stage completion should, when ever possible, be modeled via the stage’s auto-completion capability. See Case and Stage completion, further down.

stage with exit
Interaction
  • Start the case. This starts the stage which in turn starts the task.

  • By completing the task, the stage will be completed.

  • Alternatively, the user can prematurely terminate the stage by clicking "Terminate stage".

  • This terminates the stage which will propagate the termination to the active task.

  • As the stage terminates (or completes), the case is completed and archived.

9.5.18. Task with exit sentry

Use-Case

Abort an active (or enabled) task. Task elements can also be terminated by means of exit sentries. Similar to the previous example, by clicking the user event listener, the end of the stage’s life-cycle can be forced. However, this time indirectly via the termination of the task.

task with exit
Interaction
  • Start the case. This starts the stage which in turn starts the task.

  • By completing the task, the stage will be completed.

  • Alternatively, the user can prematurely terminate the stage by clicking "Terminate task".

  • This terminates the task which completes the stage.

  • As the stage completes, the case is completed and archived.

9.5.19. Case and Stage completion

Use-Case

Manage the life-cycle of your case (and possibly of sub-stages within it) via the auto-completion capability of Stages (and the Case Plan Model itself). Stage auto-completion works as follows:

A stage automatically completes as soon as it finds all of its child elements in state COMPLETED or TERMINATED.

Using default settings, a stage with children in states AVAILABLE (created but not yet triggered) or ENABLED (triggered but with Manual Activation) will not automatically complete.

A modeler however may choose to force auto-completion of a stage containing AVAILABLE or ENABLED children by setting the stage’s "Auto complete" property to true.

The property "Completion neutral" on plan items can be used to help with auto completion. It will render the state AVAILABLE neutral with respect to stage completion.

The following case contains a single task and a user event listener. By completing the task, the stage won’t complete as it still observes the user event listener "Early exit" in state AVAILABLE. To force stage completion for this situation, the modeler can either set the stage to "Auto complete" or set the user event listener to "Completion neutral".

auto complete
Interaction
  • Start the case. This start the human task.

  • Select and complete the human task.

  • The case does not complete at this time.

Variation with "Auto complete"

  • Modify the model and set "Auto complete" on the case (Case Plan Model).

  • Deploy the model (app) and run the case again.

  • Observe how the case now completes as the task is completed.

Variation with "Completion neutral" on the event listener

  • Modify the model and set "Auto complete" back to false.

  • Set the property "Completion neutral" on the user event listener to true.

  • Deploy the model (app) and run the case again.

  • Observe how the case now automatically completes as the task is completed.

9.5.20. User-triggered Stage completion

Use-Case

Allow a user to complete a stage for which no further work needs to be done.

The model element "Stage auto completion" is available to allow a case worker to manually set a stage to auto-completion. A stage with auto-completion set to true will complete even if there are available or enabled plan items in the stage.

Consider the following example: after running the case, the case is active. The case doesn’t auto complete because there are plan items in states AVAILABLE and ENABLED (and the case’s Auto complete property is set to false).

By clicking the event listener, the stage will be manually set to "Auto complete" and will thus complete as a result of the user clicking the action button.

Note: if there were an active task, setting "Auto complete" to true would not complete the stage. Consequently, the "Complete case" action button would not be visible (the CMMN engine only shows Stage auto completion buttons if selecting them actually completes the stage).

stage auto complete
Interaction
  • Start the case. This sets the "Complete case" Stage Auto Completion listener to state AVAILABLE. Because of this, the event listener will be available as an action button under "Case Actions".

  • The case is active.

  • Click the action button.

  • The case completes.