Description

The behaviours functionality allows an administrator to create one more or behaviours. A behaviour defines how fields behave for issues in a given project or issue context. Some examples of behaviours are:

  • Making a field mandatory depending on other data entered on the issue screen (i.e during an issue creation or an issue transition)

  • Making a field read-only dependent on user role or group

  • Doing server-side validation of field data, before the issue screen is submitted

  • Setting a field value dependent on other issue screen data

Once you’ve created the behaviour, apply it to a test project so you can test it works as expected. Then apply it to a real project.

Examples

Setting a default Description

This simple example can be used as a tutorial. Further worked examples can be found in the Recipes section - Behaviours Examples.

To create a new Behaviour. Go the Administration sceen, and click the Behaviours link in the Behaviours section, or press gg or . and type Behaviours.

new behaviour

Click on Fields:

click fields

Click the Create Initialiser link:

click create initialiser

Enter the following in the Script section (leave the first two fields blank):

def desc = getFieldById("description")

def defaultValue = """h2. How to reproduce
    * step 1
    * step 2

    h2. Expected Result

    The widget should appear

    h2. Actual Result

    The widget doesn't appear""".replaceAll(/    /, '')

if (! underlyingIssue?.description) { (1)
    desc.setFormValue(defaultValue)
}
1 don’t overwrite the description if it already exists

Then click on the Update button.

Now click the Add One now link to map this behaviour to a project:

add mapping

Select one or more projects, then click Add Mapping:

create mapping

This is a very simple configuration and should be used to check everything is working.

Create a new issue in the project that you have associated with this behaviour. You should see the default description. (If it doesn’t, see trouble-shooting below).

default desc result

Using a server-side validator to set the Fix Versions required

A common scenario is that, when you mark an issue as resolved with the resolution of Fixed, you want the developer to specify the Fix Version. However, it doesn’t make sense to require a fix version when the resolution is Won’t Fix.

We solve that by using a server-side validator to mark the fix versions field as required, but only when the resolution is Fixed.

Create a new behaviour, or edit your current sample one. Click Add Field, and add the Resolution field.

Our server-side script, when written, will be called the first time this field appears, and any time the user changes it in the dialog.

add field resolution

Now click Add serverside script as we did previously. The script to enter is:

import com.atlassian.jira.issue.resolution.Resolution

def resolutionField = getFieldById("resolution")
def fixVersionsField = getFieldById("fixVersions")

def resolution = resolutionField.getValue() as Resolution

if (resolution.name == "Fixed") {
    fixVersionsField.setRequired(true)
    fixVersionsField.setHidden(false)
}
else {
    fixVersionsField.setRequired(false)
    fixVersionsField.setHidden(true)
}

This example sets the fix versions field to required and shown if the resolution is Fixed, and to optional and hidden if the resolution is anything else.

Now, Resolve an issue. Experiment with changing the resolution value. The fix versions field should change accordingly:

fixed wont fix

A good experiment now would be to modify the script so that instead of hiding the field it’s made read-only. To do, change setHidden to setReadOnly.

If you have created a new behaviour do not forget to map it to a project, or project/issue type combination.
You might want to do something similar whereby if the Duplicate resolution is selected, the Linked Issues field is shown, if there not already a duplicate link for that issue

Live Editing

Using an inline script can be painful as you have to keep clicking buttons and saving. It’s more productive to point to a file, then you can just modify that. It will be reloaded automatically.

script file

Note that if you have a groovy script as opposed to a class, as in the previous examples, the method name should be run.

When configured like this you can modify your code without even leaving the Resolve Issue dialog, let alone doing a page refresh.

The path to the script can be relative to a script root.
Tip for IDE users

If using an IDE you can get code completion by adding the following lines at the beginning of your script:

import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript

@BaseScript FieldBehaviours fieldBehaviours

Hidden Fields

Hidden fields are fields that can be hidden from the REST API and various other methods of retrieving them…​ usage of hidden fields is in beta. Let me know your experiences. A field will only be truly hidden if the behaviour marks it as hidden, and it’s of a hideable type. It’s best to avoid these, and hide fields just for the purpose of focusing end-users attention on the fields that they are interested in, and removing irrelevant fields.

Fields that are marked as hidden will be hidden when the record is viewed, in the issue navigator, and elsewhere. (See below for caveats). To get this behaviour though the field type must be one of the types provided by the plugin, currently only Hideable Free Text Field (unlimited text) and Hideable Text Field (< 255 characters). If you need any other let me know.

As far as I know, this is secure when used properly. However, there is one way where it is possible to get information from a hidden field. If a user suspects that a field has a particular string, and they construct a filter having that parameter, the issue will be returned. Although they won’t see the value, it would confirm that the issue did indeed have that value in its hidden field. If this is a concern set the Searcher to None.

The Change Log value for hidden fields are disabled for hidden fields, for all users.

Converting Normal to Hidden Fields

If you have existing fields that you want to make hideable you can convert the type following the Changing Custom Field Types procedure, using the new keys below.

CF Type

Default Type Key

Hideable Type Key

New Searcher Key

Short Text

com.atlassian.jira.plugin.system.customfieldtypes:textfield

com.onresolve.jira.plugin.Behaviours:hideable-textfield

com.onresolve.jira.plugin.Behaviours:hideable-textsearcher

Unlimited Text

com.atlassian.jira.plugin.system.customfieldtypes:textarea

com.onresolve.jira.plugin.Behaviours:hideable-textarea

com.onresolve.jira.plugin.Behaviours:hideable-textsearcher

It is not actually necessary to reindex as the searcher class is the same (although the key is different).

Example - Setting up a Hidden Field

Create (or convert) a new field of type Hideable Text Field (< 255 characters).

Create a behaviour as in the other examples. Add the above field and then set it to be hidden. Now add an exception to this, and choose project role developers. Apply the behaviour to the project. You should see something like this:

img5

The field will now be hidden for any user who is not in the developers project role of the current project.

It may be helpful to use the JIRA SU plugin when testing schemes based on user name/group/role.

Do not use Shown When type logic. You must use Hidden When or Hidden Except instead.

Troubleshooting

Nothing happens at all

Enable logging (see below) and check the logs.

Limitations

Javascript-based

This relies on client-side javascript. In most environments users are free to disable javascript in their browser, so no good if security is critical. However, my use case is generally to prompt the user that they should be entering another field depending on some condition, so it’s generally good enough for me - no worse off than if you didn’t use this anyway.. If you’ve made a field read-only, you can always look at the history to see if your rules have been subverted.

However, one of the intentions of this plugin is to provide a more structured way for customisation than enter javascript in a field description, so you’re no worse off than if you had used that method.

Bulk Edit

No support for bulk edits, at the moment. This could be added, however, all issues part of the bulk edit would need to have the same behaviour associated for it to be doable.

Latency

The field behaviours are retrieved from the server after the form has loaded in the browser. In my environment this takes approximately 80 ms so is not noticeable by humans. Over the public internet this may be a lot worse, and so the delay in the styling being applied may be appreciable for the users.

Remote API

Due to limitation 1, i.e. JavaScript based, the behaviours are not enforced when using the remote API.

Getting help

If you have any problems, please include in your bug report:

  1. server logs. You can switch these on by using the enable logging link from the Behaviours Admin screen.

behaviours logging

To do so permanently, include these lines in your log4j.properties file:

log4j.category.com.onresolve.jira.groovy = DEBUG, console, filelog
log4j.additivity.com.onresolve.jira.groovy = false
  1. For the problematic behaviour, click Edit, and include the XML snippet you see there.

  2. Description of any custom field types involved, eg their type.