Workflow Enhancer for JIRA Documentation

This page contains old documentation. The new documentation can be found here:

This is the documentation for the JWFE 2.0 onwards. You can find a documentation for older versions here.


Validators and Conditions

To enter a validator or a condition provided by JWFE, edit your workflow and in any transition add a new "universal validator" or a "universal condition". You will be prompted with entering a Boolean expression as explained below. In the case of the universal validator, you will be prompted to enter a message as well.

Post Functions

As of JWFE 3.0, you have the possibility of executing any post function depending on if a Boolean expression (see the rest of this documentation) evaluates to true or false, respectively. When adding a "Universal Post Function", you will not only be prompted for a Boolean expression, but also for another post function to be executed and any values that post function might take.

Note that some of the inbuild post functions of JIRA have unintuitive functionality:

  • Create a comment: If in the transition screen a comment was added, it will be added again
  • Update Issue Status: Will update the issue status after transition, although it was already changed
  • Create Issue: Recreates the issue, e.g. previously there is an issue " TEST-4 - access task", but after post function transition it becomes " TEST-5 - access task"

In the future we might decide to hide these post functions.


Reporter, AssigneeStringUser field containing a username, e.g. {Reporter} represents the username of the issue's reporter {Reporter} = "admin"

Attention: In the old JWFE (until version 1.5.1) it represented the reporter's fullname

Anonymous is in JIRA and JWFE represented by ""

Environment, Description, SummaryStringText field, e.g. {Summary} contains the text entered in the issue's summary{Summary} = "Issue1"
Due Date, Created, UpdatedDateDate field, e.g. {Due Date} contains the date entered in the issue's Due Date field{Due Date} = 24.12.2012
Original Estimate, Remaining Estimate, Time SpentTimespanTime span field, e.g. {Original Estimate} contains the time span entered in the issue's Original Estimate field{Original Estimate} = 4w 5d 6hif nothing is entered in the field, JWFE gives back 0min ( i.e. {...} = 0min )
Σ Original Estimate, Σ Remaining Estimate, Σ Time SpentTimespanTime span field, e.g. {Σ Original Estimate} contains the sum of the Original Estimates of the issue's subtasks{Σ Original Estimate} = 1w 7d 3hif nothing is entered in the field, JWFE gives back 0min ( i.e. {...} = 0min )
ProjectString{Project} contains the issue's project name{Project} = "Rocket"
PriorityString{Priority} contains the (name of the) priority of the issue{Priority} = "Major"
{Status} = "In Progress"
{Resolution} == "Resolved"
Issue TypeString
{Issue Type} = "Bug"
KeyString{Key} contains the key of the issue which is of the form PROJECTKEY-IssueId{Key} = "ROCKET-1"
Issue LinksString{Linked Issues} <=> "Passive: LinkType % IssueKey $ ... $ LinkType % IssueKey Aktive: LinkType % IssueKey $ ...$ LinkType % IssueKey" 
  • Linked exactly with ROCKET-1 as a Blocker and ROCKET-42 as a Cloner
    • {Linked Issues} = "Passive: Blocks % ROCKET-1 Aktive: Cloners % ROCKET-42"
  • Linked  exactly with ROCKET-42 as a cloner
    • {Linked Issues} = " Aktive: Cloners % ROCKET-42"

  • Has to have at least one active Link of type ¨Relation¨
    • {Linked Issues}=/ Aktive: .* Relation .*/

JIRA default LinkTypes are Blocks, Cloners and Duplicate.

(warning) Note the space before ¨Aktive¨ and the spelling of  ¨Aktive¨

Set the log level to Debug and check in the logs, this syntax is not really easy to handle.

LabelsStringGives back the Array of labels as String in alphabetical order; e.g. [label1, label2, label3]{labels} = "[aLabel]" for exactly one specific label, or {labels} == "[]" for none

Use regular expressions to check for one label among several, e.g.

{labels} = /.*mylabel.*/
Fix Version/s, Affects Version/sStringGives back the Array of versions as String in alphabetical order; e.g. [version1, version2, version3]

{Fix Version/s} = "[aVersion]" for exactly one specific version,

{Fix Version/s} == "[]" if you want to check that no fixVersion is set.

Use regular expressions to check for one version among several
ComponentsStringGives back the Array of components as String in alphabetical order; e.g. [component1, component2, component3]

{Components} = "[myComponent]" if you want exactly one component called "myComponent" set.

{Components} == "[]" if you want to check that no component is set

{Components} == /.*myComponent.*/ if you want to chek if a component called "myComponent" set and do not care about other components

Use regular expressions to check for one version among several
Transition CommentStringGives back the comment added in the transition as a string.
Is only useful for post functions and validators and if a screen is shown during the transition

JIRA fields (written as `{field_id}`) may themselves contain a special value. Therefore if a field contains a value such as `1h 30min`, it will automatically be parsed as a timespan. This also allows for example a chain of field identifiers (by putting the identifier of another field in a field). An application may be that the first element of the chain is set as a post-function to dynamically change the behavior of the condition / validator depending on the steps in the workflow we have visited).

However, we are currently exploring the idea of not evaluating the field values or making it possible for the user to define which fields should be evaluated.

Please compare JIRA-Fields always with English field values e.g. {Resolution} == "Resolved"

Important: The fields of type String only allow string comparisons. So especially the order operations <, <=, >=, > often don't make sense, for example in the case of priority {Priority} > "a string which begins with the letter a" always evaluates to "True".

You can use both field names in your local language as well as english lower-case names, e.g. in German {resolution} and {Lösung} both refer to the resolution while {Resolution} tries to evaluate a customfield.

Custom Fields

Date Picker{Date Picker} represents the picked date as a date valuee.g. {Date Picker} = 25.09.2012 00:00, if you picked 25/Sep/2012 in the issue's Date Picker field or {Date Picker} = "" if you want to check that the date picker is not set.
Version Picker{Single Version Picker} represents all picked versions of the issue as a comma and space separated string
Single Version Picker{Version Picker} represents the picked version as a string
Project Picker{Project Picker} represents the picked projectname as a stringProjectname is a unique value
User Picker{User Picker} represents the picked user's username
Multi User Picker{Multi User Picker} represents all picked user's username in a comma and space separated stringe.g. {Multi User Picker} = "username1, username2", if you picked user1 and user2 in the issue's Multi User Picker field
Group Picker{Group Picker} represents the picked groupname in a string
Multi Group Picker{Multi Group Picker} represents all picked groups groupname in a comma and space separaded stringe.g. {Multi Group Picker} = "jira-developers, jira-users, jira-tester", if you picked these three groups in the issue's Multi Group Picker field.
Number Field{Number Field} represents the entered number as a float valuee.g. {Number Field } = "3.14", if you entered in the issue's Number Field field 3.14
Free Text Field{Free Text Field} represents the entered text as a stringe.g. {Free Text Field} = "all work and no play makes Jack a dull boy" if you entered all work and no play makes Jack a dull boy in the issue's Free Text Field
Text Fieldsee Free Text Field above
Label{Labels} represents all labels, which are affixed to the issue, as a stringe.g. {Label} = "label1, label2, label3" if you affixed this labels to the issue. Note that: JIRA sorts the labels so "label1, label2" = "label2, label1"
Date Time{Date Time} represents the picked point in time as a date valuee.g. {Date Time} = 24.12.2012 15:45 if you picked this moment in the issue's Date Time field. See Values/Date
URL Field{URL Field} represents the entered URL as a stringe.g. {URL Field} = ""
Import Id

not supported

Read only Text Fieldnot supported
Cascading Select

{Cascading Select} reprensents the selected options as as String in the same format as Atlassian´s .toString() method for Cascading Select fields

  • null=PARENT, 1=CHILD
  • null=PARENT if no child value is selected
  • ¨¨ if no value is selected
e.g. {Cascading Select} = /null=.*, 1=.*/ to ensure both values are set
Bug Import ID

not supported

Multi Select{Multi Select} represents the selected options as a comma and space separated string
Radio Buttons{Radio Button Field} represents the selected option as a string
(Multi) Checkboxes{Checkbox} represents the selected options as a comma and space separated string
Select List

{Select List} represents the selected option as a string

Hidden Job Switchnot supported

In version 2.0.5 we added better logging. Now every boolean evaluation (equation and comparison) is logged. If you are not sure, to which value JWFE evaluates your custom field, just do the following:

  1. Administration -> Logging & Profiling
  2. Configure new logger: com.tng.jira.workflowenhancer.evaluator.types.AbstractGenericValue
  3. Set logging level to debug or below
  4. Now one can see every evaluation and its result in the logs.  

Note that JWFE can change left and right side of the equation/comparison!


[user]Stringusername of the current user
[groups]Stringcomma-separated list of the groups the user belongs to
[roles]Stringcomma-separated list of the project roles the user belongs to
[now]Date valuecurrent date and time
[subtasks#field]Stringcomma-separated list of the values in the subtasks

[subtasks#Summary]=/.*Test.*/  Checks if any Subtaks has a summary that contains "Test"

[subtasks#Status]=/\0133(Done(, Done)*)?\0135/  Checks if all subtasks are in the status "Done". \0133 and \0135 are encoded "[" and "]", as you can't use them in the regex as a literal String



Any String has to be enclosed by " (quotation marks)
"String", "another String"


Any regular expression has to be enclosed by / (forward slashes)


* matches the preceding element zero or more times/a*/ = {ε,a,aa,aaa,aaaa,...}
+ matches the preceding element one or more times/a+/ = {a,aa,aaa,aaaa,...}
? matches the preceding element zero or one time/a?/ = {ε,a}
( ) defines subexpression/(ab)+/ = {ab,abab,abab,ababab,...}

{n} matches the precending element exactly n times

 /a{3}/ = {aaab}
{min, max} matches the precending element at least min and at most max times

/a{2,4}/ = {aa,aaa,aaaa}

/a{1,}/ = /a+/ = {a,aa,aaa,...}

/a{ ,5}/ = {ε,a,aa,aaa,aaaa,aaaaa}

In the examples above ε always stands for the empty word. For example in the case of /a?/ that means that there can be either one "a" or no "a".


Pattern: hh:mm24.12.2012 15:30

Time is optional


The maximal date value is 31.12.2099 23:59.


Labor timespan pattern: n1w n2d n3h n4min , where n1, n2, n3, n4 are non negative integers12w 13d 5h 3min means 12 labor weeks 13 labor days 5 hours and 3 minutes
Real timespan pattern: n1W n2D n3H n4MIN , where n1, n2, n3, n4 are non negative integers12W 13D 5H 3 MIN means 12weeks 13day 5 hours and 3minutes
If a component is 0 it can be omitted0w 5d 3h 0min = 5d 3h
It is not possible to change the orderWrong: 5d 8w Right: 8w 5d

JWFE works with the TimeTracker settings of your JIRA such that a timespan of JIRA is automatically a labor timespan. This also means that a date and a timespan field cannot be added!
If the TimeTracker is disabled, 1 day = 8 hours, 1 week  = 5 days.

So if your JIRA TimeTracker settings are 1 labour day = 24h and 1 labor week = 7 labor days, labor timespan and real timespans are the same. 


Pattern: d+(.d*)? or d*(.d+)?, where d is an integer3.14,  1.61803,  42
Insert negative numbers as a term:0 - 3.14, 0 - 5.24

The JWFE intern float data type works with negative values. But the parser does not support unary operations. 


Boolean operators

AND& (alternatively && or AND)
OR| (alternatively || or OR)

( )

Order operators

Equals= (alternatively ==)
Not equal!=





Arithmetic Operators


Order Operations

The following matrix shows between which values order operations are possible and how they are defined:

StringFloatDateReal TimespanLabor timespanRegEx




Real Timespandefault

Labor Timespandefault


Order operations are possible if the field at the crossing point is not empty. The type of the operation is explained in the legend.

slexicographical comparison based on the Unicode value of each character in the strings

"zoo" >= "a much longer string but with an a at the beginning"

"2 test strings" < "a test string without a number at the beginning"

fusual comparison of numbers4.5 < 42, 7.77 >= 2.2222,
dthe time is considered if and only if both values match the pattern hh:mm

24.12.2012 15:30 = 24.12.2012

24.12.2012 15:30 < 24.12.2012 16:00

tnumber comparison of the timespan values converted to minutes1w > 1min, 1h <= 61min, 1d 1h = 1d 1h

equal if and only if the string matches the regular expression

the other operations are defined as default (see below)

"Bar"= /Ba[a,r]/

/Ba[a,r]/ > "A"

defaultlexicographical comparison after both values have been converted to string

10.10.2000 = "10.10.2000", 10.10.2000 < "a string"

42 = "42.0", "0 a string with a zero at the beginning" < 42

"1w 0d 0h 0min" = 1w, 1w >= "1w 0d 0h 0min"

Arithmetic Operations


The following matrix shows between which values additions are possible and how they are defined:

StringFloatDateReal TimespanLabor TimespanRegEx






Real Timespan

Labor Timespan


Additions are possible if the field at the crossing point is not empty.

sstring concatenation

"An" + "na" = "Anna"

fusual addition of numbers1.5 + 3 = 4.5

usual addition of timespans based on minutes

If the the timespan values don't have the same type (i.e. not both real or both labor) the result has the type of the first operand.

1w 2d 3h + 2w 2d 2h = 3w 4d 5h

1D + 1h = 1D 1H

dThe timespan value is added to the date. If the date has no entered time, hours and minutes don't matter(12.10.2016 + 14H) + 12H = 12.10.2016, 12.10.2016 + 1W 3D = 22.10.2016


The following matrix shows between which values subtractions are possible and how they are defined:

StringFloatDateReal TimespanLabour TimespanRegEx





Real Timespan

dt t 
Labor Timespan


Subtractions are possible if the field at the crossing point is not empty.

(info) Note that substraction of dates is not supported. Use e.g.  {Date A} < {Date B} + 1W   instead of comparing the difference of the dates to a week. 

fusual subtraction of numbers

the subtraction of two timespans gives back the absolute difference based on minutes.

If the the timespan values don't have the same type (i.e. not both real or both labor) the result has the type of the first operand.

8w 1d 3h - 8w 2d 4h 9min = 1d 1h 9min

2h - 1H = 1h

the timespan value is subtracted from the date. If the date has no entered time, hours and minutes don't matter(29.05.2015 - 12H 5MIN) - 12H 5MIN = 29.05.2015, 29.11.2019 - 6D = 23.11.2019