Just a heads up: On March 24, 2025, starting at 4:30pm CDT / 19:30 UTC, the site will be undergoing scheduled maintenance for a few hours. During this time, the site might be unavailable for a short while. Thanks for your patience.

×
Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Require attachment when checkbox custom field contains [value]

Eric Smith
Contributor
February 28, 2019

Im sure this is something simple that im missing, but my google-fu is failing me.

 

I would like to force a user to attach a file when the checkbox custom field "BIP Setup Type" checkbox has "NWEA (Requires Comprehensive Data File (CDF) Upload)" checked. I wrote a behavior but it was a bit clunky so I changed it to a validator off of the Create transition. When I set the following validator, the ticket throws the error regardless if "NWEA (Requires Comprehensive Data File (CDF) Upload)" is checked or not.

import com.atlassian.jira.component.ComponentAccessor

cfValues['BIP Setup Type']*.value.contains("NWEA (Requires Comprehensive Data File (CDF) Upload)") || ComponentAccessor.attachmentManager.getAttachments(issue).size() >= 1

 

 

1 answer

0 votes
Ben Poulson
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 1, 2019
import com.atlassian.jira.component.ComponentAccessor

//split into two seperate variables for readability
def containsVal = //checks the checkbox
def hasAttachments = ComponentAccessor.attachmentManager.getAttachments(issue).size() >= 1
if(containsVal)
{
if(hasAttachments)
{
return true
}
else
{
return false
}
}
else
{
return true
}

//return true being allow, return false being deny

 

I believe there are a couple problems with your original script. Firstly, using ||. || refers to "or", so it would hypothetically allow the ticket to be created if that box was checked regardless of if there was an attachment. I believe the logic in the script above is correct. However, I think the core issue is with the way you are fetching the values from the custom field. I am not sure, but if I had to guess: 

cfValues['BIP Setup Type']*.value

is returning an arraylist rather than than the actual values that are checked- something like

 [true, false, true, true, false]

 So you would have to check the index of that specific item on the list, rather than the list itself. If you could post the output of 

cfValues['BIP Setup Type']*.value

that could help narrow it down. 

Eric Smith
Contributor
March 1, 2019

Thanks for your reply Ben, I got the idea to use || from the following use on Scriptrunners Wiki: https://scriptrunner.adaptavist.com/5.4.47/jira/recipes/workflow/validators/simple-scripted-validators.html. It explains the || as only doing the second half if the first half is true. I am setting it up as a script validator so it should work that way right? In any case, I initially made a full custom script similar to what you have above:

import com.atlassian.jira.component.ComponentAccessor
import com.opensymphony.workflow.InvalidInputException


def customFieldManager = ComponentAccessor.getCustomFieldManager()
def containsField = customFieldManager.getCustomFieldObjectByName("BIP Setup Type")
def containsVal = issue.getCustomFieldValue(containsField)
def hasAttachments = ComponentAccessor.attachmentManager.getAttachments(issue).size()
if(containsVal == "NWEA (Requires Comprehensive Data File (CDF) Attachment)")
{
if(hasAttachments == null)
{
invalidInputException = new InvalidInputException("Please use the Attachements field to add the Comprehensive Data File (CDF) ");
}
else
{
return false
}
}
else
{
return true
}

 

When I run this, I get the below error still, even though I thought I had accounted for the null value:

2019-03-01 15:00:35,042 ERROR [workflow.ScriptWorkflowFunction]: *************************************************************************************
2019-03-01 15:00:35,043 ERROR [workflow.ScriptWorkflowFunction]: Script function failed on issue: null, actionId: 1, file: <inline script>
java.lang.NullPointerException
 at com.atlassian.jira.issue.managers.DefaultAttachmentManager.getStoredAttachments(DefaultAttachmentManager.java:193)
 at com.atlassian.jira.issue.managers.DefaultAttachmentManager.getAttachments(DefaultAttachmentManager.java:187)
 at com.atlassian.jira.issue.AttachmentManager$getAttachments.call(Unknown Source)
 at Script105.run(Script105.groovy:8)

 

 

Any idea why it still fails on null value?

Like Ben Poulson likes this
Ben Poulson
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 1, 2019

@Eric Smith 

 

It explains the || as only doing the second half if the first half is true.

Other way around. It only needs one of the conditions to be true, so if the first condition is, it doesn't bother with the second statement and just proceeds, since both

true || false
and
true || true

resolve to true.

 

Re: the null error,

The exception occurs on line 8, which is this line:

def hasAttachments = ComponentAccessor.attachmentManager.getAttachments(issue).size()

To break it down:

ComponentAccessor.attachmentManager

Returns the attachmentManager object

attachmentManager.getAttachments(issue)

Returns a List object (with each item in the List being an Attachment object). If the issue has no attachments, this returns null.

getAttachments(issue).size()

This is where the issue is. If the issue has no attachments, getAttachments returns null. If you try to access the .size() method of a null object, you get a nullpointerexception. To get around this, put a ? after getAttachments(issue). The ? is called a Null Safe Operator. Here is a StackOverflow post that explains it very well.

getAttachments(issue)?.size()

However, this will still return null (but not crash) if the issue has no attachments. To sum this up into how you turn all of this into a true/false value:

def hasAttachments = ComponentAccessor.attachmentManager.getAttachments(issue)?.size()
if(hasAttachments != null)
{
hasAttachments = true
}
else
{
hasAttachments = false
}

Alternate way of doing the same thing in less lines:

def hasAttachments = (ComponentAccessor.attachmentManager.getAttachments(issue) != null)

 

 

However, I still think the other issue is checking that value in the checkbox field. If you could reply with what shows up in your log files when you include this:

def containsField = customFieldManager.getCustomFieldObjectByName("BIP Setup Type") 
def containsVal = issue.getCustomFieldValue(containsField)
log.error(containsVal.toString())

That might shed some light on how those fields work.

Ben Poulson
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 1, 2019

@Eric Smith 

 

It explains the || as only doing the second half if the first half is true.

Other way around. || only needs one condition to be true, so if the first one is, it doesn't bother evaluating the second condition, since both

true || false

and

true || true

both evaluate to true.

 

It's crashing on this line:

def hasAttachments = ComponentAccessor.attachmentManager.getAttachments(issue).size()

Specifically, it's crashing here:

getAttachments(issue).size()

If the issue has no attachments, getAttachments returns null. If you try to access the .size() method of a null object, you get a NullPointerException.

To get around that, you can just check whether getAttachments returns null (since if it is not null, it is guaranteed to have at least one attachment).

def hasAttachments = (ComponentAccessor.attachmentManager.getAttachments(issue) != null)

 

I still think their may be an issue with how the value from the checkbox is returned. Could you post what shows up in your log file when you add this line?

import com.atlassian.jira.component.ComponentAccessor
import com.opensymphony.workflow.InvalidInputException


def customFieldManager = ComponentAccessor.getCustomFieldManager()
def containsField = customFieldManager.getCustomFieldObjectByName("BIP Setup Type")
def containsVal = issue.getCustomFieldValue(containsField)
log.error("VALUE OF FIELD: ${containsVal.toString()}")//ADD THIS LINE
Eric Smith
Contributor
March 4, 2019

I updated the script to account for the attachment field being null and added the log output:

 

import com.atlassian.jira.component.ComponentAccessor
import com.opensymphony.workflow.InvalidInputException

//split into two separate variables for readability

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def containsField = customFieldManager.getCustomFieldObjectByName("BIP Setup Type")
def containsVal = issue.getCustomFieldValue(containsField)
def hasAttachments = (ComponentAccessor.attachmentManager.getAttachments(issue) == null)
if(containsVal == "NWEA (Requires Comprehensive Data File (CDF) Attachment)")
{
if(hasAttachments)
{
invalidInputException = new InvalidInputException("Please use the Attachements field to add the Comprehensive Data File (CDF) ");
}
else
{
return false
}
}
else
{
return true
}

//return true being allow, return false being deny

log.error("VALUE OF FIELD: ${containsVal.toString()}")//ADD THIS LINE

 

However I still get the following error in the log and nothing else:

2019-03-04 14:45:20,129 http-nio-8080-exec-1 url:/servicedesk/cu...ortal/7/create/146 username:esmith url:/rest/servicede...ortal/7/create/146 username:esmith ERROR esmith 885x85821x1 1agwjrs 10.233.231.29,10.231.220.22 /servicedesk/customer/portal/7/create/146 [c.o.s.jira.workflow.ScriptWorkflowFunction] Script function failed on issue: null, actionId: 1, file: <inline script>
java.lang.NullPointerException
at com.atlassian.jira.issue.managers.DefaultAttachmentManager.getStoredAttachments(DefaultAttachmentManager.java:193)
at com.atlassian.jira.issue.managers.DefaultAttachmentManager.getAttachments(DefaultAttachmentManager.java:187)
at com.atlassian.jira.issue.AttachmentManager$getAttachments.call(Unknown Source)
at Script33.run(Script33.groovy:9)
Like Ben Poulson likes this
Ben Poulson
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 4, 2019

Could you add this to the top of the script (right after the import statements) and post the output?

 

log.error(issue)
Eric Smith
Contributor
March 4, 2019

Looks like the output is the content of the issue value in the checkbox:

 

2019-03-04 16:23:19,721 http-nio-8080-exec-6 url:/servicedesk/cu...ortal/7/create/146 username:esmith url:/rest/servicede...ortal/7/create/146 username:esmith ERROR esmith 983x103730x1 17phabx 10.233.231.29,10.231.220.22 /servicedesk/customer/portal/7/create/146 [c.o.s.jira.workflow.ScriptWorkflowFunction] Test Basic Setup Attachments 125
2019-03-04 16:23:19,722 http-nio-8080-exec-6 url:/servicedesk/cu...ortal/7/create/146 username:esmith url:/rest/servicede...ortal/7/create/146 username:esmith ERROR esmith 983x103730x1 17phabx 10.233.231.29,10.231.220.22 /servicedesk/customer/portal/7/create/146 [c.o.s.jira.workflow.ScriptWorkflowFunction] VALUE OF FIELD: [NWEA (Requires Comprehensive Data File (CDF) Attachment)]
2019-03-04 16:23:19,727 http-nio-8080-exec-6 url:/servicedesk/cu...ortal/7/create/146 username:esmith url:/rest/servicede...ortal/7/create/146 username:esmith ERROR esmith 983x103730x1 17phabx 10.233.231.29,10.231.220.22 /servicedesk/customer/portal/7/create/146 [c.o.s.jira.workflow.ScriptWorkflowFunction] *************************************************************************************
2019-03-04 16:23:19,728 http-nio-8080-exec-6 url:/servicedesk/cu...ortal/7/create/146 username:esmith url:/rest/servicede...ortal/7/create/146 username:esmith ERROR esmith 983x103730x1 17phabx 10.233.231.29,10.231.220.22 /servicedesk/customer/portal/7/create/146 [c.o.s.jira.workflow.ScriptWorkflowFunction] Script function failed on issue: null, actionId: 1, file: <inline script>
java.lang.NullPointerException
at com.atlassian.jira.issue.managers.DefaultAttachmentManager.getStoredAttachments(DefaultAttachmentManager.java:193)
at com.atlassian.jira.issue.managers.DefaultAttachmentManager.getAttachments(DefaultAttachmentManager.java:187)
at com.atlassian.jira.issue.AttachmentManager$getAttachments.call(Unknown Source)
at Script70.run(Script70.groovy:10)
Like Ben Poulson likes this
Ben Poulson
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 4, 2019
def containsVal = issue.getCustomFieldValue(containsField)

needs to be

def containsVal = issue.getCustomFieldValue(containsField)[0]

Since getCustomFieldValue is returning an array. If you try to log the issue variable, what shows up? 

Eric Smith
Contributor
March 5, 2019

When I add the line

 

def containsVal = issue.getCustomFieldValue(containsField)[0]

 

It wont work. I get a red "x". I tried to add it like

 

import com.atlassian.jira.component.ComponentAccessor
import com.opensymphony.workflow.InvalidInputException
log.error(issue)
//split into two seperate variables for readability

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def containsField = customFieldManager.getCustomFieldObjectByName("BIP Setup Type")
//def containsVal = issue.getCustomFieldValue(containsField)
def containsVal = issue.getCustomFieldValue(containsField)
log.error("VALUE OF FIELD: ${containsVal.toString()}")
def hasAttachments = (ComponentAccessor.attachmentManager.getAttachments(issue))
if(containsVal == "NWEA (Requires Comprehensive Data File (CDF) Attachment)")
{
if(hasAttachments != null)
{
return true
}
else
{
invalidInputException = new InvalidInputException("Please use the Attachements field to add the Comprehensive Data File (CDF) ");
}
}
else
{
return true
}

 

Im not sure what you mean by log the variable, I thought the variable in this custom field was the value, aka "NWEA (Requires Comprehensive Data File (CDF) Attachment)"

Like Ben Poulson likes this
Ben Poulson
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 5, 2019

For containsVal, replace

def containsVal = issue.getCustomFieldValue(containsField)

with:

def containsVal = issue.getCustomFieldValue(containsField)[0]

The [0] is indicating the first item in the list (even if the list only contains one item).

 

Im not sure what you mean by log the variable, I thought the variable in this custom field was the value, aka "NWEA (Requires Comprehensive Data File (CDF) Attachment)"

Referring to the actual issue variable itself. You actually already have it in the script in your last reply- log.error(issue). Could you add these two lines above and below it, then test it again and post the log file?

Above:

log.error("VVVVVVVV")

 

Below:

log.error("^^^^^^^^^^")

So where the log.error statement is now, you would have:

log.error("VVVVVVVV")
log.error(issue)
log.error("^^^^^^^^^^")

This doesn't actually accomplish anything in terms of functionality, it just helps us narrow down where the problem is.

Eric Smith
Contributor
March 5, 2019

When I put in the [0] this is what I get:

 

attach_error.jpgAs far as the logging is concerned, I added the requested lines above and below log.error(issue) and here is what I got:

 

2019-03-05 15:25:32,783 http-nio-8080-exec-23 url:/servicedesk/cu...ortal/7/create/146 username:esmith url:/rest/servicede...ortal/7/create/146 username:esmith ERROR esmith 925x84951x1 1avr4db 10.233.231.29,10.231.220.22 /servicedesk/customer/portal/7/create/146 [c.o.s.jira.workflow.ScriptWorkflowFunction] VVVVVVVV
2019-03-05 15:25:32,783 http-nio-8080-exec-23 url:/servicedesk/cu...ortal/7/create/146 username:esmith url:/rest/servicede...ortal/7/create/146 username:esmith ERROR esmith 925x84951x1 1avr4db 10.233.231.29,10.231.220.22 /servicedesk/customer/portal/7/create/146 [c.o.s.jira.workflow.ScriptWorkflowFunction] Test Basic Setup Attachments 11
2019-03-05 15:25:32,783 http-nio-8080-exec-23 url:/servicedesk/cu...ortal/7/create/146 username:esmith url:/rest/servicede...ortal/7/create/146 username:esmith ERROR esmith 925x84951x1 1avr4db 10.233.231.29,10.231.220.22 /servicedesk/customer/portal/7/create/146 [c.o.s.jira.workflow.ScriptWorkflowFunction] ^^^^^^^^^^
2019-03-05 15:25:32,783 http-nio-8080-exec-23 url:/servicedesk/cu...ortal/7/create/146 username:esmith url:/rest/servicede...ortal/7/create/146 username:esmith ERROR esmith 925x84951x1 1avr4db 10.233.231.29,10.231.220.22 /servicedesk/customer/portal/7/create/146 [c.o.s.jira.workflow.ScriptWorkflowFunction] VALUE OF FIELD: [NWEA (Requires Comprehensive Data File (CDF) Attachment)]
2019-03-05 15:25:32,786 http-nio-8080-exec-23 url:/servicedesk/cu...ortal/7/create/146 username:esmith url:/rest/servicede...ortal/7/create/146 username:esmith ERROR esmith 925x84951x1 1avr4db 10.233.231.29,10.231.220.22 /servicedesk/customer/portal/7/create/146 [c.o.s.jira.workflow.ScriptWorkflowFunction] *************************************************************************************
2019-03-05 15:25:32,787 http-nio-8080-exec-23 url:/servicedesk/cu...ortal/7/create/146 username:esmith url:/rest/servicede...ortal/7/create/146 username:esmith ERROR esmith 925x84951x1 1avr4db 10.233.231.29,10.231.220.22 /servicedesk/customer/portal/7/create/146 [c.o.s.jira.workflow.ScriptWorkflowFunction] Script function failed on issue: null, actionId: 1, file: <inline script>
java.lang.NullPointerException
at com.atlassian.jira.issue.managers.DefaultAttachmentManager.getStoredAttachments(DefaultAttachmentManager.java:193)
at com.atlassian.jira.issue.managers.DefaultAttachmentManager.getAttachments(DefaultAttachmentManager.java:187)
at com.atlassian.jira.issue.AttachmentManager$getAttachments.call(Unknown Source)
at Script75.run(Script75.groovy:13)
Like Ben Poulson likes this
Ben Poulson
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 5, 2019

Oh, I see why that wasn't working. Replace

def containsVal = issue.getCustomFieldValue(containsField)

with

def listOfVals = issue.getCustomFieldValue(containsField)
def containsVal = listOfVals[0]

 

 Then replace

def hasAttachments = (ComponentAccessor.attachmentManager.getAttachments(issue))

With

def attachmentManager = ComponentAccessor.getAttachmentManager()
def hasAttachments = (attachmentManager.getAttachments(issue).size() > 0)

I believe that should fix it.

Eric Smith
Contributor
March 5, 2019

Still getting an error when values is [0]. See screenshot:

 

attach_error2.jpg

Ben Poulson
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 6, 2019

Looks like it's being picky about the type of object. To get around it, we can do this:

Replace

def listOfVals = issue.getCustomFieldValue(containsField)
def containsVal = listOfVals[0]

With

def listOfVals = issue.getCustomFieldValue(containsField)
def containsVal = "temp value"
try
{
containsVal = listOfVals[0]
}
catch (Exception e)
{
log.error(e.getStackTrace().toString())
}
log.error("The value is ${containsVal}")
Eric Smith
Contributor
March 7, 2019

Same error, definitely doesnt like the integer at the end:

 

attach_error3.jpg

Ben Poulson
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 15, 2019

Sorry, just saw this, been a busy week. Try changing

def listOfVals = issue.getCustomFieldValue(containsField)

to

ArrayList<> listOfVals = (ArrayList<>) issue.getCustomFieldValue(containsField)
Eric Smith
Contributor
March 15, 2019

Different error, im not sure what you are trying to do with that line:

 

attach_error4.jpg

Suggest an answer

Log in or Sign up to answer